refactor insert condition generation #1998

Merged
lunny merged 5 commits from lunny/refactor_insert_cond into master 2021-07-20 05:46:24 +00:00
35 changed files with 324 additions and 328 deletions

View File

@ -373,7 +373,6 @@ func asTime(src interface{}, dbLoc *time.Location, uiLoc *time.Location) (*time.
case *sql.NullInt64: case *sql.NullInt64:
tm := time.Unix(t.Int64, 0).In(uiLoc) tm := time.Unix(t.Int64, 0).In(uiLoc)
return &tm, nil return &tm, nil
} }
return nil, fmt.Errorf("unsupported value %#v as time", src) return nil, fmt.Errorf("unsupported value %#v as time", src)
} }
@ -751,7 +750,6 @@ func asKind(vv reflect.Value, tp reflect.Type) (interface{}, error) {
} }
return v, nil return v, nil
} }
} }
return nil, fmt.Errorf("unsupported primary key type: %v, %v", tp, vv) return nil, fmt.Errorf("unsupported primary key type: %v, %v", tp, vv)
} }
@ -946,8 +944,10 @@ var (
_ sql.Scanner = &EmptyScanner{} _ sql.Scanner = &EmptyScanner{}
) )
// EmptyScanner represents an empty scanner which will ignore the scan
type EmptyScanner struct{} type EmptyScanner struct{}
// Scan implements sql.Scanner
func (EmptyScanner) Scan(value interface{}) error { func (EmptyScanner) Scan(value interface{}) error {
return nil return nil
} }

View File

@ -10,6 +10,7 @@ import (
"time" "time"
) )
// Interface2Interface converts interface of pointer as interface of value
func Interface2Interface(userLocation *time.Location, v interface{}) (interface{}, error) { func Interface2Interface(userLocation *time.Location, v interface{}) (interface{}, error) {
if v == nil { if v == nil {
return nil, nil return nil, nil

View File

@ -45,5 +45,5 @@ func String2Time(s string, originalLocation *time.Location, convertedLocation *t
return &tm, nil return &tm, nil
} }
} }
return nil, fmt.Errorf("unsupported convertion from %s to time", s) return nil, fmt.Errorf("unsupported conversion from %s to time", s)
} }

View File

@ -118,12 +118,9 @@ func (db *Base) HasRecords(queryer core.Queryer, ctx context.Context, query stri
defer rows.Close() defer rows.Close()
if rows.Next() { if rows.Next() {
if rows.Err() != nil {
return true, rows.Err()
}
return true, nil return true, nil
} }
return false, nil return false, rows.Err()
} }
// IsColumnExist returns true if the column of the table exist // IsColumnExist returns true if the column of the table exist

View File

@ -18,14 +18,9 @@ type ScanContext struct {
UserLocation *time.Location UserLocation *time.Location
} }
type DriverFeatures struct {
SupportNullable bool
}
// Driver represents a database driver // Driver represents a database driver
type Driver interface { type Driver interface {
Parse(string, string) (*URI, error) Parse(string, string) (*URI, error)
Features() DriverFeatures
GenScanResult(string) (interface{}, error) // according given column type generating a suitable scan interface GenScanResult(string) (interface{}, error) // according given column type generating a suitable scan interface
Scan(*ScanContext, *core.Rows, []*sql.ColumnType, ...interface{}) error Scan(*ScanContext, *core.Rows, []*sql.ColumnType, ...interface{}) error
} }
@ -82,9 +77,3 @@ type baseDriver struct{}
func (b *baseDriver) Scan(ctx *ScanContext, rows *core.Rows, types []*sql.ColumnType, v ...interface{}) error { func (b *baseDriver) Scan(ctx *ScanContext, rows *core.Rows, types []*sql.ColumnType, v ...interface{}) error {
return rows.Scan(v...) return rows.Scan(v...)
} }
func (b *baseDriver) Features() DriverFeatures {
return DriverFeatures{
SupportNullable: true,
}
}

View File

