diff --git a/codegen/code_generator.go b/codegen/code_generator.go index 3ced120..bf843d2 100644 --- a/codegen/code_generator.go +++ b/codegen/code_generator.go @@ -595,38 +595,38 @@ func (g *Generator) buildUpdateByPK(importPkgs *Package, t *tableInfo) { func (g *Generator) valuer(importPkgs *Package, goPath string, t types.Type) string { utype, isPtr := underlyingType(t) if columnType, ok := g.columnTypes[t.String()]; ok && columnType.Valuer != "" { - return Expr(columnType.Valuer).Format(importPkgs, ExprParams{GoPath: goPath}) + return Expr(columnType.Valuer).Format(importPkgs, ExprParams{GoPath: goPath, IsPtr: isPtr}) } else if _, wrong := types.MissingMethod(utype, goSqlValuer, true); wrong { if isPtr { - return Expr("(database/sql/driver.Valuer)({{goPath}})").Format(importPkgs, ExprParams{GoPath: goPath}) + return Expr("(database/sql/driver.Valuer)({{goPath}})").Format(importPkgs, ExprParams{GoPath: goPath, IsPtr: isPtr}) } - return Expr("(database/sql/driver.Valuer)({{goPath}})").Format(importPkgs, ExprParams{GoPath: goPath}) + return Expr("(database/sql/driver.Valuer)({{goPath}})").Format(importPkgs, ExprParams{GoPath: goPath, IsPtr: isPtr}) } else if columnType, ok := g.columnDataType(t); ok && columnType.Valuer != "" { - return Expr(columnType.Valuer).Format(importPkgs, ExprParams{GoPath: goPath, Len: arraySize(t)}) + return Expr(columnType.Valuer).Format(importPkgs, ExprParams{GoPath: goPath, IsPtr: isPtr, Len: arraySize(t)}) } else if isImplemented(utype, textMarshaler) { - return Expr("github.com/si3nloong/sqlgen/sequel/types.TextMarshaler({{goPath}})").Format(importPkgs, ExprParams{GoPath: goPath}) + return Expr("github.com/si3nloong/sqlgen/sequel/types.TextMarshaler({{goPath}})").Format(importPkgs, ExprParams{GoPath: goPath, IsPtr: isPtr}) } - return Expr(g.defaultColumnTypes["*"].Valuer).Format(importPkgs, ExprParams{GoPath: goPath}) + return Expr(g.defaultColumnTypes["*"].Valuer).Format(importPkgs, ExprParams{GoPath: goPath, IsPtr: isPtr}) } func (g *Generator) scanner(importPkgs *Package, goPath string, t types.Type) string { ptr, isPtr := pointerType(t) if columnType, ok := g.columnTypes[t.String()]; ok && columnType.Scanner != "" { - return Expr(columnType.Scanner).Format(importPkgs, ExprParams{GoPath: goPath}) + return Expr(columnType.Scanner).Format(importPkgs, ExprParams{GoPath: goPath, IsPtr: isPtr}) } else if isImplemented(ptr, goSqlScanner) { if isPtr { - return Expr("(database/sql.Scanner)({{goPath}})").Format(importPkgs, ExprParams{GoPath: goPath}) + return Expr("(database/sql.Scanner)({{goPath}})").Format(importPkgs, ExprParams{GoPath: goPath, IsPtr: isPtr}) } - return Expr("(database/sql.Scanner)({{addrOfGoPath}})").Format(importPkgs, ExprParams{GoPath: goPath}) + return Expr("(database/sql.Scanner)({{addrOfGoPath}})").Format(importPkgs, ExprParams{GoPath: goPath, IsPtr: isPtr}) } else if columnType, ok := g.columnDataType(t); ok && columnType.Scanner != "" { - return Expr(columnType.Scanner).Format(importPkgs, ExprParams{GoPath: goPath, Len: arraySize(t)}) + return Expr(columnType.Scanner).Format(importPkgs, ExprParams{GoPath: goPath, IsPtr: isPtr, Len: arraySize(t)}) } else if isImplemented(ptr, textUnmarshaler) { if isPtr { - return Expr("github.com/si3nloong/sqlgen/sequel/types.TextUnmarshaler({{goPath}})").Format(importPkgs, ExprParams{GoPath: goPath}) + return Expr("github.com/si3nloong/sqlgen/sequel/types.TextUnmarshaler({{goPath}})").Format(importPkgs, ExprParams{GoPath: goPath, IsPtr: isPtr}) } - return Expr("github.com/si3nloong/sqlgen/sequel/types.TextUnmarshaler({{addrOfGoPath}})").Format(importPkgs, ExprParams{GoPath: goPath}) + return Expr("github.com/si3nloong/sqlgen/sequel/types.TextUnmarshaler({{addrOfGoPath}})").Format(importPkgs, ExprParams{GoPath: goPath, IsPtr: isPtr}) } - return Expr(g.defaultColumnTypes["*"].Scanner).Format(importPkgs, ExprParams{GoPath: goPath}) + return Expr(g.defaultColumnTypes["*"].Scanner).Format(importPkgs, ExprParams{GoPath: goPath, IsPtr: isPtr}) } func (g *Generator) sqlScanner(f *columnInfo) string { diff --git a/codegen/codegen.go b/codegen/codegen.go index 8b2819d..b144517 100644 --- a/codegen/codegen.go +++ b/codegen/codegen.go @@ -638,7 +638,7 @@ func parseGoPackage( return fmt.Errorf("sqlgen: struct %q has duplicate column name %q in directory %q", s.name, column.columnName, dir) } - if v, ok := column.getOption(TagOptionSize); ok { + if v, ok := column.getOptionValue(TagOptionSize); ok { column.size, err = strconv.Atoi(v) if err != nil { return fmt.Errorf(`sqlgen: invalid size value %q %w`, v, err) diff --git a/codegen/dialect/dialect.go b/codegen/dialect/dialect.go index 04d00e0..59d43c3 100644 --- a/codegen/dialect/dialect.go +++ b/codegen/dialect/dialect.go @@ -47,13 +47,21 @@ type ColumnType struct { SQLValuer string } +type Index interface { + // Indexed columns + Columns() []string + + // Whether the index is unique + Unique() bool +} + type Schema interface { DBName() string TableName() string Columns() []string Keys() []string ColumnGoType(i int) GoColumn - Indexes() []string + RangeIndex(func(Index, int)) } type GoColumn interface { @@ -84,12 +92,11 @@ type GoColumn interface { // Determine whether this column is auto increment or not AutoIncr() bool - Size() int - // Key is to identify whether column is primary or foreign key Key() bool - // Implements(*types.Interface) (*types.Func, bool) + // Column size that declared by user + Size() int } func RegisterDialect(name string, d Dialect) { diff --git a/codegen/dialect/postgres/column.go b/codegen/dialect/postgres/column.go index 8839eff..5390e94 100644 --- a/codegen/dialect/postgres/column.go +++ b/codegen/dialect/postgres/column.go @@ -18,14 +18,19 @@ type column struct { DatetimePrecision sql.NullInt64 } +func (c column) Equal(v column) bool { + return c.Name == v.Name && + c.IsNullable == v.IsNullable +} + func (c column) ColumnType() string { switch c.DataType { case "varchar": - if c.CharacterMaxLength.Valid { + if c.CharacterMaxLength.Valid && c.CharacterMaxLength.Int64 > 0 { return fmt.Sprintf("%s(%d)", c.DataType, c.CharacterMaxLength.Int64) } case "timestamptz": - if c.DatetimePrecision.Valid { + if c.DatetimePrecision.Valid && c.DatetimePrecision.Int64 > 0 { return fmt.Sprintf("%s(%d)", c.DataType, c.DatetimePrecision.Int64) } } @@ -44,7 +49,7 @@ func (s *postgresDriver) tableColumns(ctx context.Context, sqlConn *sql.DB, dbNa FROM information_schema.columns WHERE - table_schema = $1 AND + table_catalog = $1 AND table_name = $2 ORDER BY ordinal_position;`, dbName, tableName) diff --git a/codegen/dialect/postgres/column_type.go b/codegen/dialect/postgres/column_type.go index 6c7f880..4df4c5d 100644 --- a/codegen/dialect/postgres/column_type.go +++ b/codegen/dialect/postgres/column_type.go @@ -11,34 +11,40 @@ import ( ) func (s *postgresDriver) ColumnDataTypes() map[string]*dialect.ColumnType { - return map[string]*dialect.ColumnType{ + dataTypes := map[string]*dialect.ColumnType{ "rune": { DataType: s.columnDataType("char(1)"), Valuer: "(string)({{goPath}})", Scanner: "{{addrOfGoPath}}", }, "string": { - DataType: s.columnDataType("varchar(255)", ""), - Valuer: "(string)({{goPath}})", - Scanner: "github.com/si3nloong/sqlgen/sequel/types.String({{addrOfGoPath}})", + DataType: func(col dialect.GoColumn) string { + size := 255 + if n := col.Size(); n > 0 { + size = n + } + return fmt.Sprintf("varchar(%d)", size) + }, + Valuer: "(string)({{goPath}})", + Scanner: "github.com/si3nloong/sqlgen/sequel/types.String({{addrOfGoPath}})", }, "bool": { - DataType: s.columnDataType("boolean", false), + DataType: s.columnDataType("bool", false), Valuer: "(bool)({{goPath}})", Scanner: "github.com/si3nloong/sqlgen/sequel/types.Bool({{addrOfGoPath}})", }, "int8": { - DataType: s.intDataType("smallint", int64(0)), + DataType: s.intDataType("int2", int64(0)), Valuer: "(int64)({{goPath}})", Scanner: "github.com/si3nloong/sqlgen/sequel/types.Integer({{addrOfGoPath}})", }, "int16": { - DataType: s.intDataType("smallint", int64(0)), + DataType: s.intDataType("int2", int64(0)), Valuer: "(int64)({{goPath}})", Scanner: "github.com/si3nloong/sqlgen/sequel/types.Integer({{addrOfGoPath}})", }, "int32": { - DataType: s.intDataType("integer", int64(0)), + DataType: s.intDataType("int4", int64(0)), Valuer: "(int64)({{goPath}})", Scanner: "github.com/si3nloong/sqlgen/sequel/types.Integer({{addrOfGoPath}})", }, @@ -48,22 +54,22 @@ func (s *postgresDriver) ColumnDataTypes() map[string]*dialect.ColumnType { Scanner: "github.com/si3nloong/sqlgen/sequel/types.Integer({{addrOfGoPath}})", }, "int": { - DataType: s.intDataType("integer", int64(0)), + DataType: s.intDataType("int4", int64(0)), Valuer: "(int64)({{goPath}})", Scanner: "github.com/si3nloong/sqlgen/sequel/types.Integer({{addrOfGoPath}})", }, "uint8": { - DataType: s.intDataType("smallint", uint64(0)), + DataType: s.intDataType("int2", uint64(0)), Valuer: "(int64)({{goPath}})", Scanner: "github.com/si3nloong/sqlgen/sequel/types.Integer({{addrOfGoPath}})", }, "uint16": { - DataType: s.intDataType("smallint", uint64(0)), + DataType: s.intDataType("int2", uint64(0)), Valuer: "(int64)({{goPath}})", Scanner: "github.com/si3nloong/sqlgen/sequel/types.Integer({{addrOfGoPath}})", }, "uint32": { - DataType: s.intDataType("integer", uint64(0)), + DataType: s.intDataType("int4", uint64(0)), Valuer: "(int64)({{goPath}})", Scanner: "github.com/si3nloong/sqlgen/sequel/types.Integer({{addrOfGoPath}})", }, @@ -73,7 +79,7 @@ func (s *postgresDriver) ColumnDataTypes() map[string]*dialect.ColumnType { Scanner: "github.com/si3nloong/sqlgen/sequel/types.Integer({{addrOfGoPath}})", }, "uint": { - DataType: s.intDataType("integer", uint64(0)), + DataType: s.intDataType("int4", uint64(0)), Valuer: "(int64)({{goPath}})", Scanner: "github.com/si3nloong/sqlgen/sequel/types.Integer({{addrOfGoPath}})", }, @@ -88,14 +94,14 @@ func (s *postgresDriver) ColumnDataTypes() map[string]*dialect.ColumnType { Scanner: "github.com/si3nloong/sqlgen/sequel/types.Float({{addrOfGoPath}})", }, "time.Time": { - DataType: s.columnDataType("timestamp(6) with time zone", sql.RawBytes(`NOW()`)), + DataType: s.columnDataType("timestamptz(6)", sql.RawBytes(`NOW()`)), Valuer: "(time.Time)({{goPath}})", Scanner: "(*time.Time)({{addrOfGoPath}})", }, "*time.Time": { - DataType: s.columnDataType("timestamp(6) with time zone"), + DataType: s.columnDataType("timestamptz(6)"), Valuer: "github.com/si3nloong/sqlgen/sequel/types.Time({{goPath}})", - Scanner: "github.com/si3nloong/sqlgen/sequel/types.PtrOfTime({{addrOfGoPath}})", + Scanner: "github.com/si3nloong/sqlgen/sequel/types.Time({{addrOfGoPath}})", }, "[...]rune": { DataType: func(c dialect.GoColumn) string { @@ -104,6 +110,13 @@ func (s *postgresDriver) ColumnDataTypes() map[string]*dialect.ColumnType { Valuer: "string({{goPath}}[:])", Scanner: "github.com/si3nloong/sqlgen/sequel/types.FixedSizeRunes(({{goPath}})[:],{{len}})", }, + "[...]byte": { + DataType: func(c dialect.GoColumn) string { + return s.columnDataType(fmt.Sprintf("varchar(%d)", c.Size()))(c) + }, + Valuer: "string({{goPath}}[:])", + Scanner: "github.com/si3nloong/sqlgen/sequel/types.FixedSizeBytes(({{goPath}})[:],{{len}})", + }, "[...]string": { DataType: s.columnDataType("text[{{len}}]"), Valuer: "github.com/si3nloong/sqlgen/sequel/encoding.MarshalStringSlice(({{goPath}})[:],[2]byte{'{','}'})", @@ -205,6 +218,33 @@ func (s *postgresDriver) ColumnDataTypes() map[string]*dialect.ColumnType { Scanner: "github.com/si3nloong/sqlgen/sequel/types.JSONUnmarshaler({{addrOfGoPath}})", }, } + s.mapIntegers(dataTypes) + return dataTypes +} + +func (s *postgresDriver) mapIntegers(dict map[string]*dialect.ColumnType) { + types := [][2]string{ + {"int", "int4"}, {"int8", "int2"}, {"int16", "int2"}, {"int32", "int4"}, {"int64", "bigint"}, + {"uint", "int4"}, {"uint8", "int2"}, {"uint16", "int2"}, {"uint32", "int4"}, {"uint64", "bigint"}, + } + for _, t := range types { + dict[t[0]] = &dialect.ColumnType{ + DataType: s.intDataType(t[1], int64(0)), + Valuer: "(int64)({{goPath}})", + Scanner: "github.com/si3nloong/sqlgen/sequel/types.Integer({{addrOfGoPath}})", + } + } + types = [][2]string{ + {"*int", "int4"}, {"*int8", "int2"}, {"*int16", "int2"}, {"*int32", "int4"}, {"*int64", "bigint"}, + {"*uint", "int4"}, {"*uint8", "int2"}, {"*uint16", "int2"}, {"*uint32", "int4"}, {"*uint64", "bigint"}, + } + for _, t := range types { + dict[t[0]] = &dialect.ColumnType{ + DataType: s.intDataType(t[1], int64(0)), + Valuer: "github.com/si3nloong/sqlgen/sequel/types.Integer({{addrOfGoPath}})", + Scanner: "github.com/si3nloong/sqlgen/sequel/types.Integer({{addrOfGoPath}})", + } + } } func (s *postgresDriver) intDataType(dataType string, defaultValue ...any) func(dialect.GoColumn) string { diff --git a/codegen/dialect/postgres/index.go b/codegen/dialect/postgres/index.go index 383f9c9..47678ef 100644 --- a/codegen/dialect/postgres/index.go +++ b/codegen/dialect/postgres/index.go @@ -2,11 +2,26 @@ package postgres import ( "context" + "crypto/md5" "database/sql" + "encoding/hex" + "strings" + "unsafe" "github.com/lib/pq" ) +//go:generate stringer --type indexType --linecomment +type indexType uint8 + +const ( + bTree indexType = iota // BTREE + hash // HASH + brin // BRIN + unique // UNIQUE + pk +) + type index struct { Name string IsPK bool @@ -47,3 +62,16 @@ GROUP BY index_name, is_pk;`, tableName) } return idxs, rows.Err() } + +func indexName(columns []string, idxType indexType) string { + str := strings.Join(columns, ",") + hash := md5.Sum(unsafe.Slice(unsafe.StringData(str), len(str))) + prefix := "IX" + switch idxType { + case unique: + prefix = "UQ" + case pk: + prefix = "PK" + } + return prefix + "_" + hex.EncodeToString(hash[:]) +} diff --git a/codegen/dialect/postgres/migration.go b/codegen/dialect/postgres/migration.go index e28fc29..fe1b63c 100644 --- a/codegen/dialect/postgres/migration.go +++ b/codegen/dialect/postgres/migration.go @@ -18,7 +18,16 @@ func (s *postgresDriver) Migrate(ctx context.Context, dsn string, w dialect.Writ } defer sqlConn.Close() - existedColumns, err := s.tableColumns(ctx, sqlConn, "public", schema.TableName()) + if err := sqlConn.PingContext(ctx); err != nil { + return err + } + + var dbName string + if err := sqlConn.QueryRowContext(ctx, `SELECT CURRENT_DATABASE();`).Scan(&dbName); err != nil { + return err + } + + existedColumns, err := s.tableColumns(ctx, sqlConn, dbName, schema.TableName()) if err != nil { return err } @@ -68,11 +77,22 @@ func (s *postgresDriver) Migrate(ctx context.Context, dsn string, w dialect.Writ } w.WriteString(")") } - // if indexes := schema.Indexes(); len(indexes) > 0 { - // for i := range indexes { - // log.Println(indexes[i]) - // } - // } + + schema.RangeIndex(func(idx dialect.Index, _ int) { + if idx.Unique() { + w.WriteString("ADD CONSTRAINT " + indexName(idx.Columns(), unique) + " UNIQUE (") + } else { + w.WriteString("ADD CONSTRAINT " + indexName(idx.Columns(), bTree) + " INDEX (") + } + for i, col := range idx.Columns() { + if i > 0 { + w.WriteString("," + s.QuoteIdentifier(col)) + } else { + w.WriteString(s.QuoteIdentifier(col)) + } + } + w.WriteString(")") + }) w.WriteString("\n);") var up, down strings.Builder @@ -124,11 +144,12 @@ func (s *postgresDriver) Migrate(ctx context.Context, dsn string, w dialect.Writ if err != nil { return err } + keys := schema.Keys() - if existedIndex, idx, ok := lo.FindIndexOf(existedIndexes, func(v index) bool { + if existedIndex, _, ok := lo.FindIndexOf(existedIndexes, func(v index) bool { return v.IsPK }); !ok && len(keys) > 0 { - up.WriteString(",\n\tADD PRIMARY KEY (") + up.WriteString(",\n\tADD CONSTRAINT " + s.QuoteIdentifier(indexName(keys, pk)) + " PRIMARY KEY (") for i := range keys { if i > 0 { up.WriteString("," + s.QuoteIdentifier(keys[i])) @@ -137,12 +158,13 @@ func (s *postgresDriver) Migrate(ctx context.Context, dsn string, w dialect.Writ } } up.WriteByte(')') - down.WriteString("DROP PRIMARY KEY") + down.WriteString(",\n\tDROP PRIMARY KEY") } else { - existedIndexes = append(existedIndexes[:idx], existedIndexes[idx+1:]...) + // log.Println(existedIndexes, len(existedIndexes)) + // existedIndexes = append(existedIndexes[:idx], existedIndexes[idx+1:]...) up.WriteString(",\n\tDROP CONSTRAINT " + s.QuoteIdentifier(existedIndex.Name)) if len(keys) > 0 { - up.WriteString(",\n\tADD PRIMARY KEY (") + up.WriteString(",\n\tADD " + s.QuoteIdentifier(indexName(keys, pk)) + " PRIMARY KEY (") for i := range keys { if i > 0 { up.WriteString("," + s.QuoteIdentifier(keys[i])) @@ -152,7 +174,7 @@ func (s *postgresDriver) Migrate(ctx context.Context, dsn string, w dialect.Writ } up.WriteByte(')') } - down.WriteString(",\n\tADD PRIMARY KEY ()") + // down.WriteString(",\n\tADD PRIMARY KEY ()") } if len(existedColumns) > 0 { for i := range existedColumns { @@ -165,15 +187,22 @@ func (s *postgresDriver) Migrate(ctx context.Context, dsn string, w dialect.Writ } clear(existedColumns) } - if len(existedIndexes) > 0 { - for i := range existedIndexes { - idx := existedIndexes[i] - up.WriteString(",\n\tDROP CONSTRAINT " + s.QuoteIdentifier(idx.Name)) - down.WriteString(",\n\tADD CONSTRAINT " + s.QuoteIdentifier(idx.Name) + "(" + strings.Join(idx.Columns, ",") + ")") - } - clear(existedIndexes) - } - + // if len(existedIndexes) > 0 { + // for i := range existedIndexes { + // idx := existedIndexes[i] + // up.WriteString(",\n\tDROP CONSTRAINT " + s.QuoteIdentifier(idx.Name)) + // down.WriteString(",\n\tADD CONSTRAINT " + s.QuoteIdentifier(idx.Name) + " (") + // for j := range idx.Columns { + // if j > 0 { + // down.WriteString("," + s.QuoteIdentifier(idx.Columns[j])) + // } else { + // down.WriteString(s.QuoteIdentifier(idx.Columns[j])) + // } + // } + // down.WriteByte(')') + // } + // clear(existedIndexes) + // } up.WriteString(";") down.WriteString(";") diff --git a/codegen/expr.go b/codegen/expr.go index 3f78e9f..b3148ff 100644 --- a/codegen/expr.go +++ b/codegen/expr.go @@ -31,6 +31,7 @@ type ExprParams struct { // You may pass `&v.Path` or `v.Path` or any relevant go path, // we will check whether it's addr of the go path GoPath string + IsPtr bool Len int64 } @@ -52,6 +53,9 @@ func (e Expr) Format(pkg *Package, args ...ExprParams) string { return params.GoPath }, "addrOfGoPath": func() string { + if params.IsPtr { + return params.GoPath + } return "&" + params.GoPath }, } diff --git a/codegen/types.go b/codegen/types.go index 0755839..a1e4b11 100644 --- a/codegen/types.go +++ b/codegen/types.go @@ -45,7 +45,6 @@ type tableInfo struct { autoIncrKey *columnInfo keys []*columnInfo columns []*columnInfo - indexes []*indexInfo } func (b *tableInfo) GoName() string { @@ -76,10 +75,27 @@ func (b *tableInfo) ColumnGoType(i int) dialect.GoColumn { return b.columns[i] } -func (b *tableInfo) Indexes() []string { - return lo.Map(b.indexes, func(c *indexInfo, _ int) string { - return strings.Join(c.columns, ",") - }) +func (b *tableInfo) RangeIndex(rangeFunc func(dialect.Index, int)) { + var ( + optMap = make(map[string]*indexInfo) + key string + ) + for _, col := range b.columns { + switch { + case col.hasOption(TagOptionIndex): + key, _ = col.getOptionValue(TagOptionIndex) + case col.hasOption(TagOptionUnique): + key, _ = col.getOptionValue(TagOptionIndex) + default: + continue + } + + if _, ok := optMap[key]; !ok { + optMap[key] = &indexInfo{} + } + + optMap[key].columns = append(optMap[key].columns, col.columnName) + } } func (b *tableInfo) Implements(T *types.Interface) (*types.Func, bool) { @@ -192,7 +208,7 @@ func (c *columnInfo) hasOption(k string) bool { return ok } -func (c *columnInfo) getOption(k string) (string, bool) { +func (c *columnInfo) getOptionValue(k string) (string, bool) { tag, _, ok := lo.FindLastIndexOf(c.tags, func(v goTag) bool { return v.key == k }) @@ -211,10 +227,10 @@ func (c *columnInfo) Default() (driver.Value, bool) { } func (c *columnInfo) Key() bool { - _, ok1 := c.getOption(TagOptionPKAlias) - _, ok2 := c.getOption(TagOptionFK) - _, ok3 := c.getOption(TagOptionPK) - _, ok4 := c.getOption(TagOptionAutoIncrement) + _, ok1 := c.getOptionValue(TagOptionPKAlias) + _, ok2 := c.getOptionValue(TagOptionFK) + _, ok3 := c.getOptionValue(TagOptionPK) + _, ok4 := c.getOptionValue(TagOptionAutoIncrement) return ok1 || ok2 || ok3 || ok4 } @@ -232,7 +248,7 @@ func (c *columnInfo) AutoIncr() bool { } func (c columnInfo) Size() int { - return 1 + return c.size } func (i *columnInfo) sqlValuer() (func(string) string, bool) { @@ -254,14 +270,14 @@ func (i columnInfo) sqlScanner() (func(string) string, bool) { } type indexInfo struct { - columns []string - indexType string + columns []string + unique bool } func (i indexInfo) Columns() []string { return i.columns } -func (i indexInfo) Type() string { - return i.indexType +func (i indexInfo) Unique() bool { + return i.unique }