From fd06101159970b67580c62a82f44c54eab4c0f95 Mon Sep 17 00:00:00 2001 From: angelamayxie Date: Thu, 22 Jan 2026 13:05:50 -0800 Subject: [PATCH 1/8] check for existing temporary table before creating new temporary table, refactor temporary tables to use 2d map --- go/libraries/doltcore/sqle/database.go | 11 +++++-- go/libraries/doltcore/sqle/dsess/session.go | 35 ++++++++++----------- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/go/libraries/doltcore/sqle/database.go b/go/libraries/doltcore/sqle/database.go index ccbf46751c0..96cad71052a 100644 --- a/go/libraries/doltcore/sqle/database.go +++ b/go/libraries/doltcore/sqle/database.go @@ -2202,13 +2202,18 @@ func (db Database) CreateTemporaryTable(ctx *sql.Context, tableName string, pkSc return ErrInvalidTableName.New(tableName) } - tmp, err := NewTempTable(ctx, db.ddb, pkSch, tableName, db.Name(), db.editOpts, collation) + ds := dsess.DSessFromSess(ctx.Session) + databaseName := db.Name() + if _, exists := ds.GetTemporaryTable(ctx, databaseName, tableName); exists { + return sql.ErrTableAlreadyExists.New(tableName) + } + + tmp, err := NewTempTable(ctx, db.ddb, pkSch, tableName, databaseName, db.editOpts, collation) if err != nil { return err } - ds := dsess.DSessFromSess(ctx.Session) - ds.AddTemporaryTable(ctx, db.Name(), tmp) + ds.AddTemporaryTable(ctx, databaseName, tmp) return nil } diff --git a/go/libraries/doltcore/sqle/dsess/session.go b/go/libraries/doltcore/sqle/dsess/session.go index 3c0690b8321..787e7eff70f 100644 --- a/go/libraries/doltcore/sqle/dsess/session.go +++ b/go/libraries/doltcore/sqle/dsess/session.go @@ -64,7 +64,7 @@ type DoltSession struct { branchController *branch_control.Controller dbCache *DatabaseCache dbStates map[string]*DatabaseSessionState - tempTables map[string][]sql.Table + tempTables map[string]map[string]sql.Table gcSafepointController *gcctx.GCSafepointController writeSessProv WriteSessFunc @@ -90,7 +90,7 @@ func DefaultSession(pro DoltDatabaseProvider, sessFunc WriteSessFunc) *DoltSessi dbStates: make(map[string]*DatabaseSessionState), dbCache: newDatabaseCache(), provider: pro, - tempTables: make(map[string][]sql.Table), + tempTables: make(map[string]map[string]sql.Table), globalsConf: config.NewMapConfig(make(map[string]string)), branchController: branch_control.CreateDefaultController(context.TODO()), // Default sessions are fine with the default controller mu: &sync.Mutex{}, @@ -121,7 +121,7 @@ func NewDoltSession( dbStates: make(map[string]*DatabaseSessionState), dbCache: newDatabaseCache(), provider: pro, - tempTables: make(map[string][]sql.Table), + tempTables: make(map[string]map[string]sql.Table), globalsConf: globals, branchController: branchController, statsProv: statsProvider, @@ -1503,32 +1503,29 @@ func (d *DoltSession) DatabaseCache(ctx *sql.Context) *DatabaseCache { } func (d *DoltSession) AddTemporaryTable(ctx *sql.Context, db string, tbl sql.Table) { - d.tempTables[strings.ToLower(db)] = append(d.tempTables[strings.ToLower(db)], tbl) + db = strings.ToLower(db) + if _, exists := d.tempTables[db]; !exists { + d.tempTables[db] = make(map[string]sql.Table) + } + d.tempTables[db][strings.ToLower(tbl.Name())] = tbl } func (d *DoltSession) DropTemporaryTable(ctx *sql.Context, db, name string) { - tables := d.tempTables[strings.ToLower(db)] - for i, tbl := range d.tempTables[strings.ToLower(db)] { - if strings.EqualFold(tbl.Name(), name) { - tables = append(tables[:i], tables[i+1:]...) - break - } - } - d.tempTables[strings.ToLower(db)] = tables + delete(d.tempTables[strings.ToLower(db)], strings.ToLower(name)) } func (d *DoltSession) GetTemporaryTable(ctx *sql.Context, db, name string) (sql.Table, bool) { - for _, tbl := range d.tempTables[strings.ToLower(db)] { - if strings.EqualFold(tbl.Name(), name) { - return tbl, true - } - } - return nil, false + tmpTbl, exists := d.tempTables[strings.ToLower(db)][strings.ToLower(name)] + return tmpTbl, exists } // GetAllTemporaryTables returns all temp tables for this session. func (d *DoltSession) GetAllTemporaryTables(ctx *sql.Context, db string) ([]sql.Table, error) { - return d.tempTables[strings.ToLower(db)], nil + tmpTables := make([]sql.Table, 0) + for _, tbl := range d.tempTables[strings.ToLower(db)] { + tmpTables = append(tmpTables, tbl) + } + return tmpTables, nil } // CWBHeadRef returns the branch ref for this session HEAD for the database named From e024158c649d4ff43c3d43a58acd84d14e650508 Mon Sep 17 00:00:00 2001 From: angelamayxie Date: Thu, 22 Jan 2026 14:04:19 -0800 Subject: [PATCH 2/8] check for temporary tables before creating dolt table --- go/libraries/doltcore/sqle/database.go | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/go/libraries/doltcore/sqle/database.go b/go/libraries/doltcore/sqle/database.go index 96cad71052a..596a5cf01f3 100644 --- a/go/libraries/doltcore/sqle/database.go +++ b/go/libraries/doltcore/sqle/database.go @@ -2066,12 +2066,6 @@ func (db Database) createSqlTable(ctx *sql.Context, table string, schemaName str } tableName := doltdb.TableName{Name: table, Schema: schemaName} - if exists, err := root.HasTable(ctx, tableName); err != nil { - return err - } else if exists { - return sql.ErrTableAlreadyExists.New(table) - } - headRoot, err := db.GetHeadRoot(ctx) if err != nil { return err @@ -2118,12 +2112,6 @@ func (db Database) createIndexedSqlTable(ctx *sql.Context, table string, schemaN } tableName := doltdb.TableName{Name: table, Schema: schemaName} - if exists, err := root.HasTable(ctx, tableName); err != nil { - return err - } else if exists { - return sql.ErrTableAlreadyExists.New(tableName.Name) - } - headRoot, err := db.GetHeadRoot(ctx) if err != nil { return err @@ -2160,6 +2148,10 @@ func (db Database) createIndexedSqlTable(ctx *sql.Context, table string, schemaN // createDoltTable creates a table on the database using the given dolt schema while not enforcing table baseName checks. func (db Database) createDoltTable(ctx *sql.Context, tableName string, schemaName string, root doltdb.RootValue, doltSch schema.Schema) error { + if _, exists := dsess.DSessFromSess(ctx.Session).GetTemporaryTable(ctx, db.Name(), tableName); exists { + return sql.ErrTableAlreadyExists.New(tableName) + } + if exists, err := root.HasTable(ctx, doltdb.TableName{Name: tableName, Schema: schemaName}); err != nil { return err } else if exists { From 0c3109dc3a571955cf4c280fb2c04bff2dcf1c70 Mon Sep 17 00:00:00 2001 From: angelamayxie Date: Thu, 22 Jan 2026 14:18:55 -0800 Subject: [PATCH 3/8] add test script --- .../doltcore/sqle/enginetest/dolt_queries.go | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_queries.go b/go/libraries/doltcore/sqle/enginetest/dolt_queries.go index f0436f4a796..e52454fbca9 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_queries.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_queries.go @@ -8833,6 +8833,52 @@ var DoltSystemVariables = []queries.ScriptTest{ // DoltTempTableScripts tests temporary tables. // Temporary tables are not supported in GMS, eventually should move those tests there. var DoltTempTableScripts = []queries.ScriptTest{ + { + Name: "temporary and non-temporary table name collisions", + SetUpScript: []string{ + "create table t1 (id varchar(100))", + "insert into t1 values ('this is a non-temporary table')", + "create temporary table t1 (id varchar(100))", // okay to create temporary table with the same name as a non-temporary table + "insert into t1 values ('this is a temporary table')", + "create temporary table t2 (id int)", + }, + Assertions: []queries.ScriptTestAssertion{ + { + // should show temporary table t1 + Query: "select * from t1", + Expected: []sql.Row{{"this is a temporary table"}}, + }, + { + // cannot create a table with the same name as an existing table, temporary or non-temporary + Query: "create table t1 (id int)", + ExpectedErr: sql.ErrTableAlreadyExists, + }, + { + // cannot create a table with the same name as a temporary table + Query: "create table t2 (id int)", + ExpectedErr: sql.ErrTableAlreadyExists, + }, + { + // cannot create a temporary table with the same name as another temporary table + Query: "create temporary table t2 (id int)", + ExpectedErr: sql.ErrTableAlreadyExists, + }, + { + // should show temporary table + Query: "show create table t1", + Expected: []sql.Row{{"t1", "CREATE TEMPORARY TABLE `t1` (\n `id` varchar(100)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}}, + }, + { + // should drop temporary table t1 + Expected: []sql.Row{{types.NewOkResult(0)}}, + }, + { + // should show non-temporary table that was created before + Query: "show create table t1", + Expected: []sql.Row{{"t1", "CREATE TABLE `t1` (\n `id` varchar(100)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}}, + }, + }, + }, { Name: "temporary table supports auto increment", SetUpScript: []string{ From b8f37c2326c01829c8e4300ddecc696d5cf84705 Mon Sep 17 00:00:00 2001 From: angelamayxie Date: Thu, 22 Jan 2026 14:37:01 -0800 Subject: [PATCH 4/8] add back name collision check --- go/libraries/doltcore/sqle/database.go | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/go/libraries/doltcore/sqle/database.go b/go/libraries/doltcore/sqle/database.go index 596a5cf01f3..f4f29b7b3d7 100644 --- a/go/libraries/doltcore/sqle/database.go +++ b/go/libraries/doltcore/sqle/database.go @@ -2049,7 +2049,7 @@ OuterLoop: }, nil } -// createSqlTable is the private version of CreateTable. It doesn't enforce any table name checks. +// createSqlTable is the private version of CreateTable. func (db Database) createSqlTable(ctx *sql.Context, table string, schemaName string, sch sql.PrimaryKeySchema, collation sql.CollationID, comment string) error { ws, err := db.GetWorkingSet(ctx) if err != nil { @@ -2066,6 +2066,13 @@ func (db Database) createSqlTable(ctx *sql.Context, table string, schemaName str } tableName := doltdb.TableName{Name: table, Schema: schemaName} + // TODO: This check is also done in createDoltTable, which is called at the end of this function, meaning it's done + // multiple times. Consider refactoring out. + if exists, err := root.HasTable(ctx, tableName); err != nil { + return err + } else if exists { + return sql.ErrTableAlreadyExists.New(tableName.Name) + } headRoot, err := db.GetHeadRoot(ctx) if err != nil { return err @@ -2112,6 +2119,14 @@ func (db Database) createIndexedSqlTable(ctx *sql.Context, table string, schemaN } tableName := doltdb.TableName{Name: table, Schema: schemaName} + // TODO: This check is also done in createDoltTable, which is called at the end of this function, meaning it's done + // multiple times. Consider refactoring out. + if exists, err := root.HasTable(ctx, tableName); err != nil { + return err + } else if exists { + return sql.ErrTableAlreadyExists.New(tableName.Name) + } + headRoot, err := db.GetHeadRoot(ctx) if err != nil { return err @@ -2152,6 +2167,8 @@ func (db Database) createDoltTable(ctx *sql.Context, tableName string, schemaNam return sql.ErrTableAlreadyExists.New(tableName) } + // TODO: This check is also done in createSqlTable and createIndexedSqlTable, which both call createDoltTable, + // meaning it's done multiple times. Consider refactoring. if exists, err := root.HasTable(ctx, doltdb.TableName{Name: tableName, Schema: schemaName}); err != nil { return err } else if exists { From 3e7e0ec6339c06cd4d448e839caef54b281fbb45 Mon Sep 17 00:00:00 2001 From: angelamayxie Date: Thu, 22 Jan 2026 14:39:26 -0800 Subject: [PATCH 5/8] nit: add empty line back --- go/libraries/doltcore/sqle/database.go | 1 + 1 file changed, 1 insertion(+) diff --git a/go/libraries/doltcore/sqle/database.go b/go/libraries/doltcore/sqle/database.go index f4f29b7b3d7..ebc47142af0 100644 --- a/go/libraries/doltcore/sqle/database.go +++ b/go/libraries/doltcore/sqle/database.go @@ -2073,6 +2073,7 @@ func (db Database) createSqlTable(ctx *sql.Context, table string, schemaName str } else if exists { return sql.ErrTableAlreadyExists.New(tableName.Name) } + headRoot, err := db.GetHeadRoot(ctx) if err != nil { return err From 1af63069affb880445369469c99e1422ce216c75 Mon Sep 17 00:00:00 2001 From: angelamayxie Date: Thu, 22 Jan 2026 14:41:40 -0800 Subject: [PATCH 6/8] nit: whitespace --- go/libraries/doltcore/sqle/database.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/libraries/doltcore/sqle/database.go b/go/libraries/doltcore/sqle/database.go index ebc47142af0..58ba28e1be4 100644 --- a/go/libraries/doltcore/sqle/database.go +++ b/go/libraries/doltcore/sqle/database.go @@ -2073,7 +2073,7 @@ func (db Database) createSqlTable(ctx *sql.Context, table string, schemaName str } else if exists { return sql.ErrTableAlreadyExists.New(tableName.Name) } - + headRoot, err := db.GetHeadRoot(ctx) if err != nil { return err From d7e41934b201c303f55c146d973b55143f656ba1 Mon Sep 17 00:00:00 2001 From: angelamayxie Date: Thu, 22 Jan 2026 15:19:05 -0800 Subject: [PATCH 7/8] okay to create non-temporary tables with the same name as temporary tables --- go/libraries/doltcore/sqle/database.go | 4 ---- .../doltcore/sqle/enginetest/dolt_queries.go | 15 ++++----------- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/go/libraries/doltcore/sqle/database.go b/go/libraries/doltcore/sqle/database.go index 58ba28e1be4..b6bb4faf0ff 100644 --- a/go/libraries/doltcore/sqle/database.go +++ b/go/libraries/doltcore/sqle/database.go @@ -2164,10 +2164,6 @@ func (db Database) createIndexedSqlTable(ctx *sql.Context, table string, schemaN // createDoltTable creates a table on the database using the given dolt schema while not enforcing table baseName checks. func (db Database) createDoltTable(ctx *sql.Context, tableName string, schemaName string, root doltdb.RootValue, doltSch schema.Schema) error { - if _, exists := dsess.DSessFromSess(ctx.Session).GetTemporaryTable(ctx, db.Name(), tableName); exists { - return sql.ErrTableAlreadyExists.New(tableName) - } - // TODO: This check is also done in createSqlTable and createIndexedSqlTable, which both call createDoltTable, // meaning it's done multiple times. Consider refactoring. if exists, err := root.HasTable(ctx, doltdb.TableName{Name: tableName, Schema: schemaName}); err != nil { diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_queries.go b/go/libraries/doltcore/sqle/enginetest/dolt_queries.go index e52454fbca9..213d91afd6b 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_queries.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_queries.go @@ -8841,6 +8841,8 @@ var DoltTempTableScripts = []queries.ScriptTest{ "create temporary table t1 (id varchar(100))", // okay to create temporary table with the same name as a non-temporary table "insert into t1 values ('this is a temporary table')", "create temporary table t2 (id int)", + "create table t2 (id int)", // okay to create a non-temporary table with the same name as a temporary table + "create temporary table t3 (id int)", }, Assertions: []queries.ScriptTestAssertion{ { @@ -8848,19 +8850,9 @@ var DoltTempTableScripts = []queries.ScriptTest{ Query: "select * from t1", Expected: []sql.Row{{"this is a temporary table"}}, }, - { - // cannot create a table with the same name as an existing table, temporary or non-temporary - Query: "create table t1 (id int)", - ExpectedErr: sql.ErrTableAlreadyExists, - }, - { - // cannot create a table with the same name as a temporary table - Query: "create table t2 (id int)", - ExpectedErr: sql.ErrTableAlreadyExists, - }, { // cannot create a temporary table with the same name as another temporary table - Query: "create temporary table t2 (id int)", + Query: "create temporary table t3 (id int)", ExpectedErr: sql.ErrTableAlreadyExists, }, { @@ -8870,6 +8862,7 @@ var DoltTempTableScripts = []queries.ScriptTest{ }, { // should drop temporary table t1 + Query: "drop table t1", Expected: []sql.Row{{types.NewOkResult(0)}}, }, { From 06b39912e941b89cae085107d9bdf0e41bf1aa6a Mon Sep 17 00:00:00 2001 From: angelamayxie Date: Thu, 22 Jan 2026 15:27:35 -0800 Subject: [PATCH 8/8] remove unnecessary variable name change --- go/libraries/doltcore/sqle/database.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/libraries/doltcore/sqle/database.go b/go/libraries/doltcore/sqle/database.go index b6bb4faf0ff..d541bf197ed 100644 --- a/go/libraries/doltcore/sqle/database.go +++ b/go/libraries/doltcore/sqle/database.go @@ -2071,7 +2071,7 @@ func (db Database) createSqlTable(ctx *sql.Context, table string, schemaName str if exists, err := root.HasTable(ctx, tableName); err != nil { return err } else if exists { - return sql.ErrTableAlreadyExists.New(tableName.Name) + return sql.ErrTableAlreadyExists.New(table) } headRoot, err := db.GetHeadRoot(ctx)