Skip to content
This repository was archived by the owner on Jan 14, 2025. It is now read-only.

Commit 14c5359

Browse files
authored
fix: Support some placeholders (#43)
2 parents f8e328c + 4f684f1 commit 14c5359

17 files changed

+322
-286
lines changed

internal/arcgen/lang/go/dialect.go

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package arcgengo
2+
3+
import (
4+
"strconv"
5+
"strings"
6+
7+
"github.com/kunitsucom/arcgen/internal/config"
8+
)
9+
10+
func columnValuesPlaceholder(columns []string) string {
11+
switch config.Dialect() {
12+
case "mysql", "sqlite3":
13+
// ?, ?, ?, ...
14+
return "?" + strings.Repeat(", ?", len(columns)-1)
15+
case "postgres", "cockroach":
16+
// $1, $2, $3, ...
17+
var s strings.Builder
18+
s.WriteString("$1")
19+
for i := 2; i <= len(columns); i++ {
20+
s.WriteString(", $")
21+
s.WriteString(strconv.Itoa(i))
22+
}
23+
return s.String()
24+
case "spanner":
25+
// @column_1, @column_2, @column_3, ...
26+
var s strings.Builder
27+
s.WriteString("@" + columns[0])
28+
for i := 2; i <= len(columns); i++ {
29+
s.WriteString(", @")
30+
s.WriteString(columns[i-1])
31+
}
32+
return s.String()
33+
case "oracle":
34+
// :column_1, :column_2, :column_3, ...
35+
var s strings.Builder
36+
s.WriteString(":" + columns[0])
37+
for i := 2; i <= len(columns); i++ {
38+
s.WriteString(", :")
39+
s.WriteString(columns[i-1])
40+
}
41+
return s.String()
42+
default:
43+
// ?, ?, ?, ...
44+
return "?" + strings.Repeat(", ?", len(columns)-1)
45+
}
46+
}
47+
48+
//nolint:unparam,cyclop
49+
func whereColumnsPlaceholder(columns []string, op string) string {
50+
switch config.Dialect() {
51+
case "mysql", "sqlite3":
52+
// column1 = ? AND column2 = ? AND column3 = ...
53+
return strings.Join(columns, " = ? "+op+" ") + " = ?"
54+
case "postgres", "cockroach":
55+
// column1 = $1 AND column2 = $2 AND column3 = ...
56+
var s strings.Builder
57+
for i, column := range columns {
58+
if i > 0 {
59+
s.WriteString(" " + op + " ")
60+
}
61+
s.WriteString(column)
62+
s.WriteString(" = $")
63+
s.WriteString(strconv.Itoa(i + 1))
64+
}
65+
return s.String()
66+
case "spanner":
67+
// column1 = @column_1 AND column2 = @column_2 AND column3 = ...
68+
var s strings.Builder
69+
for i, column := range columns {
70+
if i > 0 {
71+
s.WriteString(" " + op + " ")
72+
}
73+
s.WriteString(column)
74+
s.WriteString(" = @")
75+
s.WriteString(column)
76+
}
77+
return s.String()
78+
case "oracle":
79+
// column1 = :column_1 AND column2 = :column_2 AND column3 = ...
80+
var s strings.Builder
81+
for i, column := range columns {
82+
if i > 0 {
83+
s.WriteString(" " + op + " ")
84+
}
85+
s.WriteString(column)
86+
s.WriteString(" = :")
87+
s.WriteString(column)
88+
}
89+
return s.String()
90+
default:
91+
// column1 = ? AND column2 = ? AND column3 = ...
92+
return strings.Join(columns, " = ? "+op+" ") + " = ?"
93+
}
94+
}

internal/arcgen/lang/go/generate.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,15 @@ func generate(arcSrcSetSlice ARCSourceSetSlice) error {
5454
}
5555
}
5656

