Skip to content

Commit 334a2a2

Browse files
authored
Merge pull request #126 from zhangyongding/master
support oracle
2 parents 18c5787 + 647fbb1 commit 334a2a2

File tree

13 files changed

+465
-25
lines changed

13 files changed

+465
-25
lines changed

args.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,8 @@ func (args *Args) compileArg(buf *stringBuilder, flavor Flavor, values []interfa
247247
fmt.Fprintf(buf, "$%d", len(values)+1)
248248
case SQLServer:
249249
fmt.Fprintf(buf, "@p%d", len(values)+1)
250+
case Oracle:
251+
fmt.Fprintf(buf, ":%d", len(values)+1)
250252
default:
251253
panic(fmt.Errorf("Args.CompileWithFlavor: invalid flavor %v (%v)", flavor, int(flavor)))
252254
}

fieldmapper.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package sqlbuilder
22

33
import (
4+
"reflect"
5+
46
"github.com/huandu/xstrings"
57
)
68

@@ -13,8 +15,19 @@ var (
1315
//
1416
// Field mapper is called only once on a Struct when the Struct is used to create builder for the first time.
1517
DefaultFieldMapper FieldMapperFunc
18+
19+
// DefaultGetAlias is the default alias and dbtag get func
20+
DefaultGetAlias GetAliasFunc
1621
)
1722

23+
func init() {
24+
DefaultGetAlias = func(field *reflect.StructField) (alias string, dbtag string) {
25+
dbtag = field.Tag.Get(DBTag)
26+
alias = dbtag
27+
return
28+
}
29+
}
30+
1831
// FieldMapperFunc is a func to map struct field names to column names,
1932
// which will be used in query as columns.
2033
type FieldMapperFunc func(name string) string
@@ -28,3 +41,6 @@ type FieldMapperFunc func(name string) string
2841
func SnakeCaseMapper(field string) string {
2942
return xstrings.ToSnakeCase(field)
3043
}
44+
45+
// GetAliasFunc is a func to get alias and dbtag
46+
type GetAliasFunc func(field *reflect.StructField) (alias string, dbtag string)

flavor.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const (
1919
CQL
2020
ClickHouse
2121
Presto
22+
Oracle
2223
)
2324

2425
var (
@@ -58,6 +59,8 @@ func (f Flavor) String() string {
5859
return "ClickHouse"
5960
case Presto:
6061
return "Presto"
62+
case Oracle:
63+
return "Oracle"
6164
}
6265

6366
return "<invalid>"
@@ -84,6 +87,8 @@ func (f Flavor) Interpolate(sql string, args []interface{}) (string, error) {
8487
return clickhouseInterpolate(sql, args...)
8588
case Presto:
8689
return prestoInterpolate(sql, args...)
90+
case Oracle:
91+
return oracleInterpolate(sql, args...)
8792
}
8893

8994
return "", ErrInterpolateNotImplemented
@@ -140,7 +145,7 @@ func (f Flavor) Quote(name string) string {
140145
switch f {
141146
case MySQL, ClickHouse:
142147
return fmt.Sprintf("`%s`", name)
143-
case PostgreSQL, SQLServer, SQLite, Presto:
148+
case PostgreSQL, SQLServer, SQLite, Presto, Oracle:
144149
return fmt.Sprintf(`"%s"`, name)
145150
case CQL:
146151
return fmt.Sprintf("'%s'", name)
@@ -152,7 +157,7 @@ func (f Flavor) Quote(name string) string {
152157
// PrepareInsertIgnore prepares the insert builder to build insert ignore SQL statement based on the sql flavor
153158
func (f Flavor) PrepareInsertIgnore(table string, ib *InsertBuilder) {
154159
switch ib.args.Flavor {
155-
case MySQL:
160+
case MySQL, Oracle:
156161
ib.verb = "INSERT IGNORE"
157162

158163
case PostgreSQL:

flavor_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,3 +138,21 @@ func ExampleFlavor_Interpolate_cql() {
138138
// SELECT name FROM user WHERE id = 1234 AND name = 'Charmy Liu'
139139
// <nil>
140140
}
141+
142+
func ExampleFlavor_Interpolate_oracle() {
143+
sb := Oracle.NewSelectBuilder()
144+
sb.Select("name").From("user").Where(
145+
sb.E("id", 1234),
146+
sb.E("name", "Charmy Liu"),
147+
sb.E("enabled", true),
148+
)
149+
sql, args := sb.Build()
150+
query, err := Oracle.Interpolate(sql, args)
151+
152+
fmt.Println(query)
153+
fmt.Println(err)
154+
155+
// Output:
156+
// SELECT name FROM user WHERE id = 1234 AND name = 'Charmy Liu' AND enabled = 1
157+
// <nil>
158+
}

insert.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,37 @@ func (ib *InsertBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{
120120
buf := newStringBuilder()
121121
ib.injection.WriteTo(buf, insertMarkerInit)
122122

123+
if len(ib.values) > 1 && ib.args.Flavor == Oracle {
124+
buf.WriteLeadingString(ib.verb)
125+
buf.WriteString(" ALL")
126+
127+
for _, v := range ib.values {
128+
if len(ib.table) > 0 {
129+
buf.WriteString(" INTO ")
130+
buf.WriteString(ib.table)
131+
}
132+
ib.injection.WriteTo(buf, insertMarkerAfterInsertInto)
133+
if len(ib.cols) > 0 {
134+
buf.WriteLeadingString("(")
135+
buf.WriteString(strings.Join(ib.cols, ", "))
136+
buf.WriteString(")")
137+
138+
ib.injection.WriteTo(buf, insertMarkerAfterCols)
139+
}
140+
141+
buf.WriteLeadingString("VALUES ")
142+
values := make([]string, 0, len(ib.values))
143+
values = append(values, fmt.Sprintf("(%v)", strings.Join(v, ", ")))
144+
buf.WriteString(strings.Join(values, ", "))
145+
}
146+
147+
buf.WriteString(" SELECT 1 from DUAL")
148+
149+
ib.injection.WriteTo(buf, insertMarkerAfterValues)
150+
151+
return ib.args.CompileWithFlavor(buf.String(), flavor, initialArg...)
152+
}
153+
123154
if len(ib.table) > 0 {
124155
buf.WriteLeadingString(ib.verb)
125156
buf.WriteString(" INTO ")

insert_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,22 @@ func ExampleInsertBuilder() {
6565
// [1 Huan Du 1 2 Charmy Liu 1 1234567890]
6666
}
6767

68+
func ExampleInsertBuilder_Oracle() {
69+
ib := Oracle.NewInsertBuilder()
70+
ib.InsertInto("demo.user")
71+
ib.Cols("id", "name", "status")
72+
ib.Values(1, "Huan Du", 1)
73+
ib.Values(2, "Charmy Liu", 1)
74+
75+
sql, args := ib.Build()
76+
fmt.Println(sql)
77+
fmt.Println(args)
78+
79+
// Output:
80+
// INSERT ALL INTO demo.user (id, name, status) VALUES (:1, :2, :3) INTO demo.user (id, name, status) VALUES (:4, :5, :6) SELECT 1 from DUAL
81+
// [1 Huan Du 1 2 Charmy Liu 1]
82+
}
83+
6884
func ExampleInsertBuilder_insertIgnore() {
6985
ib := NewInsertBuilder()
7086
ib.InsertIgnoreInto("demo.user")

0 commit comments

Comments
 (0)