diff --git a/catalog/comment.go b/catalog/comment.go index 0ad9f923..d9f47cfc 100644 --- a/catalog/comment.go +++ b/catalog/comment.go @@ -13,8 +13,6 @@ type Comment[T any] struct { Meta T `json:"meta,omitempty"` // extra information, e.g. the original MySQL column type, etc. } -const ManagedCommentPrefix = "base64:" - func DecodeComment[T any](encodedOrRawText string) *Comment[T] { if !strings.HasPrefix(encodedOrRawText, ManagedCommentPrefix) { return NewComment[T](encodedOrRawText) diff --git a/catalog/constants.go b/catalog/constants.go new file mode 100644 index 00000000..05768326 --- /dev/null +++ b/catalog/constants.go @@ -0,0 +1,8 @@ +package catalog + +const ( + // ManagedCommentPrefix is the prefix for comments that are managed by the catalog. + ManagedCommentPrefix = "base64:" + // SequenceNamePrefix is the prefix for sequence names that are managed by the catalog. + SequenceNamePrefix = "__sys_table_seq_" +) diff --git a/catalog/database.go b/catalog/database.go index 500e12d7..dac6fa79 100644 --- a/catalog/database.go +++ b/catalog/database.go @@ -10,6 +10,8 @@ import ( "github.com/apecloud/myduckserver/configuration" "github.com/apecloud/myduckserver/mycontext" "github.com/dolthub/go-mysql-server/sql" + "github.com/google/uuid" + "github.com/sirupsen/logrus" ) type Database struct { @@ -120,6 +122,8 @@ func (d *Database) createAllTable(ctx *sql.Context, name string, schema sql.Prim fullTableName = FullTableName(d.catalog, d.name, name) } + var sequenceName, fullSequenceName string + for _, col := range schema.Schema { typ, err := DuckdbDataType(col.Type) if err != nil { @@ -133,11 +137,30 @@ func (d *Database) createAllTable(ctx *sql.Context, name string, schema sql.Prim } if col.Default != nil { - columnDefault, err := typ.mysql.withDefault(col.Default.String()) + typ.mysql.Default = col.Default.String() + defaultExpr, err := parseDefaultValue(typ.mysql.Default) + if err != nil { + return err + } + colDef += " DEFAULT " + defaultExpr + } else if col.AutoIncrement { + typ.mysql.AutoIncrement = true + + // Generate a random sequence name. + // TODO(fan): Drop the sequence when the table is dropped or the column is removed. + uuid, err := uuid.NewRandom() if err != nil { return err } - colDef += " DEFAULT " + columnDefault + sequenceName = SequenceNamePrefix + uuid.String() + if temporary { + fullSequenceName = `temp.main."` + sequenceName + `"` + } else { + fullSequenceName = InternalSchemas.SYS.Schema + `."` + sequenceName + `"` + } + + defaultExpr := `nextval('` + fullSequenceName + `')` + colDef += " DEFAULT " + defaultExpr } columns = append(columns, colDef) @@ -158,6 +181,20 @@ func (d *Database) createAllTable(ctx *sql.Context, name string, schema sql.Prim } var b strings.Builder + b.Grow(256) + + if sequenceName != "" { + b.WriteString(`CREATE `) + if temporary { + b.WriteString(`TEMP SEQUENCE "`) + b.WriteString(sequenceName) + b.WriteString(`"`) + } else { + b.WriteString(`SEQUENCE `) + b.WriteString(fullSequenceName) + } + b.WriteString(`;`) + } if temporary { b.WriteString(fmt.Sprintf(`CREATE TEMP TABLE %s (%s`, name, strings.Join(columns, ", "))) @@ -180,10 +217,11 @@ func (d *Database) createAllTable(ctx *sql.Context, name string, schema sql.Prim b.WriteString(")") // Add comment to the table + info := ExtraTableInfo{schema.PkOrdinals, withoutIndex, fullSequenceName} b.WriteString(fmt.Sprintf( "; COMMENT ON TABLE %s IS '%s'", fullTableName, - NewCommentWithMeta(comment, ExtraTableInfo{schema.PkOrdinals, withoutIndex}).Encode(), + NewCommentWithMeta(comment, info).Encode(), )) // Add column comments @@ -192,7 +230,13 @@ func (d *Database) createAllTable(ctx *sql.Context, name string, schema sql.Prim b.WriteString(s) } - _, err := adapter.Exec(ctx, b.String()) + ddl := b.String() + + if logger := ctx.GetLogger(); logger.Logger.GetLevel() >= logrus.DebugLevel { + logger.WithField("DuckSQL", ddl).Debug("Executing DDL") + } + + _, err := adapter.Exec(ctx, ddl) if err != nil { if IsDuckDBTableAlreadyExistsError(err) { return sql.ErrTableAlreadyExists.New(name) diff --git a/catalog/internal_schemas.go b/catalog/internal_schemas.go index f169bc21..daf68b5f 100644 --- a/catalog/internal_schemas.go +++ b/catalog/internal_schemas.go @@ -5,13 +5,17 @@ type InternalSchema struct { } var InternalSchemas = struct { + SYS InternalSchema MySQL InternalSchema }{ + SYS: InternalSchema{ + Schema: "__sys__", + }, MySQL: InternalSchema{ Schema: "mysql", }, } var internalSchemas = []InternalSchema{ - InternalSchemas.MySQL, + InternalSchemas.MySQL, InternalSchemas.SYS, } diff --git a/catalog/table.go b/catalog/table.go index 3cc4936d..845e33aa 100644 --- a/catalog/table.go +++ b/catalog/table.go @@ -3,6 +3,7 @@ package catalog import ( stdsql "database/sql" "fmt" + "strconv" "strings" "sync" @@ -25,6 +26,7 @@ type Table struct { type ExtraTableInfo struct { PkOrdinals []int Replicated bool + Sequence string } type ColumnInfo struct { @@ -51,6 +53,7 @@ var _ sql.DeletableTable = (*Table)(nil) var _ sql.TruncateableTable = (*Table)(nil) var _ sql.ReplaceableTable = (*Table)(nil) var _ sql.CommentedTable = (*Table)(nil) +var _ sql.AutoIncrementTable = (*Table)(nil) func NewTable(name string, db *Database) *Table { return &Table{ @@ -132,6 +135,7 @@ func getPKSchema(ctx *sql.Context, catalogName, dbName, tableName string) sql.Pr Source: tableName, DatabaseSource: dbName, Default: defaultValue, + AutoIncrement: decodedComment.Meta.AutoIncrement, Comment: decodedComment.Text, } @@ -201,11 +205,12 @@ func (t *Table) AddColumn(ctx *sql.Context, column *sql.Column, order *sql.Colum } if column.Default != nil { - columnDefault, err := typ.mysql.withDefault(column.Default.String()) + typ.mysql.Default = column.Default.String() + defaultExpr, err := parseDefaultValue(typ.mysql.Default) if err != nil { return err } - sql += fmt.Sprintf(" DEFAULT %s", columnDefault) + sql += " DEFAULT " + defaultExpr } // add comment @@ -257,11 +262,12 @@ func (t *Table) ModifyColumn(ctx *sql.Context, columnName string, column *sql.Co } if column.Default != nil { - columnDefault, err := typ.mysql.withDefault(column.Default.String()) + typ.mysql.Default = column.Default.String() + defaultExpr, err := parseDefaultValue(typ.mysql.Default) if err != nil { return err } - sqls = append(sqls, fmt.Sprintf(`%s SET DEFAULT %s`, baseSQL, columnDefault)) + sqls = append(sqls, fmt.Sprintf(`%s SET DEFAULT %s`, baseSQL, defaultExpr)) } else { sqls = append(sqls, fmt.Sprintf(`%s DROP DEFAULT`, baseSQL)) } @@ -578,3 +584,88 @@ func queryColumns(ctx *sql.Context, catalogName, schemaName, tableName string) ( func (t *IndexedTable) LookupPartitions(ctx *sql.Context, lookup sql.IndexLookup) (sql.PartitionIter, error) { return nil, fmt.Errorf("unimplemented(LookupPartitions) (table: %s, query: %s)", t.name, ctx.Query()) } + +// PeekNextAutoIncrementValue implements sql.AutoIncrementTable. +func (t *Table) PeekNextAutoIncrementValue(ctx *sql.Context) (uint64, error) { + if t.comment.Meta.Sequence == "" { + return 0, sql.ErrNoAutoIncrementCol + } + + // For PeekNextAutoIncrementValue, we want to see what the next value would be + // without actually incrementing. We can do this by getting currval + 1. + var val uint64 + err := adapter.QueryRowCatalog(ctx, `SELECT currval('`+t.comment.Meta.Sequence+`') + 1`).Scan(&val) + if err != nil { + return 0, ErrDuckDB.New(err) + } + + return val, nil +} + +// GetNextAutoIncrementValue implements sql.AutoIncrementTable. +func (t *Table) GetNextAutoIncrementValue(ctx *sql.Context, insertVal interface{}) (uint64, error) { + if t.comment.Meta.Sequence == "" { + return 0, sql.ErrNoAutoIncrementCol + } + + // If insertVal is provided and greater than current sequence value, update sequence + if insertVal != nil { + var start uint64 + switch v := insertVal.(type) { + case uint64: + start = v + case int64: + if v > 0 { + start = uint64(v) + } + } + if start > 0 { + err := t.setAutoIncrementValue(ctx, start) + if err != nil { + return 0, err + } + return start, nil + } + } + + // Get next value from sequence + var val uint64 + err := adapter.QueryRowCatalog(ctx, `SELECT nextval('`+t.comment.Meta.Sequence+`')`).Scan(&val) + if err != nil { + return 0, ErrDuckDB.New(err) + } + + return val, nil +} + +// AutoIncrementSetter implements sql.AutoIncrementTable. +func (t *Table) AutoIncrementSetter(ctx *sql.Context) sql.AutoIncrementSetter { + if t.comment.Meta.Sequence == "" { + return nil + } + return &autoIncrementSetter{t: t} +} + +// setAutoIncrementValue is a helper function to update the sequence value +func (t *Table) setAutoIncrementValue(ctx *sql.Context, value uint64) error { + _, err := adapter.ExecCatalog(ctx, `CREATE OR REPLACE SEQUENCE `+t.comment.Meta.Sequence+` START WITH `+strconv.FormatUint(value, 10)) + return err +} + +// autoIncrementSetter implements the AutoIncrementSetter interface +type autoIncrementSetter struct { + t *Table +} + +func (s *autoIncrementSetter) SetAutoIncrementValue(ctx *sql.Context, value uint64) error { + return s.t.setAutoIncrementValue(ctx, value) +} + +func (s *autoIncrementSetter) Close(ctx *sql.Context) error { + return nil +} + +func (s *autoIncrementSetter) AcquireAutoIncrementLock(ctx *sql.Context) (func(), error) { + // DuckDB handles sequence synchronization internally + return func() {}, nil +} diff --git a/catalog/type_mapping.go b/catalog/type_mapping.go index 548ce6e3..6a6266ec 100644 --- a/catalog/type_mapping.go +++ b/catalog/type_mapping.go @@ -29,15 +29,16 @@ func (t AnnotatedDuckType) MySQL() MySQLType { } type MySQLType struct { - Name string - Length uint32 `json:",omitempty"` - Precision uint8 `json:",omitempty"` - Scale uint8 `json:",omitempty"` - Unsigned bool `json:",omitempty"` - Display uint8 `json:",omitempty"` // Display width for integer types - Collation uint16 `json:",omitempty"` // For string types - Values []string `json:",omitempty"` // For ENUM and SET - Default string `json:",omitempty"` // Default value of column + Name string + Length uint32 `json:",omitempty"` + Precision uint8 `json:",omitempty"` + Scale uint8 `json:",omitempty"` + Unsigned bool `json:",omitempty"` + Display uint8 `json:",omitempty"` // Display width for integer types + Collation uint16 `json:",omitempty"` // For string types + Values []string `json:",omitempty"` // For ENUM and SET + Default string `json:",omitempty"` // Default value of column + AutoIncrement bool `json:",omitempty"` // Auto increment flag } func newCommonType(name string) AnnotatedDuckType { @@ -316,9 +317,8 @@ func mysqlDataType(duckType AnnotatedDuckType, numericPrecision uint8, numericSc } } -func (typ *MySQLType) withDefault(defaultValue string) (string, error) { - typ.Default = defaultValue - parsed, err := sqlparser.Parse(fmt.Sprintf("SELECT %s", defaultValue)) +func parseDefaultValue(defaultValue string) (string, error) { + parsed, err := sqlparser.Parse("SELECT " + defaultValue) if err != nil { return "", err } diff --git a/go.mod b/go.mod index 770fec3d..9fd48c52 100644 --- a/go.mod +++ b/go.mod @@ -12,13 +12,12 @@ require ( github.com/aws/aws-sdk-go-v2/credentials v1.17.30 github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.15 github.com/aws/aws-sdk-go-v2/service/s3 v1.60.1 - github.com/aws/smithy-go v1.20.4 github.com/cockroachdb/apd/v3 v3.2.1 github.com/cockroachdb/cockroachdb-parser v0.23.2 github.com/cockroachdb/errors v1.9.0 github.com/dolthub/doltgresql v0.13.0 - github.com/dolthub/go-mysql-server v0.18.2-0.20241127000145-a1809677932e - github.com/dolthub/vitess v0.0.0-20241126223332-cd8f828f26ac + github.com/dolthub/go-mysql-server v0.18.2-0.20241215013221-68ab2c34608f + github.com/dolthub/vitess v0.0.0-20241211024425-b00987f7ba54 github.com/go-sql-driver/mysql v1.8.1 github.com/google/uuid v1.6.0 github.com/jackc/pglogrepl v0.0.0-20240307033717-828fbfe908e9 @@ -37,8 +36,8 @@ require ( ) replace ( - github.com/dolthub/go-mysql-server v0.18.2-0.20241127000145-a1809677932e => github.com/apecloud/go-mysql-server v0.0.0-20241127073935-94c04f2f750d - github.com/dolthub/vitess v0.0.0-20241126223332-cd8f828f26ac => github.com/apecloud/dolt-vitess v0.0.0-20241127063501-5c7c985f0e57 + github.com/dolthub/go-mysql-server v0.18.2-0.20241215013221-68ab2c34608f => github.com/apecloud/go-mysql-server v0.0.0-20241217030038-1ec40b6e7e7f + github.com/dolthub/vitess v0.0.0-20241211024425-b00987f7ba54 => github.com/apecloud/dolt-vitess v0.0.0-20241217030333-e641a5d88d61 github.com/marcboeker/go-duckdb v1.8.3 => github.com/apecloud/go-duckdb v0.0.0-20241127093618-047c1a233928 ) @@ -59,6 +58,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/sso v1.22.5 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.30.5 // indirect + github.com/aws/smithy-go v1.20.4 // indirect github.com/bazelbuild/rules_go v0.46.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/biogo/store v0.0.0-20201120204734-aad293a2328f // indirect @@ -69,7 +69,7 @@ require ( github.com/dave/dst v0.27.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dolthub/flatbuffers/v23 v23.3.3-dh.2 // indirect - github.com/dolthub/go-icu-regex v0.0.0-20240916130659-0118adc6b662 // indirect + github.com/dolthub/go-icu-regex v0.0.0-20241215010122-db690dd53c90 // indirect github.com/dolthub/jsonpath v0.0.2-0.20240227200619-19675ab05c71 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/getsentry/sentry-go v0.12.0 // indirect @@ -111,7 +111,7 @@ require ( github.com/rs/xid v1.5.0 // indirect github.com/sasha-s/go-deadlock v0.3.1 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/tetratelabs/wazero v1.1.0 // indirect + github.com/tetratelabs/wazero v1.8.2 // indirect github.com/twpayne/go-geom v1.4.1 // indirect github.com/twpayne/go-kml v1.5.2 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect diff --git a/go.sum b/go.sum index 52f0a392..d8bd5f8f 100644 --- a/go.sum +++ b/go.sum @@ -49,12 +49,12 @@ github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.21.0 h1:tdPmh/ptjE1IJnhbhrcl2++TauVjy242rkV/UzJChnE= github.com/apache/thrift v0.21.0/go.mod h1:W1H8aR/QRtYNvrPeFXBtobyRkd0/YVhTc6i07XIAgDw= -github.com/apecloud/dolt-vitess v0.0.0-20241127063501-5c7c985f0e57 h1:djc1asm2fLvAwY9LKT4Jz8jzGkZQv0DH+WiUIyIEz3A= -github.com/apecloud/dolt-vitess v0.0.0-20241127063501-5c7c985f0e57/go.mod h1:alcJgfdyIhFaAiYyEmuDCFSLCzedz3KCaIclLoCUtJg= +github.com/apecloud/dolt-vitess v0.0.0-20241217030333-e641a5d88d61 h1:R91iftRDONaExzXlbMLGS+BMZfk3e/J51YW62155WK4= +github.com/apecloud/dolt-vitess v0.0.0-20241217030333-e641a5d88d61/go.mod h1:1gQZs/byeHLMSul3Lvl3MzioMtOW1je79QYGyi2fd70= github.com/apecloud/go-duckdb v0.0.0-20241127093618-047c1a233928 h1:uI/JM1iflKvc/u4SusP5V9EB4VMud7+YFlUK5xe6RcE= github.com/apecloud/go-duckdb v0.0.0-20241127093618-047c1a233928/go.mod h1:C9bYRE1dPYb1hhfu/SSomm78B0FXmNgRvv6YBW/Hooc= -github.com/apecloud/go-mysql-server v0.0.0-20241127073935-94c04f2f750d h1:qyupLWM3sncs2fgIekV8yBKPXNvvCunHKYL8cEDTIpI= -github.com/apecloud/go-mysql-server v0.0.0-20241127073935-94c04f2f750d/go.mod h1:QdaXQKE8XFwM4P1yN14m2eydx4V2xyuqpQp4tmNoXzQ= +github.com/apecloud/go-mysql-server v0.0.0-20241217030038-1ec40b6e7e7f h1:Nn7HEMLNxRaDlsG4o1P484NJ6H3jSjKN0jdXujDIOno= +github.com/apecloud/go-mysql-server v0.0.0-20241217030038-1ec40b6e7e7f/go.mod h1:elfIatfq2fkU5lqTBrTcpL0RcHZOgYPE8EzBD7yQFiY= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= @@ -175,8 +175,8 @@ github.com/dolthub/doltgresql v0.13.0 h1:pqySzZgabDH5YZQh5Ji+MynaTSaE7H4SY9+RD5c github.com/dolthub/doltgresql v0.13.0/go.mod h1:7SoMEKxcl3/MQSX3Q88/MnUNV+C5eK4U5A9kyKZnLiI= github.com/dolthub/flatbuffers/v23 v23.3.3-dh.2 h1:u3PMzfF8RkKd3lB9pZ2bfn0qEG+1Gms9599cr0REMww= github.com/dolthub/flatbuffers/v23 v23.3.3-dh.2/go.mod h1:mIEZOHnFx4ZMQeawhw9rhsj+0zwQj7adVsnBX7t+eKY= -github.com/dolthub/go-icu-regex v0.0.0-20240916130659-0118adc6b662 h1:aC17hZD6iwzBwwfO5M+3oBT5E5gGRiQPdn+vzpDXqIA= -github.com/dolthub/go-icu-regex v0.0.0-20240916130659-0118adc6b662/go.mod h1:KPUcpx070QOfJK1gNe0zx4pA5sicIK1GMikIGLKC168= +github.com/dolthub/go-icu-regex v0.0.0-20241215010122-db690dd53c90 h1:Sni8jrP0sy/w9ZYXoff4g/ixe+7bFCZlfCqXKJSU+zM= +github.com/dolthub/go-icu-regex v0.0.0-20241215010122-db690dd53c90/go.mod h1:ylU4XjUpsMcvl/BKeRRMXSH7e7WBrPXdSLvnRJYrxEA= github.com/dolthub/jsonpath v0.0.2-0.20240227200619-19675ab05c71 h1:bMGS25NWAGTEtT5tOBsCuCrlYnLRKpbJVJkDbrTRhwQ= github.com/dolthub/jsonpath v0.0.2-0.20240227200619-19675ab05c71/go.mod h1:2/2zjLQ/JOOSbbSboojeg+cAwcRV0fDLzIiWch/lhqI= github.com/dolthub/sqllogictest/go v0.0.0-20240618184124-ca47f9354216 h1:JWkKRE4EHUcEVQCMRBej8DYxjYjRz/9MdF/NNQh0o70= @@ -639,8 +639,8 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/tetratelabs/wazero v1.1.0 h1:EByoAhC+QcYpwSZJSs/aV0uokxPwBgKxfiokSUwAknQ= -github.com/tetratelabs/wazero v1.1.0/go.mod h1:wYx2gNRg8/WihJfSDxA1TIL8H+GkfLYm+bIfbblu9VQ= +github.com/tetratelabs/wazero v1.8.2 h1:yIgLR/b2bN31bjxwXHD8a3d+BogigR952csSDdLYEv4= +github.com/tetratelabs/wazero v1.8.2/go.mod h1:yAI0XTsMBhREkM/YDAK/zNou3GoiAce1P6+rp/wQhjs= github.com/the42/cartconvert v0.0.0-20131203171324-aae784c392b8 h1:I4DY8wLxJXCrMYzDM6lKCGc3IQwJX0PlTLsd3nQqI3c= github.com/the42/cartconvert v0.0.0-20131203171324-aae784c392b8/go.mod h1:fWO/msnJVhHqN1yX6OBoxSyfj7TEj1hHiL8bJSQsK30= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= diff --git a/main_test.go b/main_test.go index 21c5f8e3..26b0ef48 100644 --- a/main_test.go +++ b/main_test.go @@ -230,7 +230,6 @@ func TestQueriesSimple(t *testing.T) { "SELECT_pk_FROM_one_pk_WHERE_(pk,_123)_NOT_IN_(SELECT_count(*)_AS_u,_123_AS_v_FROM_emptytable);", "SELECT_pk_FROM_one_pk_WHERE_(pk,_123)_NOT_IN_(SELECT_count(*)_AS_u,_123_AS_v_FROM_mytable_WHERE_false);", "SELECT_pk1,_SUM(c1)_FROM_two_pk_WHERE_pk1_=_0", - "SELECT_floor(i),_avg(char_length(s))_FROM_mytable_mt_group_by_1_ORDER_BY_floor(i)_DESC", "SELECT_FORMAT(i,_3)_FROM_mytable;", "SELECT_FORMAT(i,_3,_'da_DK')_FROM_mytable;", "SELECT_JSON_OVERLAPS(c3,_'{\"a\":_2,_\"d\":_2}')_FROM_jsontable", @@ -320,7 +319,6 @@ func TestQueriesSimple(t *testing.T) { "select_sha1(i)_from_mytable_order_by_1", "select_sha2(i,_256)_from_mytable_order_by_1", "select_octet_length(s)_from_mytable_order_by_i", - "select_char_length(s)_from_mytable_order_by_i", "select_locate(upper(\"roW\"),_upper(s),_power(10,_0))_from_mytable_order_by_i", "select_log2(i)_from_mytable_order_by_i", "select_ln(i)_from_mytable_order_by_i",