Add CQL support (#1)

* Add CQL flavor.

* Add support for CQL argument compilation.

* Adopt substests for interpolation tests.

* Add support for CQL interpolation.

* Add support for CQL blobs.

https://docs.datastax.com/en/cql-oss/3.x/cql/cql_reference/blob_r.html

* Add CQL timestamp interpolation support.

https://docs.datastax.com/en/cql-oss/3.x/cql/cql_reference/timestamp_type_r.html

* Add builder test for CQL.

* Add support for the NOW function.

https://docs.datastax.com/en/cql-oss/3.3/cql/cql_reference/timeuuid_functions_r.html?hl=now

* Add support for CQL update IF statement.

https://docs.datastax.com/en/cql-oss/3.3/cql/cql_reference/cqlUpdate.html#Conditionallyupdatingcolumns

* Drop table prefixes for CQL SELECTs.

* Switch to single quoting for CQL queries.

https://docs.datastax.com/en/cql-oss/3.3/cql/cql_reference/escape_char_r.html

* Update documentation.

* Use valid CQL in tests.

* Support CQL LIMIT.
This commit is contained in:
Spencer Connaughton
2022-09-08 14:39:35 -04:00
committed by GitHub
parent 68495078ea
commit 0f54cd520c
16 changed files with 206 additions and 32 deletions
+39 -5
View File
@@ -1,6 +1,7 @@
package sqlbuilder
import (
"fmt"
"strconv"
"testing"
"time"
@@ -9,7 +10,6 @@ import (
)
func TestFlavorInterpolate(t *testing.T) {
a := assert.New(t)
dt := time.Date(2019, 4, 24, 12, 23, 34, 123456789, time.FixedZone("CST", 8*60*60)) // 2019-04-24 12:23:34.987654321 CST
_, errOutOfRange := strconv.ParseInt("12345678901234567890", 10, 32)
cases := []struct {
@@ -137,13 +137,47 @@ func TestFlavorInterpolate(t *testing.T) {
"SELECT @p1", nil,
"", ErrInterpolateMissingArgs,
},
{
CQL,
"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,
},
{
CQL,
"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,
},
{
CQL,
"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, 0x49276D206279746573, '2019-04-24 12:23:34.123457+0800', '0000-00-00', NULL", nil,
},
{
CQL,
"SELECT '\\'?', \"\\\"?\", `\\`?`, \\?", []interface{}{CQL},
"SELECT '\\'?', \"\\\"?\", `\\`?`, \\'CQL'", nil,
},
{
CQL,
"SELECT ?", nil,
"", ErrInterpolateMissingArgs,
},
{
CQL,
"SELECT ?", []interface{}{complex(1, 2)},
"", ErrInterpolateUnsupportedArgs,
},
}
for idx, c := range cases {
a.Use(&idx, &c)
query, err := c.flavor.Interpolate(c.sql, c.args)
t.Run(fmt.Sprintf("%s: %s", c.flavor.String(), c.query), func(t *testing.T) {
a := assert.New(t)
a.Use(&idx, &c)
query, err := c.flavor.Interpolate(c.sql, c.args)
a.Equal(query, c.query)
a.Assert(err == c.err || err.Error() == c.err.Error())
a.Equal(query, c.query)
a.Assert(err == c.err || err.Error() == c.err.Error())
})
}
}