detect autoincrement column, fix lastID in upsert when update doesnt change anything

This commit is contained in:
Alex Grintsvayg 2017-06-12 14:02:04 -04:00
parent 09c585cdb1
commit ed423a3606
10 changed files with 63 additions and 6 deletions

View file

@ -62,6 +62,10 @@ func (m *MockDriver) UniqueKeyInfo(schema, tableName string) ([]bdb.UniqueKey, e
return []bdb.UniqueKey{}, nil
}
func (m *MockDriver) AutoincrementInfo(schema, tableName string) (string, error) {
return "", nil
}
// ForeignKeyInfo returns a list of mock foreignkeys
func (m *MockDriver) ForeignKeyInfo(schema, tableName string) ([]bdb.ForeignKey, error) {
return map[string][]bdb.ForeignKey{

View file

@ -245,6 +245,10 @@ func (m *MSSQLDriver) UniqueKeyInfo(schema, tableName string) ([]bdb.UniqueKey,
return []bdb.UniqueKey{}, errors.New("not implemented")
}
func (m *MSSQLDriver) AutoincrementInfo(schema, tableName string) (string, error) {
return "", errors.New("not implemented")
}
// ForeignKeyInfo retrieves the foreign keys for a given table name.
func (m *MSSQLDriver) ForeignKeyInfo(schema, tableName string) ([]bdb.ForeignKey, error) {
var fkeys []bdb.ForeignKey

View file

@ -272,6 +272,38 @@ func (m *MySQLDriver) UniqueKeyInfo(schema, tableName string) ([]bdb.UniqueKey,
return ukeys, nil
}
// AutoincrementInfo retrieves the autoincrement column for a given table name, if one exists.
func (m *MySQLDriver) AutoincrementInfo(schema, tableName string) (string, error) {
query := `
select column_name
from information_schema.columns
where table_schema = ? and table_name = ? and extra like "%auto_increment%"
`
var rows *sql.Rows
var err error
if rows, err = m.dbConn.Query(query, schema, tableName); err != nil {
return "", err
}
for rows.Next() {
var column string
err = rows.Scan(&column)
if err != nil {
return "", err
}
return column, nil
}
if err = rows.Err(); err != nil {
return "", err
}
return "", nil
}
// ForeignKeyInfo retrieves the foreign keys for a given table name.
func (m *MySQLDriver) ForeignKeyInfo(schema, tableName string) ([]bdb.ForeignKey, error) {
var fkeys []bdb.ForeignKey

View file

@ -270,6 +270,10 @@ func (p *PostgresDriver) UniqueKeyInfo(schema, tableName string) ([]bdb.UniqueKe
return []bdb.UniqueKey{}, errors.New("not implemented")
}
func (p *PostgresDriver) AutoincrementInfo(schema, tableName string) (string, error) {
return "", errors.New("not implemented")
}
// ForeignKeyInfo retrieves the foreign keys for a given table name.
func (p *PostgresDriver) ForeignKeyInfo(schema, tableName string) ([]bdb.ForeignKey, error) {
var fkeys []bdb.ForeignKey

View file

@ -10,6 +10,7 @@ type Interface interface {
Columns(schema, tableName string) ([]Column, error)
PrimaryKeyInfo(schema, tableName string) (*PrimaryKey, error)
UniqueKeyInfo(schema, tableName string) ([]UniqueKey, error)
AutoincrementInfo(schema, tableName string) (string, error)
ForeignKeyInfo(schema, tableName string) ([]ForeignKey, error)
// TranslateColumnType takes a Database column type and returns a go column type.
@ -72,6 +73,10 @@ func Tables(db Interface, schema string, whitelist, blacklist []string) ([]Table
return nil, errors.Wrapf(err, "unable to fetch table fkey info (%s)", name)
}
if t.AutoIncrementColumn, err = db.AutoincrementInfo(schema, name); err != nil {
return nil, errors.Wrapf(err, "unable to fetch table autoincrement info (%s)", name)
}
setIsJoinTable(&t)
tables = append(tables, t)

View file

@ -8,7 +8,9 @@ type Table struct {
// For dbs with real schemas, like Postgres.
// Example value: "schema_name"."table_name"
SchemaName string
Columns []Column
AutoIncrementColumn string
PKey *PrimaryKey
UKeys []UniqueKey

View file

@ -8,13 +8,13 @@ import (
"strings"
"github.com/kat-co/vala"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/lbryio/sqlboiler/bdb/drivers"
"github.com/lbryio/sqlboiler/boilingcore"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
const sqlBoilerVersion = "2.3.0"
const sqlBoilerVersion = "2.4.0+lbry"
var (
cmdState *boilingcore.State

View file

@ -190,7 +190,7 @@ func buildUpdateQuery(q *Query) (*bytes.Buffer, []interface{}) {
}
// BuildUpsertQueryMySQL builds a SQL statement string using the upsertData provided.
func BuildUpsertQueryMySQL(dia Dialect, tableName string, update, whitelist []string) string {
func BuildUpsertQueryMySQL(dia Dialect, tableName string, update, whitelist []string, autoIncrementCol string) string {
whitelist = strmangle.IdentQuoteSlice(dia.LQ, dia.RQ, whitelist)
buf := strmangle.GetBuffer()
@ -220,6 +220,11 @@ func BuildUpsertQueryMySQL(dia Dialect, tableName string, update, whitelist []st
strmangle.Placeholders(dia.IndexPlaceholders, len(whitelist), 1, 1),
)
// https://stackoverflow.com/questions/778534/mysql-on-duplicate-key-last-insert-id
if autoIncrementCol != "" {
buf.WriteString(autoIncrementCol + " = LAST_INSERT_ID(" + autoIncrementCol + "), ")
}
for i, v := range update {
if i != 0 {
buf.WriteByte(',')

View file

@ -10,6 +10,7 @@ var (
{{$varNameSingular}}ColumnsWithoutDefault = []string{{"{"}}{{.Table.Columns | filterColumnsByDefault false | columnNames | stringMap .StringFuncs.quoteWrap | join ","}}{{"}"}}
{{$varNameSingular}}ColumnsWithDefault = []string{{"{"}}{{.Table.Columns | filterColumnsByDefault true | columnNames | stringMap .StringFuncs.quoteWrap | join ","}}{{"}"}}
{{$varNameSingular}}PrimaryKeyColumns = []string{{"{"}}{{.Table.PKey.Columns | stringMap .StringFuncs.quoteWrap | join ", "}}{{"}"}}
{{$varNameSingular}}AutoIncrementColumn = "{{.Table.AutoIncrementColumn }}"
)
type (

View file

@ -115,7 +115,7 @@ func (o *{{$tableNameSingular}}) Upsert(exec boil.Executor, {{if eq .DriverName
}
cache.query = queries.BuildUpsertQueryPostgres(dialect, "{{$schemaTable}}", updateOnConflict, ret, update, conflict, insert)
{{else if eq .DriverName "mysql"}}
cache.query = queries.BuildUpsertQueryMySQL(dialect, "{{.Table.Name}}", update, insert)
cache.query = queries.BuildUpsertQueryMySQL(dialect, "{{.Table.Name}}", update, insert, {{$varNameSingular}}AutoIncrementColumn)
cache.retQuery = fmt.Sprintf(
"SELECT %s FROM {{.LQ}}{{.Table.Name}}{{.RQ}} WHERE {{whereClause .LQ .RQ 0 .Table.PKey.Columns}}",
strings.Join(strmangle.IdentQuoteSlice(dialect.LQ, dialect.RQ, ret), ","),