@ -264,6 +264,9 @@ func (db *mssql) Version(ctx context.Context, queryer core.Queryer) (*schemas.Ve
var version, level, edition string var version, level, edition string
if !rows.Next() { if !rows.Next() {
if rows.Err() != nil {
return nil, rows.Err()
}
return nil, errors.New("unknow version") return nil, errors.New("unknow version")
} }
@ -456,9 +459,6 @@ func (db *mssql) GetColumns(queryer core.Queryer, ctx context.Context, tableName
cols := make(map[string]*schemas.Column) cols := make(map[string]*schemas.Column)
colSeq := make([]string, 0) colSeq := make([]string, 0)
for rows.Next() { for rows.Next() {
if rows.Err() != nil {
return nil, nil, rows.Err()
}
var name, ctype, vdefault string var name, ctype, vdefault string
var maxLen, precision, scale int var maxLen, precision, scale int
var nullable, isPK, defaultIsNull, isIncrement bool var nullable, isPK, defaultIsNull, isIncrement bool
@ -512,6 +512,9 @@ func (db *mssql) GetColumns(queryer core.Queryer, ctx context.Context, tableName
cols[col.Name] = col cols[col.Name] = col
colSeq = append(colSeq, col.Name) colSeq = append(colSeq, col.Name)
} }
if rows.Err() != nil {
return nil, nil, rows.Err()
}
return colSeq, cols, nil return colSeq, cols, nil
} }
@ -527,9 +530,6 @@ func (db *mssql) GetTables(queryer core.Queryer, ctx context.Context) ([]*schema
tables := make([]*schemas.Table, 0) tables := make([]*schemas.Table, 0)
for rows.Next() { for rows.Next() {
if rows.Err() != nil {
return nil, rows.Err()
}
table := schemas.NewEmptyTable() table := schemas.NewEmptyTable()
var name string var name string
err = rows.Scan(&name) err = rows.Scan(&name)
@ -539,6 +539,9 @@ func (db *mssql) GetTables(queryer core.Queryer, ctx context.Context) ([]*schema
table.Name = strings.Trim(name, "` ") table.Name = strings.Trim(name, "` ")
tables = append(tables, table) tables = append(tables, table)
} }
if rows.Err() != nil {
return nil, rows.Err()
}
return tables, nil return tables, nil
} }
@ -562,11 +565,8 @@ WHERE IXS.TYPE_DESC='NONCLUSTERED' and OBJECT_NAME(IXS.OBJECT_ID) =?
} }
defer rows.Close() defer rows.Close()
indexes := make(map[string]*schemas.Index, 0) indexes := make(map[string]*schemas.Index)
for rows.Next() { for rows.Next() {
if rows.Err() != nil {
return nil, rows.Err()
}
var indexType int var indexType int
var indexName, colName, isUnique string var indexName, colName, isUnique string
@ -604,6 +604,9 @@ WHERE IXS.TYPE_DESC='NONCLUSTERED' and OBJECT_NAME(IXS.OBJECT_ID) =?
} }
index.AddColumn(colName) index.AddColumn(colName)
} }
if rows.Err() != nil {
return nil, rows.Err()
}
return indexes, nil return indexes, nil
} }
@ -664,8 +667,7 @@ func (p *odbcDriver) Parse(driverName, dataSourceName string) (*URI, error) {
for _, c := range kv { for _, c := range kv {
vv := strings.Split(strings.TrimSpace(c), "=") vv := strings.Split(strings.TrimSpace(c), "=")
if len(vv) == 2 { if len(vv) == 2 {
switch strings.ToLower(vv[0]) { if strings.ToLower(vv[0]) == "database" {
case "database":
dbName = vv[1] dbName = vv[1]
} }
} }

View File

@ -213,7 +213,10 @@ func (db *mysql) Version(ctx context.Context, queryer core.Queryer) (*schemas.Ve
var version string var version string
if !rows.Next() { if !rows.Next() {
return nil, errors.New("Unknow version") if rows.Err() != nil {
return nil, rows.Err()
}
return nil, errors.New("unknow version")
} }
if err := rows.Scan(&version); err != nil { if err := rows.Scan(&version); err != nil {
@ -254,9 +257,6 @@ func (db *mysql) SetParams(params map[string]string) {
fallthrough fallthrough
case "COMPRESSED": case "COMPRESSED":
db.rowFormat = t db.rowFormat = t
break
default:
break
} }
} }
} }
@ -405,9 +405,6 @@ func (db *mysql) GetColumns(queryer core.Queryer, ctx context.Context, tableName
cols := make(map[string]*schemas.Column) cols := make(map[string]*schemas.Column)
colSeq := make([]string, 0) colSeq := make([]string, 0)
for rows.Next() { for rows.Next() {
if rows.Err() != nil {
return nil, nil, rows.Err()
}
col := new(schemas.Column) col := new(schemas.Column)
col.Indexes = make(map[string]int) col.Indexes = make(map[string]int)
@ -506,6 +503,9 @@ func (db *mysql) GetColumns(queryer core.Queryer, ctx context.Context, tableName
cols[col.Name] = col cols[col.Name] = col
colSeq = append(colSeq, col.Name) colSeq = append(colSeq, col.Name)
} }
if rows.Err() != nil {
return nil, nil, rows.Err()
}
return colSeq, cols, nil return colSeq, cols, nil
} }
@ -522,9 +522,6 @@ func (db *mysql) GetTables(queryer core.Queryer, ctx context.Context) ([]*schema
tables := make([]*schemas.Table, 0) tables := make([]*schemas.Table, 0)
for rows.Next() { for rows.Next() {
if rows.Err() != nil {
return nil, rows.Err()
}
table := schemas.NewEmptyTable() table := schemas.NewEmptyTable()
var name, engine string var name, engine string
var autoIncr, comment *string var autoIncr, comment *string
@ -540,6 +537,9 @@ func (db *mysql) GetTables(queryer core.Queryer, ctx context.Context) ([]*schema
table.StoreEngine = engine table.StoreEngine = engine
tables = append(tables, table) tables = append(tables, table)
} }
if rows.Err() != nil {
return nil, rows.Err()
}
return tables, nil return tables, nil
} }
@ -570,11 +570,8 @@ func (db *mysql) GetIndexes(queryer core.Queryer, ctx context.Context, tableName
} }
defer rows.Close() defer rows.Close()
indexes := make(map[string]*schemas.Index, 0) indexes := make(map[string]*schemas.Index)
for rows.Next() { for rows.Next() {
if rows.Err() != nil {
return nil, rows.Err()
}
var indexType int var indexType int
var indexName, colName, nonUnique string var indexName, colName, nonUnique string
err = rows.Scan(&indexName, &nonUnique, &colName) err = rows.Scan(&indexName, &nonUnique, &colName)
@ -586,7 +583,7 @@ func (db *mysql) GetIndexes(queryer core.Queryer, ctx context.Context, tableName
continue continue
} }
if "YES" == nonUnique || nonUnique == "1" { if nonUnique == "YES" || nonUnique == "1" {
indexType = schemas.IndexType indexType = schemas.IndexType
} else { } else {
indexType = schemas.UniqueType indexType = schemas.UniqueType
@ -610,6 +607,9 @@ func (db *mysql) GetIndexes(queryer core.Queryer, ctx context.Context, tableName
} }
index.AddColumn(colName) index.AddColumn(colName)
} }
if rows.Err() != nil {
return nil, rows.Err()
}
return indexes, nil return indexes, nil
} }
@ -696,14 +696,12 @@ func (p *mysqlDriver) Parse(driverName, dataSourceName string) (*URI, error) {
for _, kv := range kvs { for _, kv := range kvs {
splits := strings.Split(kv, "=") splits := strings.Split(kv, "=")
if len(splits) == 2 { if len(splits) == 2 {
switch splits[0] { if splits[0] == "charset" {
case "charset":
uri.Charset = splits[1] uri.Charset = splits[1]
} }
} }
} }
} }
} }
} }
return uri, nil return uri, nil
@ -720,13 +718,13 @@ func (p *mysqlDriver) GenScanResult(colType string) (interface{}, error) {
case "TINYINT", "SMALLINT", "MEDIUMINT", "INT": case "TINYINT", "SMALLINT", "MEDIUMINT", "INT":
var s sql.NullInt32 var s sql.NullInt32
return &s, nil return &s, nil
case "FLOAT", "REAL", "DOUBLE PRECISION": case "FLOAT", "REAL", "DOUBLE PRECISION", "DOUBLE":
var s sql.NullFloat64 var s sql.NullFloat64
return &s, nil return &s, nil
case "DECIMAL", "NUMERIC": case "DECIMAL", "NUMERIC":
var s sql.NullString var s sql.NullString
return &s, nil return &s, nil
case "DATETIME": case "DATETIME", "TIMESTAMP":
var s sql.NullTime var s sql.NullTime
return &s, nil return &s, nil
case "BIT": case "BIT":

View File

@ -525,6 +525,9 @@ func (db *oracle) Version(ctx context.Context, queryer core.Queryer) (*schemas.V
var version string var version string
if !rows.Next() { if !rows.Next() {
if rows.Err() != nil {
return nil, rows.Err()
}
return nil, errors.New("unknow version") return nil, errors.New("unknow version")
} }
@ -677,9 +680,6 @@ func (db *oracle) GetColumns(queryer core.Queryer, ctx context.Context, tableNam
cols := make(map[string]*schemas.Column) cols := make(map[string]*schemas.Column)
colSeq := make([]string, 0) colSeq := make([]string, 0)
for rows.Next() { for rows.Next() {
if rows.Err() != nil {
return nil, nil, rows.Err()
}
col := new(schemas.Column) col := new(schemas.Column)
col.Indexes = make(map[string]int) col.Indexes = make(map[string]int)
@ -759,6 +759,9 @@ func (db *oracle) GetColumns(queryer core.Queryer, ctx context.Context, tableNam
cols[col.Name] = col cols[col.Name] = col
colSeq = append(colSeq, col.Name) colSeq = append(colSeq, col.Name)
} }
if rows.Err() != nil {
return nil, nil, rows.Err()
}
return colSeq, cols, nil return colSeq, cols, nil
} }
@ -775,9 +778,6 @@ func (db *oracle) GetTables(queryer core.Queryer, ctx context.Context) ([]*schem
tables := make([]*schemas.Table, 0) tables := make([]*schemas.Table, 0)
for rows.Next() { for rows.Next() {
if rows.Err() != nil {
return nil, rows.Err()
}
table := schemas.NewEmptyTable() table := schemas.NewEmptyTable()
err = rows.Scan(&table.Name) err = rows.Scan(&table.Name)
if err != nil { if err != nil {
@ -786,6 +786,9 @@ func (db *oracle) GetTables(queryer core.Queryer, ctx context.Context) ([]*schem
tables = append(tables, table) tables = append(tables, table)
} }
if rows.Err() != nil {
return nil, rows.Err()
}
return tables, nil return tables, nil
} }
@ -800,11 +803,8 @@ func (db *oracle) GetIndexes(queryer core.Queryer, ctx context.Context, tableNam
} }
defer rows.Close() defer rows.Close()
indexes := make(map[string]*schemas.Index, 0) indexes := make(map[string]*schemas.Index)
for rows.Next() { for rows.Next() {
if rows.Err() != nil {
return nil, rows.Err()
}
var indexType int var indexType int
var indexName, colName, uniqueness string var indexName, colName, uniqueness string
@ -838,6 +838,9 @@ func (db *oracle) GetIndexes(queryer core.Queryer, ctx context.Context, tableNam
} }
index.AddColumn(colName) index.AddColumn(colName)
} }
if rows.Err() != nil {
return nil, rows.Err()
}
return indexes, nil return indexes, nil
} }
@ -851,7 +854,7 @@ type godrorDriver struct {
baseDriver baseDriver
} }
func (cfg *godrorDriver) Parse(driverName, dataSourceName string) (*URI, error) { func (g *godrorDriver) Parse(driverName, dataSourceName string) (*URI, error) {
db := &URI{DBType: schemas.ORACLE} db := &URI{DBType: schemas.ORACLE}
dsnPattern := regexp.MustCompile( dsnPattern := regexp.MustCompile(
`^(?:(?P<user>.*?)(?::(?P<passwd>.*))?@)?` + // [user[:password]@] `^(?:(?P<user>.*?)(?::(?P<passwd>.*))?@)?` + // [user[:password]@]
@ -863,8 +866,7 @@ func (cfg *godrorDriver) Parse(driverName, dataSourceName string) (*URI, error)
names := dsnPattern.SubexpNames() names := dsnPattern.SubexpNames()
for i, match := range matches { for i, match := range matches {
switch names[i] { if names[i] == "dbname" {
case "dbname":
db.DBName = match db.DBName = match
} }
} }
@ -874,7 +876,7 @@ func (cfg *godrorDriver) Parse(driverName, dataSourceName string) (*URI, error)
return db, nil return db, nil
} }
func (p *godrorDriver) GenScanResult(colType string) (interface{}, error) { func (g *godrorDriver) GenScanResult(colType string) (interface{}, error) {
switch colType { switch colType {
case "CHAR", "NCHAR", "VARCHAR", "VARCHAR2", "NVARCHAR2", "LONG", "CLOB", "NCLOB": case "CHAR", "NCHAR", "VARCHAR", "VARCHAR2", "NVARCHAR2", "LONG", "CLOB", "NCLOB":
var s sql.NullString var s sql.NullString
@ -900,7 +902,7 @@ type oci8Driver struct {
// dataSourceName=user/password@ipv4:port/dbname // dataSourceName=user/password@ipv4:port/dbname
// dataSourceName=user/password@[ipv6]:port/dbname // dataSourceName=user/password@[ipv6]:port/dbname
func (p *oci8Driver) Parse(driverName, dataSourceName string) (*URI, error) { func (o *oci8Driver) Parse(driverName, dataSourceName string) (*URI, error) {
db := &URI{DBType: schemas.ORACLE} db := &URI{DBType: schemas.ORACLE}
dsnPattern := regexp.MustCompile( dsnPattern := regexp.MustCompile(
`^(?P<user>.*)\/(?P<password>.*)@` + // user:password@ `^(?P<user>.*)\/(?P<password>.*)@` + // user:password@
@ -909,8 +911,7 @@ func (p *oci8Driver) Parse(driverName, dataSourceName string) (*URI, error) {
matches := dsnPattern.FindStringSubmatch(dataSourceName) matches := dsnPattern.FindStringSubmatch(dataSourceName)
names := dsnPattern.SubexpNames() names := dsnPattern.SubexpNames()
for i, match := range matches { for i, match := range matches {
switch names[i] { if names[i] == "dbname" {
case "dbname":
db.DBName = match db.DBName = match
} }
} }

View File

@ -810,6 +810,9 @@ func (db *postgres) Version(ctx context.Context, queryer core.Queryer) (*schemas
var version string var version string
if !rows.Next() { if !rows.Next() {
if rows.Err() != nil {
return nil, rows.Err()
}
return nil, errors.New("unknow version") return nil, errors.New("unknow version")
} }
@ -1062,7 +1065,10 @@ func (db *postgres) IsColumnExist(queryer core.Queryer, ctx context.Context, tab
} }
defer rows.Close() defer rows.Close()
return rows.Next(), nil if rows.Next() {
return true, nil
}
return false, rows.Err()
} }
func (db *postgres) GetColumns(queryer core.Queryer, ctx context.Context, tableName string) ([]string, map[string]*schemas.Column, error) { func (db *postgres) GetColumns(queryer core.Queryer, ctx context.Context, tableName string) ([]string, map[string]*schemas.Column, error) {
@ -1098,9 +1104,6 @@ WHERE n.nspname= s.table_schema AND c.relkind = 'r'::char AND c.relname = $1%s A
colSeq := make([]string, 0) colSeq := make([]string, 0)
for rows.Next() { for rows.Next() {
if rows.Err() != nil {
return nil, nil, rows.Err()
}
col := new(schemas.Column) col := new(schemas.Column)
col.Indexes = make(map[string]int) col.Indexes = make(map[string]int)
@ -1216,6 +1219,9 @@ WHERE n.nspname= s.table_schema AND c.relkind = 'r'::char AND c.relname = $1%s A
cols[col.Name] = col cols[col.Name] = col
colSeq = append(colSeq, col.Name) colSeq = append(colSeq, col.Name)
} }
if rows.Err() != nil {
return nil, nil, rows.Err()
}
return colSeq, cols, nil return colSeq, cols, nil
} }
@ -1237,9 +1243,6 @@ func (db *postgres) GetTables(queryer core.Queryer, ctx context.Context) ([]*sch
tables := make([]*schemas.Table, 0) tables := make([]*schemas.Table, 0)
for rows.Next() { for rows.Next() {
if rows.Err() != nil {
return nil, rows.Err()
}
table := schemas.NewEmptyTable() table := schemas.NewEmptyTable()
var name string var name string
err = rows.Scan(&name) err = rows.Scan(&name)
@ -1249,6 +1252,9 @@ func (db *postgres) GetTables(queryer core.Queryer, ctx context.Context) ([]*sch
table.Name = name table.Name = name
tables = append(tables, table) tables = append(tables, table)
} }
if rows.Err() != nil {
return nil, rows.Err()
}
return tables, nil return tables, nil
} }
@ -1279,9 +1285,6 @@ func (db *postgres) GetIndexes(queryer core.Queryer, ctx context.Context, tableN
indexes := make(map[string]*schemas.Index) indexes := make(map[string]*schemas.Index)
for rows.Next() { for rows.Next() {
if rows.Err() != nil {
return nil, rows.Err()
}
var indexType int var indexType int
var indexName, indexdef string var indexName, indexdef string
var colNames []string var colNames []string
@ -1322,6 +1325,9 @@ func (db *postgres) GetIndexes(queryer core.Queryer, ctx context.Context, tableN
index.IsRegular = isRegular index.IsRegular = isRegular
indexes[index.Name] = index indexes[index.Name] = index
} }
if rows.Err() != nil {
return nil, rows.Err()
}
return indexes, nil return indexes, nil
} }
@ -1333,12 +1339,6 @@ type pqDriver struct {
baseDriver baseDriver
} }
func (b *pqDriver) Features() DriverFeatures {
return DriverFeatures{
SupportNullable: false,
}
}
type values map[string]string type values map[string]string
func (vs values) Set(k, v string) { func (vs values) Set(k, v string) {
@ -1459,9 +1459,6 @@ func QueryDefaultPostgresSchema(ctx context.Context, queryer core.Queryer) (stri
} }
defer rows.Close() defer rows.Close()
if rows.Next() { if rows.Next() {
if rows.Err() != nil {
return "", rows.Err()
}
var defaultSchema string var defaultSchema string
if err = rows.Scan(&defaultSchema); err != nil { if err = rows.Scan(&defaultSchema); err != nil {
return "", err return "", err
@ -1469,6 +1466,9 @@ func QueryDefaultPostgresSchema(ctx context.Context, queryer core.Queryer) (stri
parts := strings.Split(defaultSchema, ",") parts := strings.Split(defaultSchema, ",")
return strings.TrimSpace(parts[len(parts)-1]), nil return strings.TrimSpace(parts[len(parts)-1]), nil
} }
if rows.Err() != nil {
return "", rows.Err()
}
return "", errors.New("no default schema") return "", errors.New("no default schema")
} }

View File

@ -76,9 +76,7 @@ func TestParsePgx(t *testing.T) {
} else if err == nil && !reflect.DeepEqual(test.expected, uri.DBName) { } else if err == nil && !reflect.DeepEqual(test.expected, uri.DBName) {
t.Errorf("%q got: %#v want: %#v", test.in, uri.DBName, test.expected) t.Errorf("%q got: %#v want: %#v", test.in, uri.DBName, test.expected)
} }
} }
} }
func TestGetIndexColName(t *testing.T) { func TestGetIndexColName(t *testing.T) {

View File

@ -169,7 +169,10 @@ func (db *sqlite3) Version(ctx context.Context, queryer core.Queryer) (*schemas.
var version string var version string
if !rows.Next() { if !rows.Next() {
return nil, errors.New("Unknow version") if rows.Err() != nil {
return nil, rows.Err()
}
return nil, errors.New("unknow version")
} }
if err := rows.Scan(&version); err != nil { if err := rows.Scan(&version); err != nil {
@ -416,14 +419,14 @@ func (db *sqlite3) GetColumns(queryer core.Queryer, ctx context.Context, tableNa
var name string var name string
if rows.Next() { if rows.Next() {
if rows.Err() != nil {
return nil, nil, rows.Err()
}
err = rows.Scan(&name) err = rows.Scan(&name)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
} }
if rows.Err() != nil {
return nil, nil, rows.Err()
}
if name == "" { if name == "" {
return nil, nil, errors.New("no table named " + tableName) return nil, nil, errors.New("no table named " + tableName)
@ -485,6 +488,9 @@ func (db *sqlite3) GetTables(queryer core.Queryer, ctx context.Context) ([]*sche
} }
tables = append(tables, table) tables = append(tables, table)
} }
if rows.Err() != nil {
return nil, rows.Err()
}
return tables, nil return tables, nil
} }
@ -500,9 +506,6 @@ func (db *sqlite3) GetIndexes(queryer core.Queryer, ctx context.Context, tableNa
indexes := make(map[string]*schemas.Index) indexes := make(map[string]*schemas.Index)
for rows.Next() { for rows.Next() {
if rows.Err() != nil {
return nil, rows.Err()
}
var tmpSQL sql.NullString var tmpSQL sql.NullString
err = rows.Scan(&tmpSQL) err = rows.Scan(&tmpSQL)
if err != nil { if err != nil {
@ -547,6 +550,9 @@ func (db *sqlite3) GetIndexes(queryer core.Queryer, ctx context.Context, tableNa
index.IsRegular = isRegular index.IsRegular = isRegular
indexes[index.Name] = index indexes[index.Name] = index
} }
if rows.Err() != nil {
return nil, rows.Err()
}
return indexes, nil return indexes, nil
} }
@ -592,9 +598,3 @@ func (p *sqlite3Driver) GenScanResult(colType string) (interface{}, error) {
return &r, nil return &r, nil
} }
} }
func (b *sqlite3Driver) Features() DriverFeatures {
return DriverFeatures{
SupportNullable: false,
}
}

View File

@ -551,9 +551,6 @@ func (engine *Engine) dumpTables(tables []*schemas.Table, w io.Writer, tp ...sch
sess := engine.NewSession() sess := engine.NewSession()
defer sess.Close() defer sess.Close()
for rows.Next() { for rows.Next() {
if rows.Err() != nil {
return rows.Err()
}
_, err = io.WriteString(w, "INSERT INTO "+dstDialect.Quoter().Quote(dstTableName)+" ("+destColNames+") VALUES (") _, err = io.WriteString(w, "INSERT INTO "+dstDialect.Quoter().Quote(dstTableName)+" ("+destColNames+") VALUES (")
if err != nil { if err != nil {
return err return err
@ -610,6 +607,9 @@ func (engine *Engine) dumpTables(tables []*schemas.Table, w io.Writer, tp ...sch
return err return err
} }
} }
if rows.Err() != nil {
return rows.Err()
}
// FIXME: Hack for postgres // FIXME: Hack for postgres
if dstDialect.URI().DBType == schemas.POSTGRES && table.AutoIncrColumn() != nil { if dstDialect.URI().DBType == schemas.POSTGRES && table.AutoIncrColumn() != nil {

17
go.mod
View File

@ -3,16 +3,17 @@ module xorm.io/xorm
go 1.13 go 1.13
require ( require (
github.com/denisenkom/go-mssqldb v0.9.0 github.com/denisenkom/go-mssqldb v0.10.0
github.com/go-sql-driver/mysql v1.5.0 github.com/go-sql-driver/mysql v1.6.0
github.com/json-iterator/go v1.1.11
github.com/lib/pq v1.7.0
github.com/mattn/go-sqlite3 v1.14.6
github.com/goccy/go-json v0.7.4 github.com/goccy/go-json v0.7.4
github.com/json-iterator/go v1.1.11
github.com/lib/pq v1.10.2
github.com/mattn/go-sqlite3 v1.14.8
github.com/shopspring/decimal v1.2.0 github.com/shopspring/decimal v1.2.0
github.com/stretchr/testify v1.4.0 github.com/stretchr/testify v1.7.0
github.com/syndtr/goleveldb v1.0.0 github.com/syndtr/goleveldb v1.0.0
github.com/ziutek/mymysql v1.5.4 github.com/ziutek/mymysql v1.5.4
modernc.org/sqlite v1.10.1-0.20210314190707-798bbeb9bb84 gopkg.in/yaml.v2 v2.2.2 // indirect
xorm.io/builder v0.3.8 modernc.org/sqlite v1.11.2
xorm.io/builder v0.3.9
) )

35
go.sum
View File

@ -5,12 +5,18 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/denisenkom/go-mssqldb v0.9.0 h1:RSohk2RsiZqLZ0zCjtfn3S4Gp4exhpBWHyQ7D0yGjAk= github.com/denisenkom/go-mssqldb v0.9.0 h1:RSohk2RsiZqLZ0zCjtfn3S4Gp4exhpBWHyQ7D0yGjAk=
github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/denisenkom/go-mssqldb v0.10.0 h1:QykgLZBorFE95+gO3u9esLd0BmbvpWp0/waNNZfHBM8=
github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/goccy/go-json v0.7.4 h1:B44qRUFwz/vxPKPISQ1KhvzRi9kZ28RAf6YtjriBZ5k=
github.com/goccy/go-json v0.7.4/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
@ -28,12 +34,14 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNU
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/lib/pq v1.7.0 h1:h93mCPfUSkaul3Ka/VG8uZdmW1uMHDGxzu0NWHuJmHY= github.com/lib/pq v1.7.0 h1:h93mCPfUSkaul3Ka/VG8uZdmW1uMHDGxzu0NWHuJmHY=
github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8=
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg= github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/goccy/go-json v0.7.4 h1:B44qRUFwz/vxPKPISQ1KhvzRi9kZ28RAf6YtjriBZ5k= github.com/mattn/go-sqlite3 v1.14.8 h1:gDp86IdQsN/xWjIEmr9MF6o9mpksUgh0fu+9ByFxzIU=
github.com/goccy/go-json v0.7.4/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
@ -49,10 +57,13 @@ github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6O
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@ -103,28 +114,46 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
lukechampine.com/uint128 v1.1.1 h1:pnxCASz787iMf+02ssImqk6OLt+Z5QHMoZyUXR4z6JU=
lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
modernc.org/cc/v3 v3.31.5-0.20210308123301-7a3e9dab9009 h1:u0oCo5b9wyLr++HF3AN9JicGhkUxJhMz51+8TIZH9N0= modernc.org/cc/v3 v3.31.5-0.20210308123301-7a3e9dab9009 h1:u0oCo5b9wyLr++HF3AN9JicGhkUxJhMz51+8TIZH9N0=
modernc.org/cc/v3 v3.31.5-0.20210308123301-7a3e9dab9009/go.mod h1:0R6jl1aZlIl2avnYfbfHBS1QB6/f+16mihBObaBC878= modernc.org/cc/v3 v3.31.5-0.20210308123301-7a3e9dab9009/go.mod h1:0R6jl1aZlIl2avnYfbfHBS1QB6/f+16mihBObaBC878=
modernc.org/cc/v3 v3.33.6 h1:r63dgSzVzRxUpAJFPQWHy1QeZeY1ydNENUDaBx1GqYc=
modernc.org/cc/v3 v3.33.6/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
modernc.org/ccgo/v3 v3.9.0 h1:JbcEIqjw4Agf+0g3Tc85YvfYqkkFOv6xBwS4zkfqSoA= modernc.org/ccgo/v3 v3.9.0 h1:JbcEIqjw4Agf+0g3Tc85YvfYqkkFOv6xBwS4zkfqSoA=
modernc.org/ccgo/v3 v3.9.0/go.mod h1:nQbgkn8mwzPdp4mm6BT6+p85ugQ7FrGgIcYaE7nSrpY= modernc.org/ccgo/v3 v3.9.0/go.mod h1:nQbgkn8mwzPdp4mm6BT6+p85ugQ7FrGgIcYaE7nSrpY=
modernc.org/ccgo/v3 v3.9.5 h1:dEuUSf8WN51rDkprFuAqjfchKEzN0WttP/Py3enBwjk=
modernc.org/ccgo/v3 v3.9.5/go.mod h1:umuo2EP2oDSBnD3ckjaVUXMrmeAw8C8OSICVa0iFf60=
modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM= modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
modernc.org/libc v1.7.13-0.20210308123627-12f642a52bb8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w= modernc.org/libc v1.7.13-0.20210308123627-12f642a52bb8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w=
modernc.org/libc v1.8.0 h1:Pp4uv9g0csgBMpGPABKtkieF6O5MGhfGo6ZiOdlYfR8= modernc.org/libc v1.8.0 h1:Pp4uv9g0csgBMpGPABKtkieF6O5MGhfGo6ZiOdlYfR8=
modernc.org/libc v1.8.0/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w= modernc.org/libc v1.8.0/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w=
modernc.org/libc v1.9.8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w=
modernc.org/libc v1.9.11 h1:QUxZMs48Ahg2F7SN41aERvMfGLY2HU/ADnB9DC4Yts8=
modernc.org/libc v1.9.11/go.mod h1:NyF3tsA5ArIjJ83XB0JlqhjTabTCHm9aX4XMPHyQn0Q=
modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.2.2 h1:+yFk8hBprV+4c0U9GjFtL+dV3N8hOJ8JCituQcMShFY= modernc.org/mathutil v1.2.2 h1:+yFk8hBprV+4c0U9GjFtL+dV3N8hOJ8JCituQcMShFY=
modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.4.0 h1:GCjoRaBew8ECCKINQA2nYjzvufFW9YiEuuB+rQ9bn2E=
modernc.org/mathutil v1.4.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/memory v1.0.4 h1:utMBrFcpnQDdNsmM6asmyH/FM9TqLPS7XF7otpJmrwM= modernc.org/memory v1.0.4 h1:utMBrFcpnQDdNsmM6asmyH/FM9TqLPS7XF7otpJmrwM=
modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc= modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc=
modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A= modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A=
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/sqlite v1.10.1-0.20210314190707-798bbeb9bb84 h1:rgEUzE849tFlHSoeCrKyS9cZAljC+DY7MdMHKq6R6sY= modernc.org/sqlite v1.10.1-0.20210314190707-798bbeb9bb84 h1:rgEUzE849tFlHSoeCrKyS9cZAljC+DY7MdMHKq6R6sY=
modernc.org/sqlite v1.10.1-0.20210314190707-798bbeb9bb84/go.mod h1:PGzq6qlhyYjL6uVbSgS6WoF7ZopTW/sI7+7p+mb4ZVU= modernc.org/sqlite v1.10.1-0.20210314190707-798bbeb9bb84/go.mod h1:PGzq6qlhyYjL6uVbSgS6WoF7ZopTW/sI7+7p+mb4ZVU=
modernc.org/sqlite v1.11.2 h1:ShWQpeD3ag/bmx6TqidBlIWonWmQaSQKls3aenCbt+w=
modernc.org/sqlite v1.11.2/go.mod h1:+mhs/P1ONd+6G7hcAs6irwDi/bjTQ7nLW6LHRBsEa3A=
modernc.org/strutil v1.1.0 h1:+1/yCzZxY2pZwwrsbH+4T7BQMoLQ9QiBshRC9eicYsc= modernc.org/strutil v1.1.0 h1:+1/yCzZxY2pZwwrsbH+4T7BQMoLQ9QiBshRC9eicYsc=
modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
modernc.org/strutil v1.1.1 h1:xv+J1BXY3Opl2ALrBwyfEikFAj8pmqcpnfmuwUwcozs=
modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw=
modernc.org/tcl v1.5.0 h1:euZSUNfE0Fd4W8VqXI1Ly1v7fqDJoBuAV88Ea+SnaSs= modernc.org/tcl v1.5.0 h1:euZSUNfE0Fd4W8VqXI1Ly1v7fqDJoBuAV88Ea+SnaSs=
modernc.org/tcl v1.5.0/go.mod h1:gb57hj4pO8fRrK54zveIfFXBaMHK3SKJNWcmRw1cRzc= modernc.org/tcl v1.5.0/go.mod h1:gb57hj4pO8fRrK54zveIfFXBaMHK3SKJNWcmRw1cRzc=
modernc.org/tcl v1.5.5/go.mod h1:ADkaTUuwukkrlhqwERyq0SM8OvyXo7+TjFz7yAF56EI=
modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk= modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk=
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/z v1.0.1-0.20210308123920-1f282aa71362/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA= modernc.org/z v1.0.1-0.20210308123920-1f282aa71362/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA=
@ -132,3 +161,5 @@ modernc.org/z v1.0.1 h1:WyIDpEpAIx4Hel6q/Pcgj/VhaQV5XPJ2I6ryIYbjnpc=
modernc.org/z v1.0.1/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA= modernc.org/z v1.0.1/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA=
xorm.io/builder v0.3.8 h1:P/wPgRqa9kX5uE0aA1/ukJ23u9KH0aSRpHLwDKXigSE= xorm.io/builder v0.3.8 h1:P/wPgRqa9kX5uE0aA1/ukJ23u9KH0aSRpHLwDKXigSE=
xorm.io/builder v0.3.8/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE= xorm.io/builder v0.3.8/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
xorm.io/builder v0.3.9 h1:Sd65/LdWyO7LR8+Cbd+e7mm3sK/7U9k0jS3999IDHMc=
xorm.io/builder v0.3.9/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=

View File

@ -172,7 +172,6 @@ func TestDumpTables(t *testing.T) {
name := fmt.Sprintf("dump_%v-table.sql", tp) name := fmt.Sprintf("dump_%v-table.sql", tp)
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
assert.NoError(t, testEngine.(*xorm.Engine).DumpTablesToFile([]*schemas.Table{tb}, name, tp)) assert.NoError(t, testEngine.(*xorm.Engine).DumpTablesToFile([]*schemas.Table{tb}, name, tp))
}) })
} }

View File

@ -818,8 +818,9 @@ func TestGetBigFloat(t *testing.T) {
} }
type GetBigFloat2 struct { type GetBigFloat2 struct {
Id int64 Id int64
Money *big.Float `xorm:"decimal(22,2)"` Money *big.Float `xorm:"decimal(22,2)"`
Money2 big.Float `xorm:"decimal(22,2)"`
} }
assert.NoError(t, PrepareEngine()) assert.NoError(t, PrepareEngine())
@ -827,7 +828,8 @@ func TestGetBigFloat(t *testing.T) {
{ {
var gf2 = GetBigFloat2{ var gf2 = GetBigFloat2{
Money: big.NewFloat(9999999.99), Money: big.NewFloat(9999999.99),
Money2: *big.NewFloat(99.99),
} }
_, err := testEngine.Insert(&gf2) _, err := testEngine.Insert(&gf2)
assert.NoError(t, err) assert.NoError(t, err)
@ -845,12 +847,14 @@ func TestGetBigFloat(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
assert.True(t, has) assert.True(t, has)
assert.True(t, gf3.Money.String() == gf2.Money.String(), "%v != %v", gf3.Money.String(), gf2.Money.String()) assert.True(t, gf3.Money.String() == gf2.Money.String(), "%v != %v", gf3.Money.String(), gf2.Money.String())
assert.True(t, gf3.Money2.String() == gf2.Money2.String(), "%v != %v", gf3.Money2.String(), gf2.Money2.String())
var gfs []GetBigFloat2 var gfs []GetBigFloat2
err = testEngine.Find(&gfs) err = testEngine.Find(&gfs)
assert.NoError(t, err) assert.NoError(t, err)
assert.EqualValues(t, 1, len(gfs)) assert.EqualValues(t, 1, len(gfs))
assert.True(t, gfs[0].Money.String() == gf2.Money.String(), "%v != %v", gfs[0].Money.String(), gf2.Money.String()) assert.True(t, gfs[0].Money.String() == gf2.Money.String(), "%v != %v", gfs[0].Money.String(), gf2.Money.String())
assert.True(t, gfs[0].Money2.String() == gf2.Money2.String(), "%v != %v", gfs[0].Money2.String(), gf2.Money2.String())
} }
} }

View File

@ -202,7 +202,7 @@ func TestInsertDefault2(t *testing.T) {
Id int64 Id int64
Name string Name string
Url string `xorm:"text"` Url string `xorm:"text"`
CheckTime time.Time `xorm:"not null default '2000-01-01 00:00:00' TIMESTAMP"` CheckTime time.Time `xorm:"not null default '2000-01-01 00:00:00'"`
} }
di := new(DefaultInsert2) di := new(DefaultInsert2)

View File

@ -1313,7 +1313,6 @@ func TestUpdateIgnoreOnlyFromDBFields(t *testing.T) {
assert.EqualValues(t, true, has) assert.EqualValues(t, true, has)
assert.EqualValues(t, "", record.OnlyFromDBField) assert.EqualValues(t, "", record.OnlyFromDBField)
return &record return &record
} }
assert.NoError(t, PrepareEngine()) assert.NoError(t, PrepareEngine())
assertSync(t, new(TestOnlyFromDBField)) assertSync(t, new(TestOnlyFromDBField))

View File

@ -8,6 +8,7 @@ import (
"database/sql/driver" "database/sql/driver"
"errors" "errors"
"fmt" "fmt"
"math/big"
"reflect" "reflect"
"strings" "strings"
"time" "time"
@ -662,10 +663,6 @@ func (statement *Statement) GenIndexSQL() []string {
return sqls return sqls
} }
func uniqueName(tableName, uqeName string) string {
return fmt.Sprintf("UQE_%v_%v", tableName, uqeName)
}
// GenUniqueSQL generates unique SQL // GenUniqueSQL generates unique SQL
func (statement *Statement) GenUniqueSQL() []string { func (statement *Statement) GenUniqueSQL() []string {
var sqls []string var sqls []string
@ -693,6 +690,138 @@ func (statement *Statement) GenDelIndexSQL() []string {
return sqls return sqls
} }
func (statement *Statement) asDBCond(fieldValue reflect.Value, fieldType reflect.Type, col *schemas.Column, allUseBool, requiredField bool) (interface{}, bool, error) {
switch fieldType.Kind() {
case reflect.Ptr:
if fieldValue.IsNil() {
return nil, true, nil
}
return statement.asDBCond(fieldValue.Elem(), fieldType.Elem(), col, allUseBool, requiredField)
case reflect.Bool:
if allUseBool || requiredField {
return fieldValue.Interface(), true, nil
}
// if a bool in a struct, it will not be as a condition because it default is false,
// please use Where() instead
return nil, false, nil
case reflect.String:
if !requiredField && fieldValue.String() == "" {
return nil, false, nil
}
// for MyString, should convert to string or panic
if fieldType.String() != reflect.String.String() {
return fieldValue.String(), true, nil
}
return fieldValue.Interface(), true, nil
case reflect.Int8, reflect.Int16, reflect.Int, reflect.Int32, reflect.Int64:
if !requiredField && fieldValue.Int() == 0 {
return nil, false, nil
}
return fieldValue.Interface(), true, nil
case reflect.Float32, reflect.Float64:
if !requiredField && fieldValue.Float() == 0.0 {
return nil, false, nil
}
return fieldValue.Interface(), true, nil
case reflect.Uint8, reflect.Uint16, reflect.Uint, reflect.Uint32, reflect.Uint64:
if !requiredField && fieldValue.Uint() == 0 {
return nil, false, nil
}
return fieldValue.Interface(), true, nil
case reflect.Struct:
if fieldType.ConvertibleTo(schemas.TimeType) {
t := fieldValue.Convert(schemas.TimeType).Interface().(time.Time)
if !requiredField && (t.IsZero() || !fieldValue.IsValid()) {
return nil, false, nil
}
return dialects.FormatColumnTime(statement.dialect, statement.defaultTimeZone, col, t), true, nil
} else if fieldType.ConvertibleTo(schemas.BigFloatType) {
t := fieldValue.Convert(schemas.BigFloatType).Interface().(big.Float)
v := t.String()
if v == "0" {
return nil, false, nil
}
return t.String(), true, nil
} else if _, ok := reflect.New(fieldType).Interface().(convert.Conversion); ok {
return nil, false, nil
} else if valNul, ok := fieldValue.Interface().(driver.Valuer); ok {
val, _ := valNul.Value()
if val == nil && !requiredField {
return nil, false, nil
}
return val, true, nil
} else {
if col.IsJSON {
if col.SQLType.IsText() {
bytes, err := json.DefaultJSONHandler.Marshal(fieldValue.Interface())
if err != nil {
return nil, false, err
}
return string(bytes), true, nil
} else if col.SQLType.IsBlob() {
var bytes []byte
var err error
bytes, err = json.DefaultJSONHandler.Marshal(fieldValue.Interface())
if err != nil {
return nil, false, err
}
return bytes, true, nil
}
} else {
table, err := statement.tagParser.ParseWithCache(fieldValue)
if err != nil {
return fieldValue.Interface(), true, nil
}
if len(table.PrimaryKeys) == 1 {
pkField := reflect.Indirect(fieldValue).FieldByName(table.PKColumns()[0].FieldName)
// fix non-int pk issues
//if pkField.Int() != 0 {
if pkField.IsValid() && !utils.IsZero(pkField.Interface()) {
return pkField.Interface(), true, nil
}
return nil, false, nil
}
return nil, false, fmt.Errorf("not supported %v as %v", fieldValue.Interface(), table.PrimaryKeys)
}
}
case reflect.Array:
return nil, false, nil
case reflect.Slice, reflect.Map:
if fieldValue == reflect.Zero(fieldType) {
return nil, false, nil
}
if fieldValue.IsNil() || !fieldValue.IsValid() || fieldValue.Len() == 0 {
return nil, false, nil
}
if col.SQLType.IsText() {
bytes, err := json.DefaultJSONHandler.Marshal(fieldValue.Interface())
if err != nil {
return nil, false, err
}
return string(bytes), true, nil
} else if col.SQLType.IsBlob() {
var bytes []byte
var err error
if (fieldType.Kind() == reflect.Array || fieldType.Kind() == reflect.Slice) &&
fieldType.Elem().Kind() == reflect.Uint8 {
if fieldValue.Len() > 0 {
return fieldValue.Bytes(), true, nil
}
return nil, false, nil
}
bytes, err = json.DefaultJSONHandler.Marshal(fieldValue.Interface())
if err != nil {
return nil, false, err
}
return bytes, true, nil
}
return nil, false, nil
}
return fieldValue.Interface(), true, nil
}
func (statement *Statement) buildConds2(table *schemas.Table, bean interface{}, func (statement *Statement) buildConds2(table *schemas.Table, bean interface{},
includeVersion bool, includeUpdated bool, includeNil bool, includeVersion bool, includeUpdated bool, includeNil bool,
includeAutoIncr bool, allUseBool bool, useAllCols bool, unscoped bool, includeAutoIncr bool, allUseBool bool, useAllCols bool, unscoped bool,
@ -747,9 +876,7 @@ func (statement *Statement) buildConds2(table *schemas.Table, bean interface{},
continue continue
} }
fieldType := reflect.TypeOf(fieldValue.Interface())
requiredField := useAllCols requiredField := useAllCols
if b, ok := getFlagForColumn(mustColumnMap, col); ok { if b, ok := getFlagForColumn(mustColumnMap, col); ok {
if b { if b {
requiredField = true requiredField = true
@ -758,6 +885,7 @@ func (statement *Statement) buildConds2(table *schemas.Table, bean interface{},
} }
} }
fieldType := reflect.TypeOf(fieldValue.Interface())
if fieldType.Kind() == reflect.Ptr { if fieldType.Kind() == reflect.Ptr {
if fieldValue.IsNil() { if fieldValue.IsNil() {
if includeNil { if includeNil {
@ -774,131 +902,12 @@ func (statement *Statement) buildConds2(table *schemas.Table, bean interface{},
} }
} }
var val interface{} val, ok, err := statement.asDBCond(fieldValue, fieldType, col, allUseBool, requiredField)
switch fieldType.Kind() { if err != nil {
case reflect.Bool: return nil, err
if allUseBool || requiredField { }
val = fieldValue.Interface() if !ok {
} else {
// if a bool in a struct, it will not be as a condition because it default is false,
// please use Where() instead
continue
}
case reflect.String:
if !requiredField && fieldValue.String() == "" {
continue
}
// for MyString, should convert to string or panic
if fieldType.String() != reflect.String.String() {
val = fieldValue.String()
} else {
val = fieldValue.Interface()
}
case reflect.Int8, reflect.Int16, reflect.Int, reflect.Int32, reflect.Int64:
if !requiredField && fieldValue.Int() == 0 {
continue
}
val = fieldValue.Interface()
case reflect.Float32, reflect.Float64:
if !requiredField && fieldValue.Float() == 0.0 {
continue
}
val = fieldValue.Interface()
case reflect.Uint8, reflect.Uint16, reflect.Uint, reflect.Uint32, reflect.Uint64:
if !requiredField && fieldValue.Uint() == 0 {
continue
}
val = fieldValue.Interface()
case reflect.Struct:
if fieldType.ConvertibleTo(schemas.TimeType) {
t := fieldValue.Convert(schemas.TimeType).Interface().(time.Time)
if !requiredField && (t.IsZero() || !fieldValue.IsValid()) {
continue
}
val = dialects.FormatColumnTime(statement.dialect, statement.defaultTimeZone, col, t)
} else if _, ok := reflect.New(fieldType).Interface().(convert.Conversion); ok {
continue
} else if valNul, ok := fieldValue.Interface().(driver.Valuer); ok {
val, _ = valNul.Value()
if val == nil && !requiredField {
continue
}
} else {
if col.IsJSON {
if col.SQLType.IsText() {
bytes, err := json.DefaultJSONHandler.Marshal(fieldValue.Interface())
if err != nil {
return nil, err
}
val = string(bytes)
} else if col.SQLType.IsBlob() {
var bytes []byte
var err error
bytes, err = json.DefaultJSONHandler.Marshal(fieldValue.Interface())
if err != nil {
return nil, err
}
val = bytes
}
} else {
table, err := statement.tagParser.ParseWithCache(fieldValue)
if err != nil {
val = fieldValue.Interface()
} else {
if len(table.PrimaryKeys) == 1 {
pkField := reflect.Indirect(fieldValue).FieldByName(table.PKColumns()[0].FieldName)
// fix non-int pk issues
//if pkField.Int() != 0 {
if pkField.IsValid() && !utils.IsZero(pkField.Interface()) {
val = pkField.Interface()
} else {
continue
}
} else {
//TODO: how to handler?
return nil, fmt.Errorf("not supported %v as %v", fieldValue.Interface(), table.PrimaryKeys)
}
}
}
}
case reflect.Array:
continue continue
case reflect.Slice, reflect.Map:
if fieldValue == reflect.Zero(fieldType) {
continue
}
if fieldValue.IsNil() || !fieldValue.IsValid() || fieldValue.Len() == 0 {
continue
}
if col.SQLType.IsText() {
bytes, err := json.DefaultJSONHandler.Marshal(fieldValue.Interface())
if err != nil {
return nil, err
}
val = string(bytes)
} else if col.SQLType.IsBlob() {
var bytes []byte
var err error
if (fieldType.Kind() == reflect.Array || fieldType.Kind() == reflect.Slice) &&
fieldType.Elem().Kind() == reflect.Uint8 {
if fieldValue.Len() > 0 {
val = fieldValue.Bytes()
} else {
continue
}
} else {
bytes, err = json.DefaultJSONHandler.Marshal(fieldValue.Interface())
if err != nil {
return nil, err
}
val = bytes
}
} else {
continue
}
default:
val = fieldValue.Interface()
} }
conds = append(conds, builder.Eq{colName: val}) conds = append(conds, builder.Eq{colName: val})

View File

@ -23,7 +23,7 @@ var (
bigFloatType = reflect.TypeOf(big.Float{}) bigFloatType = reflect.TypeOf(big.Float{})
) )
// Value2Interface convert a field value of a struct to interface for puting into database // Value2Interface convert a field value of a struct to interface for putting into database
func (statement *Statement) Value2Interface(col *schemas.Column, fieldValue reflect.Value) (interface{}, error) { func (statement *Statement) Value2Interface(col *schemas.Column, fieldValue reflect.Value) (interface{}, error) {
if fieldValue.CanAddr() { if fieldValue.CanAddr() {
if fieldConvert, ok := fieldValue.Addr().Interface().(convert.Conversion); ok { if fieldConvert, ok := fieldValue.Addr().Interface().(convert.Conversion); ok {

View File

@ -13,7 +13,7 @@ func IndexNoCase(s, sep string) int {
return strings.Index(strings.ToLower(s), strings.ToLower(sep)) return strings.Index(strings.ToLower(s), strings.ToLower(sep))
} }
// SplitNoCase split a string by a seperator with no care of capitalize // SplitNoCase split a string by a separator with no care of capitalize
func SplitNoCase(s, sep string) []string { func SplitNoCase(s, sep string) []string {
idx := IndexNoCase(s, sep) idx := IndexNoCase(s, sep)
if idx < 0 { if idx < 0 {
@ -22,7 +22,7 @@ func SplitNoCase(s, sep string) []string {
return strings.Split(s, s[idx:idx+len(sep)]) return strings.Split(s, s[idx:idx+len(sep)])
} }
// SplitNNoCase split n by a seperator with no care of capitalize // SplitNNoCase split n by a separator with no care of capitalize
func SplitNNoCase(s, sep string, n int) []string { func SplitNNoCase(s, sep string, n int) []string {
idx := IndexNoCase(s, sep) idx := IndexNoCase(s, sep)
if idx < 0 { if idx < 0 {

View File

@ -79,7 +79,7 @@ func (m SameMapper) Table2Obj(t string) string {
return t return t
} }
// SnakeMapper implements IMapper and provides name transaltion between // SnakeMapper implements IMapper and provides name translation between
// struct and database table // struct and database table
type SnakeMapper struct { type SnakeMapper struct {
} }

35
rows.go
View File

@ -5,7 +5,6 @@
package xorm package xorm
import ( import (
"database/sql"
"errors" "errors"
"fmt" "fmt"
"reflect" "reflect"
@ -17,10 +16,9 @@ import (
// Rows rows wrapper a rows to // Rows rows wrapper a rows to
type Rows struct { type Rows struct {
session *Session session *Session
rows *core.Rows rows *core.Rows
beanType reflect.Type beanType reflect.Type
lastError error
} }
func newRows(session *Session, bean interface{}) (*Rows, error) { func newRows(session *Session, bean interface{}) (*Rows, error) {
@ -62,15 +60,6 @@ func newRows(session *Session, bean interface{}) (*Rows, error) {
// !oinume! Add "<col> IS NULL" to WHERE whatever condiBean is given. // !oinume! Add "<col> IS NULL" to WHERE whatever condiBean is given.
// See https://gitea.com/xorm/xorm/issues/179 // See https://gitea.com/xorm/xorm/issues/179
if col := table.DeletedColumn(); col != nil && !session.statement.GetUnscoped() { // tag "deleted" is enabled if col := table.DeletedColumn(); col != nil && !session.statement.GetUnscoped() { // tag "deleted" is enabled
var colName = session.engine.Quote(col.Name)
if addedTableName {
var nm = session.statement.TableName()
if len(session.statement.TableAlias) > 0 {
nm = session.statement.TableAlias
}
colName = session.engine.Quote(nm) + "." + colName
}
autoCond = session.statement.CondDeleted(col) autoCond = session.statement.CondDeleted(col)
} }
} }
@ -86,7 +75,6 @@ func newRows(session *Session, bean interface{}) (*Rows, error) {
rows.rows, err = rows.session.queryRows(sqlStr, args...) rows.rows, err = rows.session.queryRows(sqlStr, args...)
if err != nil { if err != nil {
rows.lastError = err
rows.Close() rows.Close()
return nil, err return nil, err
} }
@ -96,25 +84,18 @@ func newRows(session *Session, bean interface{}) (*Rows, error) {
// Next move cursor to next record, return false if end has reached // Next move cursor to next record, return false if end has reached
func (rows *Rows) Next() bool { func (rows *Rows) Next() bool {
if rows.lastError == nil && rows.rows != nil { return rows.rows.Next()
hasNext := rows.rows.Next()
if !hasNext {
rows.lastError = sql.ErrNoRows
}
return hasNext
}
return false
} }
// Err returns the error, if any, that was encountered during iteration. Err may be called after an explicit or implicit Close. // Err returns the error, if any, that was encountered during iteration. Err may be called after an explicit or implicit Close.
func (rows *Rows) Err() error { func (rows *Rows) Err() error {
return rows.lastError return rows.rows.Err()
} }
// Scan row record to bean properties // Scan row record to bean properties
func (rows *Rows) Scan(bean interface{}) error { func (rows *Rows) Scan(bean interface{}) error {
if rows.lastError != nil { if rows.Err() != nil {
return rows.lastError return rows.Err()
} }
if reflect.Indirect(reflect.ValueOf(bean)).Type() != rows.beanType { if reflect.Indirect(reflect.ValueOf(bean)).Type() != rows.beanType {
@ -158,5 +139,5 @@ func (rows *Rows) Close() error {
return rows.rows.Close() return rows.rows.Close()
} }
return rows.lastError return rows.Err()
} }

14
scan.go
View File

@ -211,12 +211,8 @@ func (engine *Engine) scan(rows *core.Rows, fields []string, types []*sql.Column
scanResult = &sql.RawBytes{} scanResult = &sql.RawBytes{}
replaced = true replaced = true
default: default:
var useNullable = true nullable, ok := types[0].Nullable()
if engine.driver.Features().SupportNullable { if !ok || nullable {
nullable, ok := types[0].Nullable()
useNullable = ok && nullable
}
if useNullable {
scanResult, replaced, err = genScanResultsByBeanNullable(v) scanResult, replaced, err = genScanResultsByBeanNullable(v)
} else { } else {
scanResult, replaced, err = genScanResultsByBean(v) scanResult, replaced, err = genScanResultsByBean(v)
@ -286,15 +282,15 @@ func rows2maps(rows *core.Rows) (resultsSlice []map[string][]byte, err error) {
return nil, err return nil, err
} }
for rows.Next() { for rows.Next() {
if rows.Err() != nil {
return nil, rows.Err()
}
result, err := row2mapBytes(rows, types, fields) result, err := row2mapBytes(rows, types, fields)
if err != nil { if err != nil {
return nil, err return nil, err
} }
resultsSlice = append(resultsSlice, result) resultsSlice = append(resultsSlice, result)
} }
if rows.Err() != nil {
return nil, rows.Err()
}
return resultsSlice, nil return resultsSlice, nil
} }

View File

@ -58,7 +58,6 @@ func TestGetColumnIdx(t *testing.T) {
func BenchmarkGetColumnWithToLower(b *testing.B) { func BenchmarkGetColumnWithToLower(b *testing.B) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
for _, test := range testsGetColumn { for _, test := range testsGetColumn {
if _, ok := table.columnsMap[strings.ToLower(test.name)]; !ok { if _, ok := table.columnsMap[strings.ToLower(test.name)]; !ok {
b.Errorf("Column not found:%s", test.name) b.Errorf("Column not found:%s", test.name)
} }
@ -69,7 +68,6 @@ func BenchmarkGetColumnWithToLower(b *testing.B) {
func BenchmarkGetColumnIdxWithToLower(b *testing.B) { func BenchmarkGetColumnIdxWithToLower(b *testing.B) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
for _, test := range testsGetColumn { for _, test := range testsGetColumn {
if c, ok := table.columnsMap[strings.ToLower(test.name)]; ok { if c, ok := table.columnsMap[strings.ToLower(test.name)]; ok {
if test.idx < len(c) { if test.idx < len(c) {
continue continue

View File

@ -65,6 +65,7 @@ func (s *SQLType) IsTime() bool {
return s.IsType(TIME_TYPE) return s.IsType(TIME_TYPE)
} }
// IsBool returns true if column is a boolean type
func (s *SQLType) IsBool() bool { func (s *SQLType) IsBool() bool {
return s.IsType(BOOL_TYPE) return s.IsType(BOOL_TYPE)
} }

View File

@ -391,9 +391,6 @@ func (session *Session) rows2Beans(rows *core.Rows, fields []string, types []*sq
table *schemas.Table, newElemFunc func([]string) reflect.Value, table *schemas.Table, newElemFunc func([]string) reflect.Value,
sliceValueSetFunc func(*reflect.Value, schemas.PK) error) error { sliceValueSetFunc func(*reflect.Value, schemas.PK) error) error {
for rows.Next() { for rows.Next() {
if rows.Err() != nil {
return rows.Err()
}
var newValue = newElemFunc(fields) var newValue = newElemFunc(fields)
bean := newValue.Interface() bean := newValue.Interface()
dataStruct := newValue.Elem() dataStruct := newValue.Elem()
@ -415,7 +412,7 @@ func (session *Session) rows2Beans(rows *core.Rows, fields []string, types []*sq
bean: bean, bean: bean,
}) })
} }
return nil return rows.Err()
} }
func (session *Session) row2Slice(rows *core.Rows, fields []string, types []*sql.ColumnType, bean interface{}) ([]interface{}, error) { func (session *Session) row2Slice(rows *core.Rows, fields []string, types []*sql.ColumnType, bean interface{}) ([]interface{}, error) {

View File

@ -25,5 +25,8 @@ func (session *Session) Exist(bean ...interface{}) (bool, error) {
} }
defer rows.Close() defer rows.Close()
return rows.Next(), nil if rows.Next() {
return true, nil
}
return false, rows.Err()
} }

View File

@ -255,9 +255,6 @@ func (session *Session) noCacheFind(table *schemas.Table, containerValue reflect
} }
for rows.Next() { for rows.Next() {
if rows.Err() != nil {
return rows.Err()
}
var newValue = newElemFunc(fields) var newValue = newElemFunc(fields)
bean := newValue.Interface() bean := newValue.Interface()
@ -278,7 +275,7 @@ func (session *Session) noCacheFind(table *schemas.Table, containerValue reflect
return err return err
} }
} }
return nil return rows.Err()
} }
func convertPKToValue(table *schemas.Table, dst interface{}, pk schemas.PK) error { func convertPKToValue(table *schemas.Table, dst interface{}, pk schemas.PK) error {
@ -325,9 +322,6 @@ func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr in
var i int var i int
ids = make([]schemas.PK, 0) ids = make([]schemas.PK, 0)
for rows.Next() { for rows.Next() {
if rows.Err() != nil {
return rows.Err()
}
i++ i++
if i > 500 { if i > 500 {
session.engine.logger.Debugf("[cacheFind] ids length > 500, no cache") session.engine.logger.Debugf("[cacheFind] ids length > 500, no cache")
@ -348,6 +342,9 @@ func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr in
ids = append(ids, pk) ids = append(ids, pk)
} }
if rows.Err() != nil {
return rows.Err()
}
session.engine.logger.Debugf("[cache] cache sql: %v, %v, %v, %v, %v", ids, tableName, sqlStr, newsql, args) session.engine.logger.Debugf("[cache] cache sql: %v, %v, %v, %v, %v", ids, tableName, sqlStr, newsql, args)
err = caches.PutCacheSql(cacher, ids, tableName, newsql, args) err = caches.PutCacheSql(cacher, ids, tableName, newsql, args)

View File

@ -159,10 +159,7 @@ func (session *Session) nocacheGet(beanKind reflect.Kind, table *schemas.Table,
defer rows.Close() defer rows.Close()
if !rows.Next() { if !rows.Next() {
if rows.Err() != nil { return false, rows.Err()
return false, rows.Err()
}
return false, nil
} }
// WARN: Alougth rows return true, but we may also return error. // WARN: Alougth rows return true, but we may also return error.
@ -313,14 +310,14 @@ func (session *Session) cacheGet(bean interface{}, sqlStr string, args ...interf
defer rows.Close() defer rows.Close()
if rows.Next() { if rows.Next() {
if rows.Err() != nil {
return true, rows.Err()
}
err = rows.ScanSlice(&res) err = rows.ScanSlice(&res)
if err != nil { if err != nil {
return true, err return true, err
} }
} else { } else {
if rows.Err() != nil {
return false, rows.Err()
}
return false, ErrCacheFailed return false, ErrCacheFailed
} }

View File

@ -325,7 +325,6 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
copy(afterClosures, session.afterClosures) copy(afterClosures, session.afterClosures)
session.afterInsertBeans[bean] = &afterClosures session.afterInsertBeans[bean] = &afterClosures
} }
} else { } else {
if _, ok := interface{}(bean).(AfterInsertProcessor); ok { if _, ok := interface{}(bean).(AfterInsertProcessor); ok {
session.afterInsertBeans[bean] = nil session.afterInsertBeans[bean] = nil

View File

@ -43,9 +43,6 @@ func (session *Session) Iterate(bean interface{}, fun IterFunc) error {
i := 0 i := 0
for rows.Next() { for rows.Next() {
if rows.Err() != nil {
return rows.Err()
}
b := reflect.New(rows.beanType).Interface() b := reflect.New(rows.beanType).Interface()
err = rows.Scan(b) err = rows.Scan(b)
if err != nil { if err != nil {
@ -57,7 +54,7 @@ func (session *Session) Iterate(bean interface{}, fun IterFunc) error {
} }
i++ i++
} }
return err return rows.Err()
} }
// BufferSize sets the buffersize for iterate // BufferSize sets the buffersize for iterate

View File

@ -33,15 +33,15 @@ func (session *Session) rows2Strings(rows *core.Rows) (resultsSlice []map[string
} }
for rows.Next() { for rows.Next() {
if rows.Err() != nil {
return nil, rows.Err()
}
result, err := session.engine.row2mapStr(rows, types, fields) result, err := session.engine.row2mapStr(rows, types, fields)
if err != nil { if err != nil {
return nil, err return nil, err
} }
resultsSlice = append(resultsSlice, result) resultsSlice = append(resultsSlice, result)
} }
if rows.Err() != nil {
return nil, rows.Err()
}
return resultsSlice, nil return resultsSlice, nil
} }
@ -57,15 +57,15 @@ func (session *Session) rows2SliceString(rows *core.Rows) (resultsSlice [][]stri
} }
for rows.Next() { for rows.Next() {
if rows.Err() != nil {
return nil, rows.Err()
}
record, err := session.engine.row2sliceStr(rows, types, fields) record, err := session.engine.row2sliceStr(rows, types, fields)
if err != nil { if err != nil {
return nil, err return nil, err
} }
resultsSlice = append(resultsSlice, record) resultsSlice = append(resultsSlice, record)
} }
if rows.Err() != nil {
return nil, rows.Err()
}
return resultsSlice, nil return resultsSlice, nil
} }
@ -120,15 +120,15 @@ func (session *Session) rows2Interfaces(rows *core.Rows) (resultsSlice []map[str
return nil, err return nil, err
} }
for rows.Next() { for rows.Next() {
if rows.Err() != nil {
return nil, rows.Err()
}
result, err := session.engine.row2mapInterface(rows, types, fields) result, err := session.engine.row2mapInterface(rows, types, fields)
if err != nil { if err != nil {
return nil, err return nil, err
} }
resultsSlice = append(resultsSlice, result) resultsSlice = append(resultsSlice, result)
} }
if rows.Err() != nil {
return nil, rows.Err()
}
return resultsSlice, nil return resultsSlice, nil
} }

View File

@ -59,9 +59,6 @@ func (session *Session) cacheUpdate(table *schemas.Table, tableName, sqlStr stri
ids = make([]schemas.PK, 0) ids = make([]schemas.PK, 0)
for rows.Next() { for rows.Next() {
if rows.Err() != nil {
return rows.Err()
}
var res = make([]string, len(table.PrimaryKeys)) var res = make([]string, len(table.PrimaryKeys))
err = rows.ScanSlice(&res) err = rows.ScanSlice(&res)
if err != nil { if err != nil {
@ -84,6 +81,9 @@ func (session *Session) cacheUpdate(table *schemas.Table, tableName, sqlStr stri
ids = append(ids, pk) ids = append(ids, pk)
} }
if rows.Err() != nil {
return rows.Err()
}
session.engine.logger.Debugf("[cache] find updated id: %v", ids) session.engine.logger.Debugf("[cache] find updated id: %v", ids)
} /*else { } /*else {
session.engine.LogDebug("[xorm:cacheUpdate] del cached sql:", tableName, newsql, args) session.engine.LogDebug("[xorm:cacheUpdate] del cached sql:", tableName, newsql, args)

View File

@ -124,6 +124,7 @@ func addIndex(indexName string, table *schemas.Table, col *schemas.Column, index
} }
} }
// ErrIgnoreField represents an error to ignore field
var ErrIgnoreField = errors.New("field will be ignored") var ErrIgnoreField = errors.New("field will be ignored")
func (parser *Parser) parseFieldWithNoTag(fieldIndex int, field reflect.StructField, fieldValue reflect.Value) (*schemas.Column, error) { func (parser *Parser) parseFieldWithNoTag(fieldIndex int, field reflect.StructField, fieldValue reflect.Value) (*schemas.Column, error) {