2019-11-18 09:03:31 +00:00
|
|
|
// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
|
|
|
|
// Use of this source code is governed by an MIT-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
2016-11-03 15:03:16 +00:00
|
|
|
package sqlite3
|
|
|
|
|
|
|
|
/*
|
|
|
|
#ifndef USE_LIBSQLITE3
|
|
|
|
#include <sqlite3-binding.h>
|
|
|
|
#else
|
|
|
|
#include <sqlite3.h>
|
|
|
|
#endif
|
|
|
|
*/
|
|
|
|
import "C"
|
|
|
|
import (
|
2021-10-25 15:19:41 +00:00
|
|
|
"database/sql"
|
2016-11-03 15:03:16 +00:00
|
|
|
"reflect"
|
2021-10-25 15:19:41 +00:00
|
|
|
"strings"
|
2016-11-03 15:03:16 +00:00
|
|
|
)
|
|
|
|
|
2016-11-06 04:16:38 +00:00
|
|
|
// ColumnTypeDatabaseTypeName implement RowsColumnTypeDatabaseTypeName.
|
2016-11-03 15:03:16 +00:00
|
|
|
func (rc *SQLiteRows) ColumnTypeDatabaseTypeName(i int) string {
|
|
|
|
return C.GoString(C.sqlite3_column_decltype(rc.s.s, C.int(i)))
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
func (rc *SQLiteRows) ColumnTypeLength(index int) (length int64, ok bool) {
|
|
|
|
return 0, false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (rc *SQLiteRows) ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool) {
|
|
|
|
return 0, 0, false
|
|
|
|
}
|
2021-10-25 15:19:41 +00:00
|
|
|
*/
|
2016-11-03 15:03:16 +00:00
|
|
|
|
2016-11-06 04:16:38 +00:00
|
|
|
// ColumnTypeNullable implement RowsColumnTypeNullable.
|
2016-11-03 15:03:16 +00:00
|
|
|
func (rc *SQLiteRows) ColumnTypeNullable(i int) (nullable, ok bool) {
|
2021-10-25 15:19:41 +00:00
|
|
|
return true, true
|
2016-11-03 15:03:16 +00:00
|
|
|
}
|
|
|
|
|
2016-11-06 04:16:38 +00:00
|
|
|
// ColumnTypeScanType implement RowsColumnTypeScanType.
|
2016-11-03 15:03:16 +00:00
|
|
|
func (rc *SQLiteRows) ColumnTypeScanType(i int) reflect.Type {
|
2021-10-25 15:19:41 +00:00
|
|
|
//ct := C.sqlite3_column_type(rc.s.s, C.int(i)) // Always returns 5
|
|
|
|
return scanType(C.GoString(C.sqlite3_column_decltype(rc.s.s, C.int(i))))
|
|
|
|
}
|
|
|
|
|
|
|
|
const (
|
|
|
|
SQLITE_INTEGER = iota
|
|
|
|
SQLITE_TEXT
|
|
|
|
SQLITE_BLOB
|
|
|
|
SQLITE_REAL
|
|
|
|
SQLITE_NUMERIC
|
|
|
|
SQLITE_TIME
|
|
|
|
SQLITE_BOOL
|
|
|
|
SQLITE_NULL
|
|
|
|
)
|
|
|
|
|
|
|
|
func scanType(cdt string) reflect.Type {
|
|
|
|
t := strings.ToUpper(cdt)
|
|
|
|
i := databaseTypeConvSqlite(t)
|
|
|
|
switch i {
|
|
|
|
case SQLITE_INTEGER:
|
|
|
|
return reflect.TypeOf(sql.NullInt64{})
|
|
|
|
case SQLITE_TEXT:
|
|
|
|
return reflect.TypeOf(sql.NullString{})
|
|
|
|
case SQLITE_BLOB:
|
|
|
|
return reflect.TypeOf(sql.RawBytes{})
|
|
|
|
case SQLITE_REAL:
|
|
|
|
return reflect.TypeOf(sql.NullFloat64{})
|
|
|
|
case SQLITE_NUMERIC:
|
|
|
|
return reflect.TypeOf(sql.NullFloat64{})
|
|
|
|
case SQLITE_BOOL:
|
|
|
|
return reflect.TypeOf(sql.NullBool{})
|
|
|
|
case SQLITE_TIME:
|
|
|
|
return reflect.TypeOf(sql.NullTime{})
|
|
|
|
}
|
|
|
|
return reflect.TypeOf(new(interface{}))
|
|
|
|
}
|
|
|
|
|
|
|
|
func databaseTypeConvSqlite(t string) int {
|
|
|
|
if strings.Contains(t, "INT") {
|
|
|
|
return SQLITE_INTEGER
|
|
|
|
}
|
|
|
|
if t == "CLOB" || t == "TEXT" ||
|
|
|
|
strings.Contains(t, "CHAR") {
|
|
|
|
return SQLITE_TEXT
|
|
|
|
}
|
|
|
|
if t == "BLOB" {
|
|
|
|
return SQLITE_BLOB
|
|
|
|
}
|
|
|
|
if t == "REAL" || t == "FLOAT" ||
|
|
|
|
strings.Contains(t, "DOUBLE") {
|
|
|
|
return SQLITE_REAL
|
|
|
|
}
|
|
|
|
if t == "DATE" || t == "DATETIME" ||
|
|
|
|
t == "TIMESTAMP" {
|
|
|
|
return SQLITE_TIME
|
|
|
|
}
|
|
|
|
if t == "NUMERIC" ||
|
|
|
|
strings.Contains(t, "DECIMAL") {
|
|
|
|
return SQLITE_NUMERIC
|
|
|
|
}
|
|
|
|
if t == "BOOLEAN" {
|
|
|
|
return SQLITE_BOOL
|
|
|
|
}
|
|
|
|
|
|
|
|
return SQLITE_NULL
|
2016-11-03 15:03:16 +00:00
|
|
|
}
|