57-
if config.GenerateGoCRUDPackage() {
57+
if config.GenerateGoORMPackage() {
5858
crudFileExt := ".crud" + genFileExt
5959

6060
crudFiles := make([]string, 0)
6161
for _, arcSrcSet := range arcSrcSetSlice {
6262
// closure for defer
6363
if err := func() error {
6464
filePathWithoutExt := strings.TrimSuffix(filepath.Base(arcSrcSet.Filename), fileExt)
65-
filename := filepath.Join(config.GoCRUDPackagePath(), filePathWithoutExt+crudFileExt)
65+
filename := filepath.Join(config.GoORMPackagePath(), filePathWithoutExt+crudFileExt)
6666
f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, rw_r__r__)
6767
if err != nil {
6868
return errorz.Errorf("os.OpenFile: %w", err)
@@ -84,7 +84,7 @@ func generate(arcSrcSetSlice ARCSourceSetSlice) error {
8484
}
8585

8686
if err := func() error {
87-
filename := filepath.Join(config.GoCRUDPackagePath(), "common"+crudFileExt)
87+
filename := filepath.Join(config.GoORMPackagePath(), "common"+crudFileExt)
8888
f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, rw_r__r__)
8989
if err != nil {
9090
return errorz.Errorf("os.OpenFile: %w", err)

internal/arcgen/lang/go/generate_crud.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func generateCRUDFileContent(buf buffer, arcSrcSet *ARCSourceSet) (string, error
3838
astFile := &ast.File{
3939
// package
4040
Name: &ast.Ident{
41-
Name: config.GoCRUDPackageName(),
41+
Name: config.GoORMPackageName(),
4242
},
4343
// methods
4444
Decls: []ast.Decl{},
@@ -55,7 +55,7 @@ func generateCRUDFileContent(buf buffer, arcSrcSet *ARCSourceSet) (string, error
5555
// "context"
5656
// "fmt"
5757
//
58-
// dao "path/to/your/dao"
58+
// orm "path/to/your/orm"
5959
// )
6060
&ast.GenDecl{
6161
Tok: token.IMPORT,
@@ -67,7 +67,7 @@ func generateCRUDFileContent(buf buffer, arcSrcSet *ARCSourceSet) (string, error
6767
Path: &ast.BasicLit{Kind: token.STRING, Value: strconv.Quote("fmt")},
6868
},
6969
&ast.ImportSpec{
70-
Name: &ast.Ident{Name: "dao"},
70+
Name: &ast.Ident{Name: importName},
7171
Path: &ast.BasicLit{Kind: token.STRING, Value: strconv.Quote(structPackagePath)},
7272
},
7373
},

internal/arcgen/lang/go/generate_crud_common.go

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,17 @@ func fprintCRUDCommon(osFile osFile, buf buffer, arcSrcSetSlice ARCSourceSetSlic
3131
}
3232

3333
const (
34-
sqlQueryerContextVarName = "sqlContext"
35-
sqlQueryerContextTypeName = "sqlQueryerContext"
34+
importName = "orm"
35+
queryerContextVarName = "queryerContext"
36+
queryerContextTypeName = "QueryerContext"
3637
)
3738

3839
//nolint:cyclop,funlen,gocognit,maintidx
3940
func generateCRUDCommonFileContent(buf buffer, arcSrcSetSlice ARCSourceSetSlice, crudFiles []string) (string, error) {
4041
astFile := &ast.File{
4142
// package
4243
Name: &ast.Ident{
43-
Name: config.GoCRUDPackageName(),
44+
Name: config.GoORMPackageName(),
4445
},
4546
// methods
4647
Decls: []ast.Decl{},
@@ -60,7 +61,7 @@ func generateCRUDCommonFileContent(buf buffer, arcSrcSetSlice ARCSourceSetSlice,
6061
// "database/sql"
6162
// "log/slog"
6263
//
63-
// dao "path/to/your/dao"
64+
// orm "path/to/your/orm"
6465
// )
6566
&ast.GenDecl{
6667
Tok: token.IMPORT,
@@ -75,14 +76,14 @@ func generateCRUDCommonFileContent(buf buffer, arcSrcSetSlice ARCSourceSetSlice,
7576
Path: &ast.BasicLit{Kind: token.STRING, Value: strconv.Quote("log/slog")},
7677
},
7778
&ast.ImportSpec{
78-
Name: &ast.Ident{Name: "dao"},
79+
Name: &ast.Ident{Name: importName},
7980
Path: &ast.BasicLit{Kind: token.STRING, Value: strconv.Quote(structPackagePath)},
8081
},
8182
},
8283
},
8384
)
8485

85-
// type sqlQueryerContext interface {
86+
// type QueryerContext interface {
8687
// QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
8788
// QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row
8889
// ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
@@ -93,7 +94,7 @@ func generateCRUDCommonFileContent(buf buffer, arcSrcSetSlice ARCSourceSetSlice,
9394
Specs: []ast.Spec{
9495
&ast.TypeSpec{
9596
// Assign: token.Pos(1),
96-
Name: &ast.Ident{Name: sqlQueryerContextTypeName},
97+
Name: &ast.Ident{Name: queryerContextTypeName},
9798
Type: &ast.InterfaceType{
9899
Methods: &ast.FieldList{
99100
List: []*ast.Field{
@@ -153,7 +154,7 @@ func generateCRUDCommonFileContent(buf buffer, arcSrcSetSlice ARCSourceSetSlice,
153154
Tok: token.TYPE,
154155
Specs: []ast.Spec{
155156
&ast.TypeSpec{
156-
Name: &ast.Ident{Name: config.GoCRUDTypeNameUnexported()},
157+
Name: &ast.Ident{Name: config.GoORMStructName()},
157158
Type: &ast.StructType{Fields: &ast.FieldList{}},
158159
},
159160
},
@@ -221,7 +222,7 @@ func generateCRUDCommonFileContent(buf buffer, arcSrcSetSlice ARCSourceSetSlice,
221222
)
222223

223224
// type CRUD interface {
224-
// Create{StructName}(ctx context.Context, sqlQueryer sqlQueryerContext, s *{Struct}) error
225+
// Create{StructName}(ctx context.Context, queryerContext QueryerContext, s *{Struct}) error
225226
// ...
226227
// }
227228
methods := make([]*ast.Field, 0)
@@ -241,7 +242,7 @@ func generateCRUDCommonFileContent(buf buffer, arcSrcSetSlice ARCSourceSetSlice,
241242
if n.Recv != nil && len(n.Recv.List) > 0 {
242243
if t, ok := n.Recv.List[0].Type.(*ast.StarExpr); ok {
243244
if ident, ok := t.X.(*ast.Ident); ok {
244-
if ident.Name == config.GoCRUDTypeNameUnexported() {
245+
if ident.Name == config.GoORMStructName() {
245246
methods = append(methods, &ast.Field{
246247
Names: []*ast.Ident{{Name: n.Name.Name}},
247248
Type: n.Type,
@@ -261,7 +262,7 @@ func generateCRUDCommonFileContent(buf buffer, arcSrcSetSlice ARCSourceSetSlice,
261262
Tok: token.TYPE,
262263
Specs: []ast.Spec{
263264
&ast.TypeSpec{
264-
Name: &ast.Ident{Name: config.GoCRUDTypeName()},
265+
Name: &ast.Ident{Name: config.GoORMTypeName()},
265266
Type: &ast.InterfaceType{
266267
Methods: &ast.FieldList{List: methods},
267268
},
@@ -275,9 +276,9 @@ func generateCRUDCommonFileContent(buf buffer, arcSrcSetSlice ARCSourceSetSlice,
275276
// }
276277
astFile.Decls = append(astFile.Decls,
277278
&ast.FuncDecl{
278-
Name: &ast.Ident{Name: "New" + config.GoCRUDTypeName()},
279-
Type: &ast.FuncType{Results: &ast.FieldList{List: []*ast.Field{{Type: &ast.Ident{Name: config.GoCRUDTypeName()}}}}},
280-
Body: &ast.BlockStmt{List: []ast.Stmt{&ast.ReturnStmt{Results: []ast.Expr{&ast.UnaryExpr{Op: token.AND, X: &ast.Ident{Name: config.GoCRUDTypeNameUnexported() + "{}"}}}}}},
279+
Name: &ast.Ident{Name: "New" + config.GoORMTypeName()},
280+
Type: &ast.FuncType{Results: &ast.FieldList{List: []*ast.Field{{Type: &ast.Ident{Name: config.GoORMTypeName()}}}}},
281+
Body: &ast.BlockStmt{List: []ast.Stmt{&ast.ReturnStmt{Results: []ast.Expr{&ast.UnaryExpr{Op: token.AND, X: &ast.Ident{Name: config.GoORMStructName() + "{}"}}}}}},
281282
},
282283
)
283284

internal/arcgen/lang/go/generate_crud_create.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ func generateCREATEContent(astFile *ast.File, arcSrcSet *ARCSourceSet) {
1919

2020
// const Create{StructName}Query = `INSERT INTO {table_name} ({column_name1}, {column_name2}) VALUES ($1, $2)`
2121
//
22-
// func (q *query) Create{StructName}(ctx context.Context, queryer sqlQueryerContext, s *{Struct}) error {
22+
// func (q *query) Create{StructName}(ctx context.Context, queryer QueryerContext, s *{Struct}) error {
2323
// LoggerFromContext(ctx).Debug(Create{StructName}Query)
24-
// if _, err := sqlContext.ExecContext(ctx, Create{StructName}Query, s.{ColumnName1}, s.{ColumnName2}); err != nil {
25-
// return fmt.Errorf("sqlContext.ExecContext: %w", err)
24+
// if _, err := queryerContext.ExecContext(ctx, Create{StructName}Query, s.{ColumnName1}, s.{ColumnName2}); err != nil {
25+
// return fmt.Errorf("queryerContext.ExecContext: %w", err)
2626
// }
2727
// return nil
2828
// }
@@ -42,13 +42,13 @@ func generateCREATEContent(astFile *ast.File, arcSrcSet *ARCSourceSet) {
4242
},
4343
},
4444
&ast.FuncDecl{
45-
Recv: &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{{Name: "q"}}, Type: &ast.StarExpr{X: &ast.Ident{Name: config.GoCRUDTypeNameUnexported()}}}}},
45+
Recv: &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{{Name: "q"}}, Type: &ast.StarExpr{X: &ast.Ident{Name: config.GoORMStructName()}}}}},
4646
Name: &ast.Ident{Name: funcName},
4747
Type: &ast.FuncType{
4848
Params: &ast.FieldList{List: []*ast.Field{
4949
{Names: []*ast.Ident{{Name: "ctx"}}, Type: &ast.Ident{Name: "context.Context"}},
50-
{Names: []*ast.Ident{{Name: sqlQueryerContextVarName}}, Type: &ast.Ident{Name: sqlQueryerContextTypeName}},
51-
{Names: []*ast.Ident{{Name: "s"}}, Type: &ast.StarExpr{X: &ast.Ident{Name: "dao." + structName}}},
50+
{Names: []*ast.Ident{{Name: queryerContextVarName}}, Type: &ast.Ident{Name: queryerContextTypeName}},
51+
{Names: []*ast.Ident{{Name: "s"}}, Type: &ast.StarExpr{X: &ast.Ident{Name: importName + "." + structName}}},
5252
}},
5353
Results: &ast.FieldList{List: []*ast.Field{
5454
{Type: &ast.Ident{Name: "error"}},
@@ -67,13 +67,13 @@ func generateCREATEContent(astFile *ast.File, arcSrcSet *ARCSourceSet) {
6767
},
6868
},
6969
&ast.IfStmt{
70-
// if _, err := sqlQueryer.ExecContext(ctx, Create{StructName}Query, s.{ColumnName1}, s.{ColumnName2}); err != nil {
70+
// if _, err := queryerContext.ExecContext(ctx, Create{StructName}Query, s.{ColumnName1}, s.{ColumnName2}); err != nil {
7171
Init: &ast.AssignStmt{
7272
Lhs: []ast.Expr{&ast.Ident{Name: "_"}, &ast.Ident{Name: "err"}},
7373
Tok: token.DEFINE,
7474
Rhs: []ast.Expr{&ast.CallExpr{
7575
Fun: &ast.SelectorExpr{
76-
X: &ast.Ident{Name: sqlQueryerContextVarName},
76+
X: &ast.Ident{Name: queryerContextVarName},
7777
Sel: &ast.Ident{Name: "ExecContext"},
7878
},
7979
Args: append(
@@ -93,10 +93,10 @@ func generateCREATEContent(astFile *ast.File, arcSrcSet *ARCSourceSet) {
9393
// err != nil {
9494
Cond: &ast.BinaryExpr{X: &ast.Ident{Name: "err"}, Op: token.NEQ, Y: &ast.Ident{Name: "nil"}},
9595
Body: &ast.BlockStmt{List: []ast.Stmt{
96-
// return fmt.Errorf("sqlContext.ExecContext: %w", err)
96+
// return fmt.Errorf("queryerContext.ExecContext: %w", err)
9797
&ast.ReturnStmt{Results: []ast.Expr{&ast.CallExpr{
9898
Fun: &ast.SelectorExpr{X: &ast.Ident{Name: "fmt"}, Sel: &ast.Ident{Name: "Errorf"}},
99-
Args: []ast.Expr{&ast.Ident{Name: strconv.Quote(sqlQueryerContextVarName + ".ExecContext: %w")}, &ast.Ident{Name: "err"}},
99+
Args: []ast.Expr{&ast.Ident{Name: strconv.Quote(queryerContextVarName + ".ExecContext: %w")}, &ast.Ident{Name: "err"}},
100100
}}},
101101
}},
102102
},

internal/arcgen/lang/go/generate_crud_delete.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ func generateDELETEContent(astFile *ast.File, arcSrcSet *ARCSourceSet) {
1818

1919
// const Delete{StructName}Query = `DELETE FROM {table_name} WHERE {pk1} = ? [AND {pk2} = ?]`
2020
//
21-
// func (q *query) Delete{StructName}(ctx context.Context, queryer sqlQueryerContext, pk1 pk1type [, pk2 pk2type]) error {
22-
// if _, err := sqlContext.ExecContext(ctx, Delete{StructName}Query, pk1 [, pk2]); err != nil {
23-
// return fmt.Errorf("sqlContext.ExecContext: %w", err)
21+
// func (q *query) Delete{StructName}(ctx context.Context, queryer QueryerContext, pk1 pk1type [, pk2 pk2type]) error {
22+
// if _, err := queryerContext.ExecContext(ctx, Delete{StructName}Query, pk1 [, pk2]); err != nil {
23+
// return fmt.Errorf("queryerContext.ExecContext: %w", err)
2424
// }
2525
// return nil
2626
// }
@@ -47,13 +47,13 @@ func generateDELETEContent(astFile *ast.File, arcSrcSet *ARCSourceSet) {
4747
},
4848
},
4949
&ast.FuncDecl{
50-
Recv: &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{{Name: "q"}}, Type: &ast.StarExpr{X: &ast.Ident{Name: config.GoCRUDTypeNameUnexported()}}}}},
50+
Recv: &ast.FieldList{List: []*ast.Field{{Names: []*ast.Ident{{Name: "q"}}, Type: &ast.StarExpr{X: &ast.Ident{Name: config.GoORMStructName()}}}}},
5151
Name: &ast.Ident{Name: funcName},
5252
Type: &ast.FuncType{
5353
Params: &ast.FieldList{List: append(
5454
[]*ast.Field{
5555
{Names: []*ast.Ident{{Name: "ctx"}}, Type: &ast.Ident{Name: "context.Context"}},
56-
{Names: []*ast.Ident{{Name: sqlQueryerContextVarName}}, Type: &ast.Ident{Name: sqlQueryerContextTypeName}},
56+
{Names: []*ast.Ident{{Name: queryerContextVarName}}, Type: &ast.Ident{Name: queryerContextTypeName}},
5757
},
5858
func() []*ast.Field {
5959
var fields []*ast.Field
@@ -80,13 +80,13 @@ func generateDELETEContent(astFile *ast.File, arcSrcSet *ARCSourceSet) {
8080
},
8181
},
8282
&ast.IfStmt{
83-
// if _, err := sqlContext.ExecContext(ctx, Delete{StructName}Query, pk1 [, pk2]); err != nil {
83+
// if _, err := queryerContext.ExecContext(ctx, Delete{StructName}Query, pk1 [, pk2]); err != nil {
8484
Init: &ast.AssignStmt{
8585
Lhs: []ast.Expr{&ast.Ident{Name: "_"}, &ast.Ident{Name: "err"}},
8686
Tok: token.DEFINE,
8787
Rhs: []ast.Expr{&ast.CallExpr{
8888
Fun: &ast.SelectorExpr{
89-
X: &ast.Ident{Name: sqlQueryerContextVarName},
89+
X: &ast.Ident{Name: queryerContextVarName},
9090
Sel: &ast.Ident{Name: "ExecContext"},
9191
},
9292
Args: append(
@@ -107,10 +107,10 @@ func generateDELETEContent(astFile *ast.File, arcSrcSet *ARCSourceSet) {
107107
// err != nil {
108108
Cond: &ast.BinaryExpr{X: &ast.Ident{Name: "err"}, Op: token.NEQ, Y: &ast.Ident{Name: "nil"}},
109109
Body: &ast.BlockStmt{List: []ast.Stmt{
110-
// return fmt.Errorf("sqlContext.ExecContext: %w", err)
110+
// return fmt.Errorf("queryerContext.ExecContext: %w", err)
111111
&ast.ReturnStmt{Results: []ast.Expr{&ast.CallExpr{
112112
Fun: &ast.SelectorExpr{X: &ast.Ident{Name: "fmt"}, Sel: &ast.Ident{Name: "Errorf"}},
113-
Args: []ast.Expr{&ast.Ident{Name: strconv.Quote(sqlQueryerContextVarName + ".ExecContext: %w")}, &ast.Ident{Name: "err"}},
113+
Args: []ast.Expr{&ast.Ident{Name: strconv.Quote(queryerContextVarName + ".ExecContext: %w")}, &ast.Ident{Name: "err"}},
114114
}}},
115115
}},
116116
},

0 commit comments

Comments
 (0)