diff --git a/cmd/doltgres/main.go b/cmd/doltgres/main.go index b8d1a2a5f1..6047c13e62 100644 --- a/cmd/doltgres/main.go +++ b/cmd/doltgres/main.go @@ -150,19 +150,20 @@ func PrintDefaults(fs *flag.FlagSet) { } func main() { - if len(os.Args) >= 2 { + args := os.Args[1:] + + if len(args) >= 2 { profilingOptions := utils.ProfilingOptions{} doneDebugFlags := false - for !doneDebugFlags { - switch os.Args[1] { + for !doneDebugFlags && len(args) > 0 { + switch args[0] { case profilePath: - profilingOptions.Path = os.Args[2] + profilingOptions.Path = args[1] if _, err := os.Stat(profilingOptions.Path); errors.Is(err, os.ErrNotExist) { panic(errors.Errorf("profile path does not exist: %s", profilingOptions.Path)) } - os.Args = append([]string{os.Args[0]}, os.Args[3:]...) case profFlag: - switch os.Args[2] { + switch args[1] { case cpuProf: profilingOptions.CPU = true case memProf: @@ -172,18 +173,22 @@ func main() { case traceProf: profilingOptions.Trace = true default: - panic("Unexpected prof flag: " + os.Args[2]) + panic("Unexpected prof flag: " + args[1]) } - os.Args = append([]string{os.Args[0]}, os.Args[3:]...) default: doneDebugFlags = true } + + args = args[2:] } + if profilingOptions.HasOptions() { utils.StartProfiling(profilingOptions) defer utils.StopProfiling() + os.Args = append([]string{os.Args[0]}, args...) } } + ctx := context.Background() flags, params := parseArgs() diff --git a/go.mod b/go.mod index 010e9499fe..e5c47e8dff 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/PuerkitoBio/goquery v1.8.1 github.com/cockroachdb/apd/v2 v2.0.3-0.20200518165714-d020e156310a github.com/cockroachdb/errors v1.7.5 - github.com/dolthub/dolt/go v0.40.5-0.20250328104255-4b02d926bf54 + github.com/dolthub/dolt/go v0.40.5-0.20250402164602-d8de959edc19 github.com/dolthub/dolt/go/gen/proto/dolt/services/eventsapi v0.0.0-20250328104255-4b02d926bf54 github.com/dolthub/flatbuffers/v23 v23.3.3-dh.2 github.com/dolthub/go-icu-regex v0.0.0-20250327004329-6799764f2dad diff --git a/go.sum b/go.sum index 5de5de67ac..e43165f879 100644 --- a/go.sum +++ b/go.sum @@ -256,8 +256,8 @@ github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5Xh github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dolthub/aws-sdk-go-ini-parser v0.0.0-20250305001723-2821c37f6c12 h1:IdqX7J8vi/Kn3T3Ee0VzqnLqwFmgA2hr8WZETPcQjfM= github.com/dolthub/aws-sdk-go-ini-parser v0.0.0-20250305001723-2821c37f6c12/go.mod h1:rN7X8BHwkjPcfMQQ2QTAq/xM3leUSGLfb+1Js7Y6TVo= -github.com/dolthub/dolt/go v0.40.5-0.20250328104255-4b02d926bf54 h1:jgkbWBTDq7pJOdEfGwYfS0RxfGyPFoS1P/1j6a/LEws= -github.com/dolthub/dolt/go v0.40.5-0.20250328104255-4b02d926bf54/go.mod h1:RlmLbEjyqllLueZYCtNTYJohZ3DNPl7cpzBk3M53OzM= +github.com/dolthub/dolt/go v0.40.5-0.20250402164602-d8de959edc19 h1:fRNeSwOu8GnZgEIGPXjSaaDyt5DVl+ycBS9JWc4xbzQ= +github.com/dolthub/dolt/go v0.40.5-0.20250402164602-d8de959edc19/go.mod h1:RlmLbEjyqllLueZYCtNTYJohZ3DNPl7cpzBk3M53OzM= github.com/dolthub/dolt/go/gen/proto/dolt/services/eventsapi v0.0.0-20250328104255-4b02d926bf54 h1:IBn2A+TAjF+YRuLF0ND7eMoQp8X30iyrezwcMPsVnUw= github.com/dolthub/dolt/go/gen/proto/dolt/services/eventsapi v0.0.0-20250328104255-4b02d926bf54/go.mod h1:/jRNsdAkhDGOrY0A8f3MiQWKW4u02KWlFxq2fPz5h/Q= github.com/dolthub/flatbuffers/v23 v23.3.3-dh.2 h1:u3PMzfF8RkKd3lB9pZ2bfn0qEG+1Gms9599cr0REMww= diff --git a/server/ast/alter_table.go b/server/ast/alter_table.go index f52706c4c6..96714cd23d 100644 --- a/server/ast/alter_table.go +++ b/server/ast/alter_table.go @@ -19,6 +19,7 @@ import ( "github.com/cockroachdb/errors" vitess "github.com/dolthub/vitess/go/vt/sqlparser" + "github.com/sirupsen/logrus" "github.com/dolthub/doltgresql/postgres/parser/sem/tree" ) @@ -262,7 +263,7 @@ func nodeAlterTableDropColumn(ctx *Context, node *tree.AlterTableDropColumn, tab case tree.DropRestrict: return nil, errors.Errorf("ALTER TABLE DROP COLUMN does not support RESTRICT option") case tree.DropCascade: - return nil, errors.Errorf("ALTER TABLE DROP COLUMN does not support CASCADE option") + logrus.Warnf("CASCADE option on DROP COLUMN is not yet supported, ignoring") default: return nil, errors.Errorf("ALTER TABLE with unsupported drop behavior %v", node.DropBehavior) } diff --git a/server/types/type.go b/server/types/type.go index 2c4a3a7bcd..d0cc494892 100644 --- a/server/types/type.go +++ b/server/types/type.go @@ -525,7 +525,7 @@ func (t *DoltgresType) IsValidForPolymorphicType(target *DoltgresType) bool { // Length implements the sql.StringType interface. func (t *DoltgresType) Length() int64 { switch t.ID.TypeName() { - case "varchar": + case "varchar", "bpchar": if t.attTypMod == -1 { return StringUnbounded } else { @@ -565,6 +565,10 @@ func (t *DoltgresType) MaxCharacterLength() int64 { // MaxSerializedWidth implements the types.ExtendedType interface. func (t *DoltgresType) MaxSerializedWidth() types.ExtendedTypeSerializedWidth { if t.TypLength < 0 { + // Length will be 0 for any non-string type, as well as unbounded string types + if t.Length() > 0 { + return types.ExtendedTypeSerializedWidth_64K + } return types.ExtendedTypeSerializedWidth_Unbounded } return types.ExtendedTypeSerializedWidth_64K diff --git a/testing/go/dolt_tables_test.go b/testing/go/dolt_tables_test.go index ed5592d6c8..e77c101441 100755 --- a/testing/go/dolt_tables_test.go +++ b/testing/go/dolt_tables_test.go @@ -1763,30 +1763,24 @@ func TestUserSpaceDoltTables(t *testing.T) { { Query: `SELECT database_name, table_name, index_name, row_count, distinct_count, columns, upper_bound, upper_bound_cnt FROM dolt_statistics ORDER BY index_name, row_count`, Expected: []sql.Row{ - {"postgres", "horses", "horses_name_idx", 70, 1, "name", "Steve", 70}, - {"postgres", "horses", "horses_name_idx", 126, 1, "name", "Steve", 126}, - {"postgres", "horses", "horses_name_idx", 141, 1, "name", "Steve", 141}, - {"postgres", "horses", "horses_name_idx", 146, 1, "name", "Steve", 146}, - {"postgres", "horses", "horses_name_idx", 160, 1, "name", "Steve", 160}, - {"postgres", "horses", "horses_name_idx", 165, 1, "name", "Steve", 165}, - {"postgres", "horses", "horses_name_idx", 192, 1, "name", "Steve", 192}, + {"postgres", "horses", "horses_name_idx", 10, 1, "name", "Steve", 10}, + {"postgres", "horses", "horses_name_idx", 167, 1, "name", "Steve", 167}, + {"postgres", "horses", "horses_name_idx", 197, 1, "name", "Steve", 197}, + {"postgres", "horses", "horses_name_idx", 306, 1, "name", "Steve", 306}, + {"postgres", "horses", "horses_name_idx", 320, 1, "name", "Steve", 320}, {"postgres", "horses", "primary", 46, 46, "id", "1000", 1}, - {"postgres", "horses", "primary", 76, 76, "id", "954", 1}, - {"postgres", "horses", "primary", 89, 89, "id", "547", 1}, - {"postgres", "horses", "primary", 117, 117, "id", "117", 1}, - {"postgres", "horses", "primary", 149, 149, "id", "458", 1}, - {"postgres", "horses", "primary", 162, 162, "id", "709", 1}, - {"postgres", "horses", "primary", 169, 169, "id", "878", 1}, - {"postgres", "horses", "primary", 192, 192, "id", "309", 1}, + {"postgres", "horses", "primary", 203, 203, "id", "954", 1}, + {"postgres", "horses", "primary", 347, 347, "id", "347", 1}, + {"postgres", "horses", "primary", 404, 404, "id", "751", 1}, }, }, { Query: `SELECT count(*) FROM dolt_statistics`, - Expected: []sql.Row{{15}}, + Expected: []sql.Row{{9}}, }, { Query: `SELECT count(*) FROM public.dolt_statistics`, - Expected: []sql.Row{{15}}, + Expected: []sql.Row{{9}}, }, { Query: `SELECT dolt_statistics.index_name FROM public.dolt_statistics GROUP BY index_name ORDER BY index_name`, @@ -1825,10 +1819,12 @@ func TestUserSpaceDoltTables(t *testing.T) { Expected: []sql.Row{}, }, { + Skip: true, // http://github.com/dolthub/doltgresql/issues/1352 Query: `SELECT dolt_statistics.index_name FROM dolt_statistics GROUP BY index_name ORDER BY index_name`, Expected: []sql.Row{{"horses2_name_idx"}, {"primary"}}, }, { + Skip: true, // http://github.com/dolthub/doltgresql/issues/1352 Query: `SELECT dolt_statistics.index_name FROM newschema.dolt_statistics GROUP BY index_name ORDER BY index_name`, Expected: []sql.Row{{"horses2_name_idx"}, {"primary"}}, }, diff --git a/testing/go/index_test.go b/testing/go/index_test.go index 13daf7c737..a395bb7014 100644 --- a/testing/go/index_test.go +++ b/testing/go/index_test.go @@ -771,5 +771,206 @@ func TestBasicIndexing(t *testing.T) { }, }, }, + { + Name: "multi column int index", + SetUpScript: []string{ + `CREATE TABLE test (pk INT4 PRIMARY KEY, a int, b int);`, + `ALTER TABLE test ADD CONSTRAINT uniqIdx UNIQUE (a, b);`, + `INSERT INTO test VALUES (1, 1, 2);`, + `insert into test values (2, 1, 3)`, + `insert into test values (3, 2, 2);`, + `insert into test values (4, 3, 1);`, + }, + Assertions: []ScriptTestAssertion{ + { + Query: `SELECT pk FROM test WHERE a = 2 and b = 2;`, + Expected: []sql.Row{ + {3}, + }, + }, + { + Query: `SELECT pk FROM test WHERE a > 1`, + Expected: []sql.Row{ + {3}, + {4}, + }, + }, + { + Query: `SELECT pk FROM test WHERE a = 2 and b < 3`, + Expected: []sql.Row{ + {3}, + }, + }, + { + Query: `SELECT pk FROM test WHERE a > 2 and b < 3`, + Expected: []sql.Row{ + {4}, + }, + }, + { + Query: `SELECT pk FROM test WHERE a > 2 and b < 2`, + Expected: []sql.Row{ + {4}, + }, + }, + { + Query: `SELECT pk FROM test WHERE a > 3 and b < 2`, + Expected: []sql.Row{}, + }, + { + Query: `SELECT pk FROM test WHERE a > 3 and b < 2`, + Expected: []sql.Row{}, + }, + { + Query: `SELECT pk FROM test WHERE a > 1 and b > 1`, + Expected: []sql.Row{ + {3}, + }, + }, + { + Query: `SELECT pk FROM test WHERE a > 1 and b = 1`, + Expected: []sql.Row{ + {4}, + }, + }, + { + Query: `SELECT pk FROM test WHERE a < 3 and b > 0 order by 1`, + Expected: []sql.Row{ + {1}, + {2}, + {3}, + }, + }, + { + Query: `SELECT pk FROM test WHERE a > 1 and a < 3 order by 1`, + Expected: []sql.Row{ + {3}, + }, + }, + { + Query: `SELECT pk FROM test WHERE a > 1 and a < 3 order by 1`, + Expected: []sql.Row{ + {3}, + }, + }, + { + Query: `SELECT pk FROM test WHERE a > 1 and b > 1 order by 1`, + Expected: []sql.Row{ + {3}, + }, + }, + }, + }, + { + Name: "multi column int index, part 2", + SetUpScript: []string{ + `CREATE TABLE test (pk INT4 PRIMARY KEY, a int, b int);`, + `ALTER TABLE test ADD CONSTRAINT uniqIdx UNIQUE (a, b);`, + `INSERT INTO test VALUES (1, 1, 2);`, + `insert into test values (2, 1, 3)`, + `insert into test values (3, 2, 2);`, + `insert into test values (4, 2, 3);`, + }, + Assertions: []ScriptTestAssertion{ + { + Query: `SELECT pk FROM test WHERE a = 2 and b = 2;`, + Expected: []sql.Row{ + {3}, + }, + }, + { + Query: `SELECT pk FROM test WHERE a = 2 and b = 3;`, + Expected: []sql.Row{ + {4}, + }, + }, + }, + }, + { + Name: "multi column int index, reverse traversal", + SetUpScript: []string{ + `CREATE TABLE test (pk INT4 PRIMARY KEY, a int, b int);`, + `ALTER TABLE test ADD CONSTRAINT uniqIdx UNIQUE (a, b);`, + `INSERT INTO test VALUES (1, 1, 1);`, + `insert into test values (2, 1, 3)`, + `insert into test values (3, 2, 2);`, + }, + Assertions: []ScriptTestAssertion{ + { + Query: `SELECT pk FROM test WHERE a < 3 and b = 2 order by a desc, b desc;`, + Expected: []sql.Row{ + {3}, + }, + }, + { + Query: `SELECT pk FROM test WHERE a < 2 and b = 3 order by a desc, b desc;`, + Expected: []sql.Row{ + {2}, + }, + }, + { + Query: `SELECT pk FROM test WHERE a < 2 and b < 10 order by a desc, b desc;`, + Expected: []sql.Row{ + {2}, + {1}, + }, + }, + }, + }, + { + Name: "Unique index varchar", + SetUpScript: []string{ + `CREATE TABLE test (pk INT4 PRIMARY KEY, v1 varchar(100), v2 varchar(100));`, + `ALTER TABLE test ADD CONSTRAINT uniqIdx UNIQUE (v1, v2);`, + `INSERT INTO test VALUES (1, 'a', 'b');`, + `insert into test values (2, 'a', 'u')`, + `insert into test values (3, 'c', 'c');`, + }, + Assertions: []ScriptTestAssertion{ + { + Query: `SELECT pk FROM test WHERE (v1 = 'c' AND v2 = 'c');`, + Expected: []sql.Row{ + {3}, + }, + }, + }, + }, + { + Name: "unique index select", + SetUpScript: []string{ + `CREATE TABLE "django_content_type" ("id" integer NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, "name" varchar(100) NOT NULL, "app_label" varchar(100) NOT NULL, "model" varchar(100) NOT NULL);`, + `ALTER TABLE "django_content_type" ADD CONSTRAINT "django_content_type_app_label_model_76bd3d3b_uniq" UNIQUE ("app_label", "model");`, + `ALTER TABLE "django_content_type" ALTER COLUMN "name" DROP NOT NULL;`, + `ALTER TABLE "django_content_type" DROP COLUMN "name" CASCADE;`, + `INSERT INTO "django_content_type" ("app_label", "model") VALUES ('auth', 'permission'), ('auth', 'group'), ('auth', 'user') RETURNING "django_content_type"."id";`, + `INSERT INTO "django_content_type" ("app_label", "model") VALUES ('contenttypes', 'contenttype') RETURNING "django_content_type"."id";`, + }, + Assertions: []ScriptTestAssertion{ + { + Query: `SELECT "django_content_type"."id", "django_content_type"."app_label", "django_content_type"."model" FROM "django_content_type" WHERE ("django_content_type"."app_label" = 'auth' AND "django_content_type"."model" = 'permission') LIMIT 21;`, + Expected: []sql.Row{ + {1, "auth", "permission"}, + }, + }, + { + Query: `SELECT "django_content_type"."id", "django_content_type"."app_label", "django_content_type"."model" FROM "django_content_type" WHERE ("django_content_type"."app_label" = 'auth' AND "django_content_type"."model" = 'group') LIMIT 21;`, + Expected: []sql.Row{ + {2, "auth", "group"}, + }, + }, + { + Query: `SELECT "django_content_type"."id", "django_content_type"."app_label", "django_content_type"."model" FROM "django_content_type" WHERE ("django_content_type"."app_label" = 'auth' AND "django_content_type"."model" = 'user') LIMIT 21;`, + Expected: []sql.Row{ + {3, "auth", "user"}, + }, + }, + { + Query: `SELECT "django_content_type"."id", "django_content_type"."app_label", "django_content_type"."model" FROM "django_content_type" WHERE ("django_content_type"."app_label" = 'contenttypes' AND "django_content_type"."model" = 'contenttype') LIMIT 21;`, + Expected: []sql.Row{ + {4, "contenttypes", "contenttype"}, + }, + }, + }, + }, }) }