Skip to content

Commit

Permalink
Revive ability to read dolt_schema table which predates 0.19.0
Browse files Browse the repository at this point in the history
  • Loading branch information
macneale4 committed Jul 25, 2024
1 parent 38555b7 commit ebfd472
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 16 deletions.
2 changes: 1 addition & 1 deletion go/libraries/doltcore/sqle/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,7 @@ func (db Database) getTableInsensitive(ctx *sql.Context, head *doltdb.Commit, ds
dt = NewEmptySchemaTable()
} else {
writeTable := backingTable.(*WritableDoltTable)
dt, err = NewSchemaTable(ctx, db, writeTable)
dt, err = NewSchemaTable(writeTable)
if err != nil {
return nil, false, err
}
Expand Down
41 changes: 29 additions & 12 deletions go/libraries/doltcore/sqle/schema_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,15 @@ func (st *SchemaTable) String() string {

func (st *SchemaTable) Schema() sql.Schema {
if st.backingTable == nil {
// No backing table; return an current schema.
// No backing table; return a current schema.
return SchemaTableSqlSchema().Schema
}

if !st.backingTable.Schema().Contains(doltdb.SchemasTablesExtraCol, doltdb.SchemasTableName) {
// No Extra column; return an ancient schema.
return SchemaTableAncientSqlSchema()
}

if !st.backingTable.Schema().Contains(doltdb.SchemasTablesSqlModeCol, doltdb.SchemasTableName) {
// No SQL_MODE column; return an old schema.
return SchemaTableV1SqlSchema()
Expand Down Expand Up @@ -163,6 +168,22 @@ func SchemaTableV1SqlSchema() sql.Schema {
return sqlSchema.Schema
}

// dolt_schemas columns, for dolt_schemas <= 0.19.0.
func SchemaTableAncientSqlSchema() sql.Schema {
var schemasTableCols = schema.NewColCollection(
mustNewColWithTypeInfo(doltdb.SchemasTablesTypeCol, schema.DoltSchemasTypeTag, typeinfo.CreateVarStringTypeFromSqlType(mustCreateStringType(query.Type_VARCHAR, 64, sql.Collation_utf8mb4_0900_ai_ci)), true, "", false, ""),
mustNewColWithTypeInfo(doltdb.SchemasTablesNameCol, schema.DoltSchemasNameTag, typeinfo.CreateVarStringTypeFromSqlType(mustCreateStringType(query.Type_VARCHAR, 64, sql.Collation_utf8mb4_0900_ai_ci)), true, "", false, ""),
mustNewColWithTypeInfo(doltdb.SchemasTablesFragmentCol, schema.DoltSchemasFragmentTag, typeinfo.CreateVarStringTypeFromSqlType(gmstypes.LongText), false, "", false, ""),
)

legacy := schema.MustSchemaFromCols(schemasTableCols)
sqlSchema, err := sqlutil.FromDoltSchema("", doltdb.SchemasTableName, legacy)
if err != nil {
panic(err) // should never happen
}
return sqlSchema.Schema
}

// dolt_schemas columns
func SchemaTableSchema() schema.Schema {
var schemasTableCols = schema.NewColCollection(
Expand All @@ -180,11 +201,7 @@ func NewEmptySchemaTable() sql.Table {
return &SchemaTable{}
}

func NewSchemaTable(ctx *sql.Context, db Database, backingTable *WritableDoltTable) (sql.Table, error) {
if !backingTable.Schema().Contains(doltdb.SchemasTablesExtraCol, doltdb.SchemasTableName) {
return nil, fmt.Errorf("cannot migrate dolt_schemas table from v0.19.1 or earlier")
}

func NewSchemaTable(backingTable *WritableDoltTable) (sql.Table, error) {
return &SchemaTable{backingTable: backingTable}, nil
}

Expand Down Expand Up @@ -221,10 +238,9 @@ func getOrCreateDoltSchemasTable(ctx *sql.Context, db Database) (retTbl *Writabl

if wrapper.backingTable != nil {
schemasTable := wrapper.backingTable
// Old schemas are missing the `extra` column. Very ancient. Provide error message and bail.
if !schemasTable.Schema().Contains(doltdb.SchemasTablesExtraCol, doltdb.SchemasTableName) {
return nil, fmt.Errorf("cannot migrate dolt_schemas table from v0.19.1 or earlier")
} else if !schemasTable.Schema().Contains(doltdb.SchemasTablesSqlModeCol, doltdb.SchemasTableName) {

if !schemasTable.Schema().Contains(doltdb.SchemasTablesExtraCol, doltdb.SchemasTableName) ||
!schemasTable.Schema().Contains(doltdb.SchemasTablesSqlModeCol, doltdb.SchemasTableName) {
return migrateOldSchemasTableToNew(ctx, db, schemasTable)
} else {
return schemasTable, nil
Expand Down Expand Up @@ -288,8 +304,9 @@ func migrateOldSchemasTableToNew(ctx *sql.Context, db Database, schemasTable *Wr
newRow[0] = sqlRow[typeIdx]
newRow[1] = sqlRow[nameIdx]
newRow[2] = sqlRow[fragmentIdx]
newRow[3] = sqlRow[extraIdx]

if extraIdx >= 0 {
newRow[3] = sqlRow[extraIdx]
}
if sqlModeIdx >= 0 {
newRow[4] = sqlRow[sqlModeIdx]
}
Expand Down
45 changes: 42 additions & 3 deletions go/libraries/doltcore/sqle/schema_table_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ package sqle

import (
"context"
"io"
"testing"

"github.com/dolthub/go-mysql-server/sql"
gmstypes "github.com/dolthub/go-mysql-server/sql/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
Expand All @@ -45,10 +47,47 @@ func TestAncientSchemaTableError(t *testing.T) {
}), sql.Collation_Default, "")
require.NoError(t, err)

_, _, err = db.GetTableInsensitive(ctx, doltdb.SchemasTableName)
require.Error(t, err)
require.Contains(t, err.Error(), "cannot migrate dolt_schemas table from v0.19.1 or earlier")
sqlTbl, found, err := db.GetTableInsensitive(ctx, doltdb.SchemasTableName)
require.NoError(t, err)
require.True(t, found)

wrapper, ok := sqlTbl.(*SchemaTable)
require.True(t, ok)
require.NotNil(t, wrapper.backingTable)
// unmodified dolt_schemas table.
require.Equal(t, 3, len(wrapper.backingTable.Schema()))

inserter := wrapper.backingTable.Inserter(ctx)
err = inserter.Insert(ctx, sql.Row{"view", "view1", "SELECT v1 FROM test;"})
require.NoError(t, err)
err = inserter.Insert(ctx, sql.Row{"view", "view2", "SELECT v2 FROM test;"})
require.NoError(t, err)
err = inserter.Close(ctx)
require.NoError(t, err)

tbl, err := getOrCreateDoltSchemasTable(ctx, db) // removes the old table and recreates it with the new schema
require.NoError(t, err)

iter, err := SqlTableToRowIter(ctx, tbl.DoltTable, nil)
require.NoError(t, err)

var rows []sql.Row
for {
row, err := iter.Next(ctx)
if err == io.EOF {
break
}

require.NoError(t, err)
rows = append(rows, row)
}

require.NoError(t, iter.Close(ctx))
expectedRows := []sql.Row{
{"view", "view1", "SELECT v1 FROM test;", nil, nil},
{"view", "view2", "SELECT v2 FROM test;", nil, nil},
}
assert.Equal(t, expectedRows, rows)
}

func TestV1SchemasTable(t *testing.T) {
Expand Down
19 changes: 19 additions & 0 deletions integration-tests/bats/triggers.bats
Original file line number Diff line number Diff line change
Expand Up @@ -184,3 +184,22 @@ SQL
[ "$status" -eq "0" ]
[[ "$output" =~ "type,name,fragment,extra,sql_mode" ]] || false
}

@test "triggers: Upgrade oldest dolt_schemas" {
rm -rf .dolt

# old_old_dolt_schemas was created using v0.19.0, which is pre-extra column.
cp -a $BATS_TEST_DIRNAME/helper/old_old_dolt_schemas/. ./.dolt/

run dolt sql -q "SELECT * FROM dolt_schemas" -r=csv
[ "$status" -eq "0" ]

[[ "$output" =~ "type,name,fragment" ]] || false
[[ "$output" =~ "view,view1,SELECT 2+2 FROM dual" ]] || false

dolt sql -q "CREATE VIEW another_view AS SELECT 3+3"

run dolt sql -q "SELECT * FROM dolt_schemas" -r=csv
[ "$status" -eq "0" ]
[[ "$output" =~ "type,name,fragment,extra,sql_mode" ]] || false
}

0 comments on commit ebfd472

Please sign in to comment.