mirror of
https://github.com/neilotoole/sq.git
synced 2024-12-25 17:25:36 +03:00
implementing SQLDriver.AlterTableAddColumn (#65)
This commit is contained in:
parent
9746f726f6
commit
b3667d60cd
@ -377,7 +377,7 @@ ORDER BY c.TABLE_NAME ASC, c.ORDINAL_POSITION ASC`
|
|||||||
|
|
||||||
tblMetas = append(tblMetas, curTblMeta)
|
tblMetas = append(tblMetas, curTblMeta)
|
||||||
|
|
||||||
rowCountTbl, rowCount, i := curTblName.String, &curTblMeta.RowCount, len(tblMetas)
|
rowCountTbl, rowCount, i := curTblName.String, &curTblMeta.RowCount, len(tblMetas)-1
|
||||||
gRowCount.Go(func() error {
|
gRowCount.Go(func() error {
|
||||||
err := db.QueryRowContext(gctx, "SELECT COUNT(*) FROM `"+rowCountTbl+"`").Scan(rowCount)
|
err := db.QueryRowContext(gctx, "SELECT COUNT(*) FROM `"+rowCountTbl+"`").Scan(rowCount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -394,7 +394,6 @@ ORDER BY c.TABLE_NAME ASC, c.ORDINAL_POSITION ASC`
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
col := &source.ColMetadata{
|
col := &source.ColMetadata{
|
||||||
|
@ -102,6 +102,18 @@ func (d *driveri) CreateTable(ctx context.Context, db sqlz.DB, tblDef *sqlmodel.
|
|||||||
return errz.Err(err)
|
return errz.Err(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AlterTableAddColumn implements driver.SQLDriver.
|
||||||
|
func (d *driveri) AlterTableAddColumn(ctx context.Context, db *sql.DB, tbl string, col string, kind sqlz.Kind) error {
|
||||||
|
q := fmt.Sprintf("ALTER TABLE %q ADD COLUMN %q ", tbl, col) + dbTypeNameFromKind(kind)
|
||||||
|
|
||||||
|
_, err := db.ExecContext(ctx, q)
|
||||||
|
if err != nil {
|
||||||
|
return errz.Wrapf(err, "alter table: failed to add column %q to table %q", col, tbl)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// PrepareInsertStmt implements driver.SQLDriver.
|
// PrepareInsertStmt implements driver.SQLDriver.
|
||||||
func (d *driveri) PrepareInsertStmt(ctx context.Context, db sqlz.DB, destTbl string, destColNames []string, numRows int) (*driver.StmtExecer, error) {
|
func (d *driveri) PrepareInsertStmt(ctx context.Context, db sqlz.DB, destTbl string, destColNames []string, numRows int) (*driver.StmtExecer, error) {
|
||||||
destColsMeta, err := d.getTableRecordMeta(ctx, db, destTbl, destColNames)
|
destColsMeta, err := d.getTableRecordMeta(ctx, db, destTbl, destColNames)
|
||||||
@ -316,11 +328,6 @@ func (d *driveri) Truncate(ctx context.Context, src *source.Source, tbl string,
|
|||||||
return beforeCount, errz.Err(tx.Commit())
|
return beforeCount, errz.Err(tx.Commit())
|
||||||
}
|
}
|
||||||
|
|
||||||
// AlterTableAddColumn implements driver.Driver.
|
|
||||||
func (d *driveri) AlterTableAddColumn(ctx context.Context, db sqlz.DB, tbl string, col string, kind sqlz.Kind, ordinal int) error {
|
|
||||||
return errz.New("not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
// database implements driver.Database.
|
// database implements driver.Database.
|
||||||
type database struct {
|
type database struct {
|
||||||
log lg.Log
|
log lg.Log
|
||||||
|
@ -157,6 +157,18 @@ func (d *driveri) CreateTable(ctx context.Context, db sqlz.DB, tblDef *sqlmodel.
|
|||||||
return errz.Err(err)
|
return errz.Err(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AlterTableAddColumn implements driver.SQLDriver.
|
||||||
|
func (d *driveri) AlterTableAddColumn(ctx context.Context, db *sql.DB, tbl string, col string, kind sqlz.Kind) error {
|
||||||
|
q := fmt.Sprintf("ALTER TABLE %q ADD COLUMN %q ", tbl, col) + dbTypeNameFromKind(kind)
|
||||||
|
|
||||||
|
_, err := db.ExecContext(ctx, q)
|
||||||
|
if err != nil {
|
||||||
|
return errz.Wrapf(err, "alter table: failed to add column %q to table %q", col, tbl)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// PrepareInsertStmt implements driver.SQLDriver.
|
// PrepareInsertStmt implements driver.SQLDriver.
|
||||||
func (d *driveri) PrepareInsertStmt(ctx context.Context, db sqlz.DB, destTbl string, destColNames []string, numRows int) (*driver.StmtExecer, error) {
|
func (d *driveri) PrepareInsertStmt(ctx context.Context, db sqlz.DB, destTbl string, destColNames []string, numRows int) (*driver.StmtExecer, error) {
|
||||||
// Note that the pgx driver doesn't support res.LastInsertId.
|
// Note that the pgx driver doesn't support res.LastInsertId.
|
||||||
@ -396,11 +408,6 @@ func (d *driveri) RecordMeta(colTypes []*sql.ColumnType) (sqlz.RecordMeta, drive
|
|||||||
return recMeta, mungeFn, nil
|
return recMeta, mungeFn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AlterTableAddColumn implements driver.Driver.
|
|
||||||
func (d *driveri) AlterTableAddColumn(ctx context.Context, db sqlz.DB, tbl string, col string, kind sqlz.Kind, ordinal int) error {
|
|
||||||
return errz.New("not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
// database is the postgres implementation of driver.Database.
|
// database is the postgres implementation of driver.Database.
|
||||||
type database struct {
|
type database struct {
|
||||||
log lg.Log
|
log lg.Log
|
||||||
|
@ -249,6 +249,18 @@ func (d *driveri) CreateTable(ctx context.Context, db sqlz.DB, tblDef *sqlmodel.
|
|||||||
return errz.Err(stmt.Close())
|
return errz.Err(stmt.Close())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AlterTableAddColumn implements driver.SQLDriver.
|
||||||
|
func (d *driveri) AlterTableAddColumn(ctx context.Context, db *sql.DB, tbl string, col string, kind sqlz.Kind) error {
|
||||||
|
q := fmt.Sprintf("ALTER TABLE %q ADD COLUMN %q ", tbl, col) + DBTypeForKind(kind)
|
||||||
|
|
||||||
|
_, err := db.ExecContext(ctx, q)
|
||||||
|
if err != nil {
|
||||||
|
return errz.Wrapf(err, "alter table: failed to add column %q to table %q", col, tbl)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// PrepareInsertStmt implements driver.SQLDriver.
|
// PrepareInsertStmt implements driver.SQLDriver.
|
||||||
func (d *driveri) PrepareInsertStmt(ctx context.Context, db sqlz.DB, destTbl string, destColNames []string, numRows int) (*driver.StmtExecer, error) {
|
func (d *driveri) PrepareInsertStmt(ctx context.Context, db sqlz.DB, destTbl string, destColNames []string, numRows int) (*driver.StmtExecer, error) {
|
||||||
destColsMeta, err := d.getTableRecordMeta(ctx, db, destTbl, destColNames)
|
destColsMeta, err := d.getTableRecordMeta(ctx, db, destTbl, destColNames)
|
||||||
@ -356,11 +368,6 @@ func (d *driveri) TableColumnTypes(ctx context.Context, db sqlz.DB, tblName stri
|
|||||||
return colTypes, nil
|
return colTypes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AlterTableAddColumn implements driver.Driver.
|
|
||||||
func (d *driveri) AlterTableAddColumn(ctx context.Context, db sqlz.DB, tbl string, col string, kind sqlz.Kind, ordinal int) error {
|
|
||||||
return errz.New("not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *driveri) getTableRecordMeta(ctx context.Context, db sqlz.DB, tblName string, colNames []string) (sqlz.RecordMeta, error) {
|
func (d *driveri) getTableRecordMeta(ctx context.Context, db sqlz.DB, tblName string, colNames []string) (sqlz.RecordMeta, error) {
|
||||||
colTypes, err := d.TableColumnTypes(ctx, db, tblName, colNames)
|
colTypes, err := d.TableColumnTypes(ctx, db, tblName, colNames)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
BIN
drivers/sqlite3/testdata/sakila.db
vendored
BIN
drivers/sqlite3/testdata/sakila.db
vendored
Binary file not shown.
@ -248,6 +248,18 @@ func (d *driveri) CreateTable(ctx context.Context, db sqlz.DB, tblDef *sqlmodel.
|
|||||||
return errz.Err(err)
|
return errz.Err(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AlterTableAddColumn implements driver.SQLDriver.
|
||||||
|
func (d *driveri) AlterTableAddColumn(ctx context.Context, db *sql.DB, tbl string, col string, kind sqlz.Kind) error {
|
||||||
|
q := fmt.Sprintf("ALTER TABLE %q ADD %q ", tbl, col) + dbTypeNameFromKind(kind)
|
||||||
|
|
||||||
|
_, err := db.ExecContext(ctx, q)
|
||||||
|
if err != nil {
|
||||||
|
return errz.Wrapf(err, "alter table: failed to add column %q to table %q", col, tbl)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// CopyTable implements driver.SQLDriver.
|
// CopyTable implements driver.SQLDriver.
|
||||||
func (d *driveri) CopyTable(ctx context.Context, db sqlz.DB, fromTable, toTable string, copyData bool) (int64, error) {
|
func (d *driveri) CopyTable(ctx context.Context, db sqlz.DB, fromTable, toTable string, copyData bool) (int64, error) {
|
||||||
var stmt string
|
var stmt string
|
||||||
@ -317,11 +329,6 @@ func (d *driveri) PrepareUpdateStmt(ctx context.Context, db sqlz.DB, destTbl str
|
|||||||
return execer, nil
|
return execer, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AlterTableAddColumn implements driver.Driver.
|
|
||||||
func (d *driveri) AlterTableAddColumn(ctx context.Context, db sqlz.DB, tbl string, col string, kind sqlz.Kind, ordinal int) error {
|
|
||||||
return errz.New("not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *driveri) getTableColsMeta(ctx context.Context, db sqlz.DB, tblName string, colNames []string) (sqlz.RecordMeta, error) {
|
func (d *driveri) getTableColsMeta(ctx context.Context, db sqlz.DB, tblName string, colNames []string) (sqlz.RecordMeta, error) {
|
||||||
// SQLServer has this unusual incantation for its LIMIT equivalent:
|
// SQLServer has this unusual incantation for its LIMIT equivalent:
|
||||||
//
|
//
|
||||||
|
@ -143,8 +143,10 @@ type SQLDriver interface {
|
|||||||
// or equivalent clause is added, if supported.
|
// or equivalent clause is added, if supported.
|
||||||
DropTable(ctx context.Context, db sqlz.DB, tbl string, ifExists bool) error
|
DropTable(ctx context.Context, db sqlz.DB, tbl string, ifExists bool) error
|
||||||
|
|
||||||
// AlterTableAddColumn adds column col to tbl at position ordinal.
|
// AlterTableAddColumn adds column col to tbl. The column is appended
|
||||||
AlterTableAddColumn(ctx context.Context, db sqlz.DB, tbl string, col string, kind sqlz.Kind, ordinal int) error
|
// to the list of columns (that is, the column position cannot be
|
||||||
|
// specified).
|
||||||
|
AlterTableAddColumn(ctx context.Context, db *sql.DB, tbl string, col string, kind sqlz.Kind) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Database models a database handle. It is conceptually equivalent to
|
// Database models a database handle. It is conceptually equivalent to
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/neilotoole/sq/drivers/sqlite3"
|
"github.com/neilotoole/sq/drivers/sqlite3"
|
||||||
"github.com/neilotoole/sq/drivers/sqlserver"
|
"github.com/neilotoole/sq/drivers/sqlserver"
|
||||||
"github.com/neilotoole/sq/drivers/xlsx"
|
"github.com/neilotoole/sq/drivers/xlsx"
|
||||||
|
"github.com/neilotoole/sq/libsq/sqlz"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@ -437,3 +438,34 @@ func TestDatabase_SourceMetadata(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSQLDriver_AlterTableAddColumn(t *testing.T) {
|
||||||
|
testCases := []string{sakila.SL3, sakila.Pg, sakila.MS}
|
||||||
|
|
||||||
|
for _, handle := range testCases {
|
||||||
|
handle := handle
|
||||||
|
|
||||||
|
t.Run(handle, func(t *testing.T) {
|
||||||
|
th, src, dbase, drvr := testh.NewWith(t, handle)
|
||||||
|
|
||||||
|
// Make a copy of the table to play with
|
||||||
|
tbl := th.CopyTable(true, src, sakila.TblActor, "", true)
|
||||||
|
|
||||||
|
const wantCol, wantKind = "col_int", sqlz.KindInt
|
||||||
|
wantCols := append(sakila.TblActorCols(), wantCol)
|
||||||
|
wantKinds := append(sakila.TblActorColKinds(), wantKind)
|
||||||
|
|
||||||
|
err := drvr.AlterTableAddColumn(th.Context, dbase.DB(), tbl, wantCol, wantKind)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
sink, err := th.QuerySQL(src, "SELECT * FROM "+tbl)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
gotCols := sink.RecMeta.Names()
|
||||||
|
require.Equal(t, wantCols, gotCols)
|
||||||
|
|
||||||
|
gotKinds := sink.RecMeta.Kinds()
|
||||||
|
require.Equal(t, wantKinds, gotKinds)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user