Skip to content
This repository was archived by the owner on Mar 4, 2025. It is now read-only.

Commit 65146a6

Browse files
committed
common: Fix INSERT statements generated by diff code
This fixes a couple of issues with the INSERT statements generated by the database diff code. It also makes the generated SQL safer by explicitly naming the columns of the table. Finally it makes sure the INSERT statements work for tables with generated columns.
1 parent c64b5d1 commit 65146a6

File tree

2 files changed

+44
-15
lines changed

2 files changed

+44
-15
lines changed

common/diff.go

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -230,23 +230,28 @@ func diffSingleObject(sdb *sqlite.Conn, objectName string, objectType string) (b
230230
}
231231

232232
func dataDiffForAllTableRows(sdb *sqlite.Conn, schemaName string, tableName string, action DiffType, includeSql bool) (diff []DataDiff, err error) {
233-
// Retrieve a list of all primary key columns in this table
234-
pk, err := GetPrimaryKeyColumns(sdb, schemaName, tableName)
233+
// Retrieve a list of all primary key columns and other columns in this table
234+
pk, implicit_pk, other_columns, err := GetPrimaryKeyAndOtherColumns(sdb, schemaName, tableName)
235235
if err != nil {
236236
return nil, err
237237
}
238238

239239
// Escape all the column names
240-
var pk_escaped []string
240+
var pk_escaped, other_escaped []string
241241
for _, v := range pk {
242242
pk_escaped = append(pk_escaped, EscapeId(v))
243243
}
244+
for _, v := range other_columns {
245+
other_escaped = append(other_escaped, EscapeId(v))
246+
}
244247

245248
// Prepare query for the primary keys of all rows in this table. Only include the rest of the data
246249
// in the rows if required
247250
query := "SELECT " + strings.Join(pk_escaped, ",")
248251
if includeSql && action == ACTION_ADD {
249-
query += ", *"
252+
if len(other_escaped) > 0 {
253+
query += "," + strings.Join(other_escaped, ",")
254+
}
250255
}
251256
query += " FROM " + EscapeId(schemaName) + "." + EscapeId(tableName)
252257

@@ -265,7 +270,14 @@ func dataDiffForAllTableRows(sdb *sqlite.Conn, schemaName string, tableName stri
265270
if action == ACTION_DELETE {
266271
d.Sql = "DELETE FROM " + EscapeId(tableName) + " WHERE "
267272
} else if action == ACTION_ADD {
268-
d.Sql = "INSERT INTO " + EscapeId(tableName) + " VALUES("
273+
var insert_columns []string
274+
// Don't include rowid column, only regular PK
275+
if !implicit_pk {
276+
insert_columns = append(insert_columns, pk_escaped...)
277+
}
278+
insert_columns = append(insert_columns, other_escaped...)
279+
280+
d.Sql = "INSERT INTO " + EscapeId(tableName) + "(" + strings.Join(insert_columns, ",") + ") VALUES("
269281
}
270282
}
271283

common/sqlite.go

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -962,25 +962,36 @@ func EscapeValue(val DataValue) string {
962962
}
963963
}
964964

965-
// Figure out the primary key columns of a table.
965+
// Figure out the primary key columns and the other columns of a table.
966966
// The schema and table parameters specify the schema and table names to use.
967-
func GetPrimaryKeyColumns(sdb *sqlite.Conn, schema string, table string) (pks []string, err error) {
967+
// This function returns two arrays: One containing the list of primary key columns in the same order as they
968+
// are used in the primary key. The other array contains a list of all the other, non-primary key columns.
969+
// Generated columns are ignored completely. If the primary key exists only implicitly, i.e. it's the rowid
970+
// column, the implicit_pk flag is set to true.
971+
func GetPrimaryKeyAndOtherColumns(sdb *sqlite.Conn, schema string, table string) (pks []string, implicit_pk bool, other []string, err error) {
968972
// Prepare query
969973
var stmt *sqlite.Stmt
970974
stmt, err = sdb.Prepare("PRAGMA " + EscapeId(schema) + ".table_info(" + EscapeId(table) + ")")
971975
if err != nil {
972-
log.Printf("Error when preparing statement in GetPrimaryKey(): %s\n", err)
973-
return nil, err
976+
log.Printf("Error when preparing statement in GetPrimaryKeyAndOtherColumns(): %s\n", err)
977+
return nil, false, nil, err
974978
}
975979
defer stmt.Finalize()
976980

977-
// Execute query and retrieve all primary key columns
981+
// Execute query and retrieve all columns
978982
primaryKeyColumns := make(map[int]string)
979983
var hasColumnRowid, hasColumn_Rowid_, hasColumnOid bool
980984
err = stmt.Select(func(s *sqlite.Stmt) error {
985+
// Get name and primary key order
981986
columnName, _ := s.ScanText(1)
982987
pkOrder, _, _ := s.ScanInt(5)
983-
if pkOrder > 0 {
988+
989+
// Is this column part of the primary key?
990+
if pkOrder == 0 {
991+
// It's not
992+
other = append(other, columnName)
993+
} else {
994+
// It is
984995
primaryKeyColumns[pkOrder] = columnName
985996
}
986997

@@ -995,15 +1006,17 @@ func GetPrimaryKeyColumns(sdb *sqlite.Conn, schema string, table string) (pks []
9951006
return nil
9961007
})
9971008
if err != nil {
998-
log.Printf("Error when retrieving rows in GetPrimaryKey(): %s\n", err)
999-
return nil, err
1009+
log.Printf("Error when retrieving rows in GetPrimaryKeyAndOtherColumns(): %s\n", err)
1010+
return nil, false, nil, err
10001011
}
10011012

10021013
// Did we get any primary key columns? If not, this table has only an implicit primary key which
10031014
// is accessible by the name rowid, _rowid_, or oid
10041015
if len(primaryKeyColumns) > 0 {
10051016
// Explicit primary key
10061017

1018+
implicit_pk = false
1019+
10071020
// Sort the columns by their order in the PK
10081021
keys := make([]int, 0, len(primaryKeyColumns))
10091022
for k := range primaryKeyColumns {
@@ -1017,6 +1030,9 @@ func GetPrimaryKeyColumns(sdb *sqlite.Conn, schema string, table string) (pks []
10171030
}
10181031
} else {
10191032
// Implicit primary key
1033+
1034+
implicit_pk = true
1035+
10201036
if !hasColumnRowid {
10211037
pks = append(pks, "rowid")
10221038
} else if !hasColumn_Rowid_ {
@@ -1025,8 +1041,9 @@ func GetPrimaryKeyColumns(sdb *sqlite.Conn, schema string, table string) (pks []
10251041
pks = append(pks, "oid")
10261042
} else {
10271043
log.Printf("Unreachable rowid column in GetPrimaryKey()\n")
1028-
return nil, errors.New("Unreachable rowid column")
1044+
return nil, false, nil, errors.New("Unreachable rowid column")
10291045
}
10301046
}
1031-
return pks, nil
1047+
1048+
return pks, implicit_pk, other, nil
10321049
}

0 commit comments

Comments
 (0)