Skip to content

Commit

Permalink
支持informix
Browse files Browse the repository at this point in the history
  • Loading branch information
maixl committed Mar 19, 2024
1 parent a5eff69 commit 7e50c88
Show file tree
Hide file tree
Showing 10 changed files with 117 additions and 6 deletions.
2 changes: 1 addition & 1 deletion args.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ func (args *Args) compileArg(buf *stringBuilder, flavor Flavor, values []interfa

default:
switch flavor {
case MySQL, SQLite, CQL, ClickHouse, Presto:
case MySQL, SQLite, CQL, ClickHouse, Presto, Informix:
buf.WriteRune('?')
case PostgreSQL:
fmt.Fprintf(buf, "$%d", len(values)+1)
Expand Down
8 changes: 8 additions & 0 deletions builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,19 @@ func ExampleWithFlavor() {
fmt.Println(sql)
fmt.Println(args)

// Explicitly use MySQL as the informix.
sql, args = WithFlavor(Buildf("SELECT * FROM foo WHERE id = %v", 1234), Informix).Build()

fmt.Println(sql)
fmt.Println(args)

// Output:
// SELECT * FROM foo WHERE id = $1
// [1234]
// SELECT * FROM foo WHERE id = ?
// [1234]
// SELECT * FROM foo WHERE id = ?
// [1234]
}

func TestBuildWithPostgreSQL(t *testing.T) {
Expand Down
9 changes: 7 additions & 2 deletions flavor.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const (
ClickHouse
Presto
Oracle
Informix
)

var (
Expand Down Expand Up @@ -61,6 +62,8 @@ func (f Flavor) String() string {
return "Presto"
case Oracle:
return "Oracle"
case Informix:
return "Informix"
}

return "<invalid>"
Expand Down Expand Up @@ -89,6 +92,8 @@ func (f Flavor) Interpolate(sql string, args []interface{}) (string, error) {
return prestoInterpolate(sql, args...)
case Oracle:
return oracleInterpolate(sql, args...)
case Informix:
return informixInterpolate(sql, args...)
}

return "", ErrInterpolateNotImplemented
Expand Down Expand Up @@ -145,7 +150,7 @@ func (f Flavor) Quote(name string) string {
switch f {
case MySQL, ClickHouse:
return fmt.Sprintf("`%s`", name)
case PostgreSQL, SQLServer, SQLite, Presto, Oracle:
case PostgreSQL, SQLServer, SQLite, Presto, Oracle, Informix:
return fmt.Sprintf(`"%s"`, name)
case CQL:
return fmt.Sprintf("'%s'", name)
Expand All @@ -171,7 +176,7 @@ func (f Flavor) PrepareInsertIgnore(table string, ib *InsertBuilder) {
// see https://www.sqlite.org/lang_insert.html
ib.verb = "INSERT OR IGNORE"

case ClickHouse, CQL, SQLServer, Presto:
case ClickHouse, CQL, SQLServer, Presto, Informix:
// All other databases do not support insert ignore
ib.verb = "INSERT"

Expand Down
19 changes: 19 additions & 0 deletions flavor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func TestFlavor(t *testing.T) {
CQL: "CQL",
ClickHouse: "ClickHouse",
Oracle: "Oracle",
Informix: "Informix",
}

for f, expected := range cases {
Expand Down Expand Up @@ -159,3 +160,21 @@ func ExampleFlavor_Interpolate_oracle() {
// SELECT name FROM user WHERE id = 1234 AND name = 'Charmy Liu' AND enabled = 1
// <nil>
}

func ExampleFlavor_Interpolate_infomix() {
sb := Informix.NewSelectBuilder()
sb.Select("name").From("user").Where(
sb.NE("id", 1234),
sb.E("name", "Charmy Liu"),
sb.E("enabled", true),
)
sql, args := sb.Build()
query, err := Informix.Interpolate(sql, args)

fmt.Println(query)
fmt.Println(err)

// Output:
// SELECT name FROM user WHERE id <> 1234 AND name = 'Charmy Liu' AND enabled = TRUE
// <nil>
}
16 changes: 16 additions & 0 deletions insert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,22 @@ func ExampleInsertBuilder_subSelect_oracle() {
// [1]
}

func ExampleInsertBuilder_subSelect_informix() {
ib := Informix.NewInsertBuilder()
ib.InsertInto("demo.user")
ib.Cols("id", "name")
sb := ib.Select("id", "name").From("demo.test")
sb.Where(sb.EQ("id", 1))

sql, args := ib.Build()
fmt.Println(sql)
fmt.Println(args)

// Output:
// INSERT INTO demo.user (id, name) SELECT id, name FROM demo.test WHERE id = :1
// [1]
}

func ExampleInsertBuilder_NumValue() {
ib := NewInsertBuilder()
ib.InsertInto("demo.user")
Expand Down
9 changes: 9 additions & 0 deletions interpolate.go
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,10 @@ func prestoInterpolate(query string, args ...interface{}) (string, error) {
return mysqlLikeInterpolate(Presto, query, args...)
}

func informixInterpolate(query string, args ...interface{}) (string, error) {
return mysqlLikeInterpolate(Informix, query, args...)
}

// oraclelInterpolate parses query and replace all ":*" with encoded args.
// If there are more ":*" than len(args), returns ErrMissingArgs.
// Otherwise, if there are less ":*" than len(args), the redundant args are omitted.
Expand Down Expand Up @@ -612,6 +616,9 @@ func encodeValue(buf []byte, arg interface{}, flavor Flavor) ([]byte, error) {
buf = append(buf, v.Format("2006-01-02 15:04:05.999999")...)
buf = append(buf, "', 'YYYY-MM-DD HH24:MI:SS.FF')"...)

case Informix:
buf = append(buf, v.Format("'2006-01-02 15:04:05.999999'")...)

}

case fmt.Stringer:
Expand Down Expand Up @@ -734,6 +741,8 @@ func encodeValue(buf []byte, arg interface{}, flavor Flavor) ([]byte, error) {
buf = append(buf, "hextoraw('"...)
buf = appendHex(buf, data)
buf = append(buf, "')"...)
default:
return nil, ErrInterpolateUnsupportedArgs
}

default:
Expand Down
47 changes: 47 additions & 0 deletions interpolate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,53 @@ func TestFlavorInterpolate(t *testing.T) {
"SELECT :12345678901234567890", nil,
"", errOutOfRange,
},
{
Informix,
"SELECT * FROM a WHERE name = ? AND state IN (?, ?, ?, ?, ?)", []interface{}{"I'm fine", 42, int8(8), int16(-16), int32(32), int64(64)},
"SELECT * FROM a WHERE name = 'I\\'m fine' AND state IN (42, 8, -16, 32, 64)", nil,
},
{
Informix,
"SELECT * FROM `a?` WHERE name = \"?\" AND state IN (?, '?', ?, ?, ?, ?, ?)", []interface{}{"\r\n\b\t\x1a\x00\\\"'", uint(42), uint8(8), uint16(16), uint32(32), uint64(64), "useless"},
"SELECT * FROM `a?` WHERE name = \"?\" AND state IN ('\\r\\n\\b\\t\\Z\\0\\\\\\\"\\'', '?', 42, 8, 16, 32, 64)", nil,
},
{
Informix,
"SELECT ?, ?, ?, ?, ?, ?, ?, ?, ?", []interface{}{true, false, float32(1.234567), float64(9.87654321), []byte(nil), []byte("I'm bytes"), dt, time.Time{}, nil},
// "SELECT TRUE, FALSE, 1.234567, 9.87654321, NULL, _binary'I\\'m bytes', '2019-04-24 12:23:34.123457', '0000-00-00', NULL", nil,
"", ErrInterpolateUnsupportedArgs,
},
{
Informix,
"SELECT '\\'?', \"\\\"?\", `\\`?`, \\?", []interface{}{Informix},
"SELECT '\\'?', \"\\\"?\", `\\`?`, \\'Informix'", nil,
},
{
Informix,
"SELECT ?", []interface{}{byteArr},
// "SELECT _binary'foo'", nil,
"", ErrInterpolateUnsupportedArgs,
},
{
Informix,
"SELECT ?", nil,
"", ErrInterpolateMissingArgs,
},
{
Informix,
"SELECT ?", []interface{}{complex(1, 2)},
"", ErrInterpolateUnsupportedArgs,
},
{
Informix,
"SELECT ?", []interface{}{[]complex128{complex(1, 2)}},
"", ErrInterpolateUnsupportedArgs,
},
{
Informix,
"SELECT ?", []interface{}{errorValuer(1)},
"", ErrErrorValuer,
},
}

for idx, c := range cases {
Expand Down
2 changes: 1 addition & 1 deletion select.go
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ func (sb *SelectBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{
}

switch flavor {
case MySQL, SQLite, ClickHouse:
case MySQL, SQLite, ClickHouse, Informix:
if sb.limit >= 0 {
buf.WriteLeadingString("LIMIT ")
buf.WriteString(strconv.Itoa(sb.limit))
Expand Down
9 changes: 8 additions & 1 deletion select_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ func ExampleSelectBuilder_join() {
}

func ExampleSelectBuilder_limit_offset() {
flavors := []Flavor{MySQL, PostgreSQL, SQLite, SQLServer, CQL, ClickHouse, Presto, Oracle}
flavors := []Flavor{MySQL, PostgreSQL, SQLite, SQLServer, CQL, ClickHouse, Presto, Oracle, Informix}
results := make([][]string, len(flavors))
sb := NewSelectBuilder()
saveResults := func() {
Expand Down Expand Up @@ -233,6 +233,13 @@ func ExampleSelectBuilder_limit_offset() {
// #3: SELECT * FROM ( SELECT ROWNUM r, * FROM ( SELECT * FROM user ) user ) WHERE r BETWEEN 1 AND 1
// #4: SELECT * FROM ( SELECT ROWNUM r, * FROM ( SELECT * FROM user ) user ) WHERE r BETWEEN 1 AND 1
// #5: SELECT * FROM ( SELECT ROWNUM r, * FROM ( SELECT * FROM user ORDER BY id ) user ) WHERE r BETWEEN 2 AND 2
//
// Informix
// #1: SELECT * FROM user
// #2: SELECT * FROM user
// #3: SELECT * FROM user LIMIT 1 OFFSET 0
// #4: SELECT * FROM user LIMIT 1
// #5: SELECT * FROM user ORDER BY id LIMIT 1 OFFSET 1
}

func ExampleSelectBuilder_ForUpdate() {
Expand Down
2 changes: 1 addition & 1 deletion union.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ func (ub *UnionBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{}

}

if MySQL == flavor && ub.limit >= 0 || PostgreSQL == flavor {
if ((MySQL == flavor || Informix == flavor) && ub.limit >= 0) || PostgreSQL == flavor {
if ub.offset >= 0 {
buf.WriteLeadingString("OFFSET ")
buf.WriteString(strconv.Itoa(ub.offset))
Expand Down

0 comments on commit 7e50c88

Please sign in to comment.