@@ -199,6 +199,14 @@ func getPrimaryKeyOrdinals(ctx *sql.Context, catalogName, dbName, tableName stri
199199 return ordinals
200200}
201201
202+ func getCreateSequence (temporary bool , sequenceName string ) (createStmt , fullName string ) {
203+ if temporary {
204+ return `CREATE TEMP SEQUENCE "` + sequenceName + `"` , `temp.main."` + sequenceName + `"`
205+ }
206+ fullName = InternalSchemas .SYS .Schema + `."` + sequenceName + `"`
207+ return `CREATE SEQUENCE ` + fullName , fullName
208+ }
209+
202210// AddColumn implements sql.AlterableTable.
203211func (t * Table ) AddColumn (ctx * sql.Context , column * sql.Column , order * sql.ColumnOrder ) error {
204212 t .mu .Lock ()
@@ -215,7 +223,7 @@ func (t *Table) AddColumn(ctx *sql.Context, column *sql.Column, order *sql.Colum
215223 sql := `ALTER TABLE ` + FullTableName (t .db .catalog , t .db .name , t .name ) + ` ADD COLUMN ` + QuoteIdentifierANSI (column .Name ) + ` ` + typ .name
216224
217225 temporary := t .db .catalog == "temp"
218- var sequenceName , fullSequenceName string
226+ var sequenceName , fullSequenceName , createSequenceStmt string
219227
220228 if column .Default != nil {
221229 typ .mysql .Default = column .Default .String ()
@@ -233,24 +241,13 @@ func (t *Table) AddColumn(ctx *sql.Context, column *sql.Column, order *sql.Colum
233241 return err
234242 }
235243 sequenceName = SequenceNamePrefix + uuid .String ()
236- if temporary {
237- fullSequenceName = `temp.main."` + sequenceName + `"`
238- } else {
239- fullSequenceName = InternalSchemas .SYS .Schema + `."` + sequenceName + `"`
240- }
244+ createSequenceStmt , fullSequenceName = getCreateSequence (temporary , sequenceName )
245+ sqls = append (sqls , createSequenceStmt )
241246
242247 defaultExpr := `nextval('` + fullSequenceName + `')`
243248 sql += " DEFAULT " + defaultExpr
244249 }
245250
246- if column .AutoIncrement {
247- if temporary {
248- sqls = append (sqls , `CREATE TEMP SEQUENCE "` + sequenceName + `"` )
249- } else {
250- sqls = append (sqls , `CREATE SEQUENCE ` + fullSequenceName )
251- }
252- }
253-
254251 sqls = append (sqls , sql )
255252
256253 // DuckDB does not support constraints in ALTER TABLE ADD COLUMN statement,
@@ -387,7 +384,7 @@ func (t *Table) ModifyColumn(ctx *sql.Context, columnName string, column *sql.Co
387384 tableInfoChanged := false
388385
389386 temporary := t .db .catalog == "temp"
390- var sequenceName , fullSequenceName string
387+ var sequenceName , fullSequenceName , createSequenceStmt string
391388
392389 // Handle AUTO_INCREMENT changes
393390 if ! oldColumn .AutoIncrement && column .AutoIncrement {
@@ -398,17 +395,8 @@ func (t *Table) ModifyColumn(ctx *sql.Context, columnName string, column *sql.Co
398395 return err
399396 }
400397 sequenceName = SequenceNamePrefix + uuid .String ()
401- if temporary {
402- fullSequenceName = `temp.main."` + sequenceName + `"`
403- } else {
404- fullSequenceName = InternalSchemas .SYS .Schema + `."` + sequenceName + `"`
405- }
406-
407- if temporary {
408- sqls = append (sqls , `CREATE TEMP SEQUENCE "` + sequenceName + `"` )
409- } else {
410- sqls = append (sqls , `CREATE SEQUENCE ` + fullSequenceName )
411- }
398+ createSequenceStmt , fullSequenceName = getCreateSequence (temporary , sequenceName )
399+ sqls = append (sqls , createSequenceStmt )
412400 sqls = append (sqls , baseSQL + ` SET DEFAULT nextval('` + fullSequenceName + `')` )
413401
414402 // Update table comment with sequence info
@@ -782,7 +770,18 @@ func (t *Table) PeekNextAutoIncrementValue(ctx *sql.Context) (uint64, error) {
782770 var val uint64
783771 err := adapter .QueryRowCatalog (ctx , `SELECT currval('` + t .comment .Meta .Sequence + `') + 1` ).Scan (& val )
784772 if err != nil {
785- return 0 , ErrDuckDB .New (err )
773+ // https://duckdb.org/docs/sql/statements/create_sequence.html#selecting-the-current-value
774+ // > Note that the nextval function must have already been called before calling currval,
775+ // > otherwise a Serialization Error (sequence is not yet defined in this session) will be thrown.
776+ if ! strings .Contains (err .Error (), "sequence is not yet defined in this session" ) {
777+ return 0 , ErrDuckDB .New (err )
778+ }
779+ // If the sequence has not been used yet, we can get the start value from the sequence.
780+ // See getCreateSequence() for the sequence name format.
781+ err = adapter .QueryRowCatalog (ctx , `SELECT start_value FROM duckdb_sequences() WHERE concat(schema_name, '."', sequence_name, '"') = '` + t .comment .Meta .Sequence + `'` ).Scan (& val )
782+ if err != nil {
783+ return 0 , ErrDuckDB .New (err )
784+ }
786785 }
787786
788787 return val , nil
@@ -834,8 +833,67 @@ func (t *Table) AutoIncrementSetter(ctx *sql.Context) sql.AutoIncrementSetter {
834833
835834// setAutoIncrementValue is a helper function to update the sequence value
836835func (t * Table ) setAutoIncrementValue (ctx * sql.Context , value uint64 ) error {
837- _ , err := adapter .ExecCatalog (ctx , `CREATE OR REPLACE SEQUENCE ` + t .comment .Meta .Sequence + ` START WITH ` + strconv .FormatUint (value , 10 ))
838- return err
836+ // DuckDB does not support setting the sequence value directly,
837+ // so we need to recreate the sequence with the new start value.
838+ //
839+ // _, err := adapter.ExecCatalog(ctx, `CREATE OR REPLACE SEQUENCE `+t.comment.Meta.Sequence+` START WITH `+strconv.FormatUint(value, 10))
840+ //
841+ // However, `CREATE OR REPLACE` leads to a Dependency Error,
842+ // while `ALTER TABLE ... ALTER COLUMN ... DROP DEFAULT` deos not remove the dependency:
843+ // https://github.com/duckdb/duckdb/issues/15399
844+ // So we create a new sequence with the new start value and change the auto_increment column to use the new sequence.
845+
846+ // Find the column with the auto_increment property
847+ var autoIncrementColumn * sql.Column
848+ for _ , column := range t .schema .Schema {
849+ if column .AutoIncrement {
850+ autoIncrementColumn = column
851+ break
852+ }
853+ }
854+ if autoIncrementColumn == nil {
855+ return sql .ErrNoAutoIncrementCol
856+ }
857+
858+ // Generate a random sequence name.
859+ uuid , err := uuid .NewRandom ()
860+ if err != nil {
861+ return err
862+ }
863+ sequenceName := SequenceNamePrefix + uuid .String ()
864+
865+ // Create a new sequence with the new start value
866+ temporary := t .db .catalog == "temp"
867+ createSequenceStmt , fullSequenceName := getCreateSequence (temporary , sequenceName )
868+ _ , err = adapter .Exec (ctx , createSequenceStmt + ` START WITH ` + strconv .FormatUint (value , 10 ))
869+ if err != nil {
870+ return ErrDuckDB .New (err )
871+ }
872+
873+ // Update the auto_increment column to use the new sequence
874+ alterStmt := `ALTER TABLE ` + FullTableName (t .db .catalog , t .db .name , t .name ) +
875+ ` ALTER COLUMN ` + QuoteIdentifierANSI (autoIncrementColumn .Name ) +
876+ ` SET DEFAULT nextval('` + fullSequenceName + `')`
877+ if _ , err = adapter .Exec (ctx , alterStmt ); err != nil {
878+ return ErrDuckDB .New (err )
879+ }
880+
881+ // Drop the old sequence
882+ // https://github.com/duckdb/duckdb/issues/15399
883+ // if _, err = adapter.Exec(ctx, "DROP SEQUENCE " + t.comment.Meta.Sequence); err != nil {
884+ // return ErrDuckDB.New(err)
885+ // }
886+
887+ // Update the table comment with the new sequence name
888+ tableInfo := t .comment .Meta
889+ tableInfo .Sequence = fullSequenceName
890+ comment := NewCommentWithMeta (t .comment .Text , tableInfo )
891+ if _ , err = adapter .Exec (ctx , `COMMENT ON TABLE ` + FullTableName (t .db .catalog , t .db .name , t .name )+ ` IS '` + comment .Encode ()+ `'` ); err != nil {
892+ return ErrDuckDB .New (err )
893+ }
894+
895+ t .comment .Meta .Sequence = fullSequenceName
896+ return t .withSchema (ctx )
839897}
840898
841899// autoIncrementSetter implements the AutoIncrementSetter interface
0 commit comments