Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
B
beego
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
beego
Commits
1977d87d
Commit
1977d87d
authored
Aug 14, 2013
by
benlovell
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
https://github.com/astaxie/beego
into spelling
parents
9cbefacf
42f1d1ae
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
607 additions
and
86 deletions
+607
-86
beego.go
beego.go
+1
-1
README.md
orm/README.md
+19
-4
db.go
orm/db.go
+0
-0
db_alias.go
orm/db_alias.go
+42
-4
db_postgres.go
orm/db_postgres.go
+1
-1
db_sqlite.go
orm/db_sqlite.go
+10
-0
db_tables.go
orm/db_tables.go
+5
-4
db_utils.go
orm/db_utils.go
+4
-4
Models.md
orm/docs/zh/Models.md
+85
-21
Orm.md
orm/docs/zh/Orm.md
+52
-2
Query.md
orm/docs/zh/Query.md
+1
-1
README.md
orm/docs/zh/README.md
+11
-2
models_fields.go
orm/models_fields.go
+6
-2
models_info_f.go
orm/models_info_f.go
+6
-2
models_test.go
orm/models_test.go
+197
-0
models_utils.go
orm/models_utils.go
+5
-1
orm.go
orm/orm.go
+4
-4
orm_object.go
orm/orm_object.go
+1
-1
orm_queryset.go
orm/orm_queryset.go
+8
-8
orm_raw.go
orm/orm_raw.go
+2
-2
orm_test.go
orm/orm_test.go
+118
-10
types.go
orm/types.go
+15
-12
utils.go
orm/utils.go
+14
-0
No files found.
beego.go
View file @
1977d87d
...
...
@@ -13,7 +13,7 @@ import (
"time"
)
const
VERSION
=
"0.
8
.0"
const
VERSION
=
"0.
9
.0"
var
(
BeeApp
*
App
...
...
orm/README.md
View file @
1977d87d
# beego orm
a powerful orm framework
[
![Build Status
](
https://drone.io/github.com/astaxie/beego/status.png
)
](https://drone.io/github.com/astaxie/beego/latest)
A powerful orm framework for go.
It is heavily influenced by Django ORM, SQLAlchemy.
now, beta, unstable, may be changing some api make your app build failed.
...
...
@@ -14,12 +18,25 @@ Passed all test, but need more feedback.
**Features:**
...
*
full go type support
*
easy for usage, simple CRUD operation
*
auto join with relation table
*
cross DataBase compatible query
*
Raw SQL query / mapper without orm model
*
full test keep stable and strong
more features please read the docs
**Install:**
go get github.com/astaxie/beego/orm
## Changelog
*
2013-08-13: update test for database types
*
2013-08-13: go type support, such as int8, uint8, byte, rune
*
2013-08-13: date / datetime timezone support very well
## Quick Start
#### Simple Usage
...
...
@@ -143,5 +160,3 @@ more details and examples in docs and test
-
some unrealized api
-
examples
-
docs
##
orm/db.go
View file @
1977d87d
This diff is collapsed.
Click to expand it.
orm/db_alias.go
View file @
1977d87d
...
...
@@ -5,6 +5,7 @@ import (
"fmt"
"os"
"sync"
"time"
)
const
defaultMaxIdle
=
30
...
...
@@ -82,6 +83,7 @@ type alias struct {
MaxIdle
int
DB
*
sql
.
DB
DbBaser
dbBaser
TZ
*
time
.
Location
}
func
RegisterDataBase
(
name
,
driverName
,
dataSource
string
,
maxIdle
int
)
{
...
...
@@ -120,6 +122,33 @@ func RegisterDataBase(name, driverName, dataSource string, maxIdle int) {
al
.
DB
.
SetMaxIdleConns
(
al
.
MaxIdle
)
// orm timezone system match database
// default use Local
al
.
TZ
=
time
.
Local
switch
al
.
Driver
{
case
DR_MySQL
:
row
:=
al
.
DB
.
QueryRow
(
"SELECT @@session.time_zone"
)
var
tz
string
row
.
Scan
(
&
tz
)
if
tz
!=
"SYSTEM"
{
t
,
err
:=
time
.
Parse
(
"-07:00"
,
tz
)
if
err
==
nil
{
al
.
TZ
=
t
.
Location
()
}
}
case
DR_Sqlite
:
al
.
TZ
=
time
.
UTC
case
DR_Postgres
:
row
:=
al
.
DB
.
QueryRow
(
"SELECT current_setting('TIMEZONE')"
)
var
tz
string
row
.
Scan
(
&
tz
)
loc
,
err
:=
time
.
LoadLocation
(
tz
)
if
err
==
nil
{
al
.
TZ
=
loc
}
}
err
=
al
.
DB
.
Ping
()
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"register db `%s`, %s"
,
name
,
err
.
Error
())
...
...
@@ -133,13 +162,22 @@ end:
}
}
func
RegisterDriver
(
n
ame
string
,
typ
DriverType
)
{
if
t
,
ok
:=
drivers
[
n
ame
];
ok
==
false
{
drivers
[
n
ame
]
=
typ
func
RegisterDriver
(
driverN
ame
string
,
typ
DriverType
)
{
if
t
,
ok
:=
drivers
[
driverN
ame
];
ok
==
false
{
drivers
[
driverN
ame
]
=
typ
}
else
{
if
t
!=
typ
{
fmt
.
Println
(
"name `%s` db driver already registered and is other type"
)
fmt
.
Sprintf
(
"driverName `%s` db driver already registered and is other type
\n
"
,
driverName
)
os
.
Exit
(
2
)
}
}
}
func
SetDataBaseTZ
(
name
string
,
tz
*
time
.
Location
)
{
if
al
,
ok
:=
dataBaseCache
.
get
(
name
);
ok
{
al
.
TZ
=
tz
}
else
{
fmt
.
Sprintf
(
"DataBase name `%s` not registered
\n
"
,
name
)
os
.
Exit
(
2
)
}
}
orm/db_postgres.go
View file @
1977d87d
...
...
@@ -30,7 +30,7 @@ func (d *dbBasePostgres) OperatorSql(operator string) string {
return
postgresOperators
[
operator
]
}
func
(
d
*
dbBasePostgres
)
GenerateOperatorLeftCol
(
operator
string
,
leftCol
*
string
)
{
func
(
d
*
dbBasePostgres
)
GenerateOperatorLeftCol
(
fi
*
fieldInfo
,
operator
string
,
leftCol
*
string
)
{
switch
operator
{
case
"contains"
,
"startswith"
,
"endswith"
:
*
leftCol
=
fmt
.
Sprintf
(
"%s::text"
,
*
leftCol
)
...
...
orm/db_sqlite.go
View file @
1977d87d
package
orm
import
(
"fmt"
)
var
sqliteOperators
=
map
[
string
]
string
{
"exact"
:
"= ?"
,
"iexact"
:
"LIKE ? ESCAPE '
\\
'"
,
...
...
@@ -25,6 +29,12 @@ func (d *dbBaseSqlite) OperatorSql(operator string) string {
return
sqliteOperators
[
operator
]
}
func
(
d
*
dbBaseSqlite
)
GenerateOperatorLeftCol
(
fi
*
fieldInfo
,
operator
string
,
leftCol
*
string
)
{
if
fi
.
fieldType
==
TypeDateField
{
*
leftCol
=
fmt
.
Sprintf
(
"DATE(%s)"
,
*
leftCol
)
}
}
func
(
d
*
dbBaseSqlite
)
SupportUpdateJoin
()
bool
{
return
false
}
...
...
orm/db_tables.go
View file @
1977d87d
...
...
@@ -3,6 +3,7 @@ package orm
import
(
"fmt"
"strings"
"time"
)
type
dbTable
struct
{
...
...
@@ -266,7 +267,7 @@ func (d *dbTables) parseExprs(mi *modelInfo, exprs []string) (index, name string
return
}
func
(
d
*
dbTables
)
getCondSql
(
cond
*
Condition
,
sub
bool
)
(
where
string
,
params
[]
interface
{})
{
func
(
d
*
dbTables
)
getCondSql
(
cond
*
Condition
,
sub
bool
,
tz
*
time
.
Location
)
(
where
string
,
params
[]
interface
{})
{
if
cond
==
nil
||
cond
.
IsEmpty
()
{
return
}
...
...
@@ -288,7 +289,7 @@ func (d *dbTables) getCondSql(cond *Condition, sub bool) (where string, params [
where
+=
"NOT "
}
if
p
.
isCond
{
w
,
ps
:=
d
.
getCondSql
(
p
.
cond
,
true
)
w
,
ps
:=
d
.
getCondSql
(
p
.
cond
,
true
,
tz
)
if
w
!=
""
{
w
=
fmt
.
Sprintf
(
"( %s) "
,
w
)
}
...
...
@@ -313,10 +314,10 @@ func (d *dbTables) getCondSql(cond *Condition, sub bool) (where string, params [
operator
=
"exact"
}
operSql
,
args
:=
d
.
base
.
GenerateOperatorSql
(
mi
,
fi
,
operator
,
p
.
args
)
operSql
,
args
:=
d
.
base
.
GenerateOperatorSql
(
mi
,
fi
,
operator
,
p
.
args
,
tz
)
leftCol
:=
fmt
.
Sprintf
(
"%s.%s%s%s"
,
index
,
Q
,
fi
.
column
,
Q
)
d
.
base
.
GenerateOperatorLeftCol
(
operator
,
&
leftCol
)
d
.
base
.
GenerateOperatorLeftCol
(
fi
,
operator
,
&
leftCol
)
where
+=
fmt
.
Sprintf
(
"%s %s "
,
leftCol
,
operSql
)
params
=
append
(
params
,
args
...
)
...
...
orm/db_utils.go
View file @
1977d87d
...
...
@@ -24,7 +24,7 @@ func getExistPk(mi *modelInfo, ind reflect.Value) (column string, value interfac
return
}
func
getFlatParams
(
fi
*
fieldInfo
,
args
[]
interface
{})
(
params
[]
interface
{})
{
func
getFlatParams
(
fi
*
fieldInfo
,
args
[]
interface
{}
,
tz
*
time
.
Location
)
(
params
[]
interface
{})
{
outFor
:
for
_
,
arg
:=
range
args
{
...
...
@@ -39,9 +39,9 @@ outFor:
case
[]
byte
:
case
time
.
Time
:
if
fi
!=
nil
&&
fi
.
fieldType
==
TypeDateField
{
arg
=
v
.
Format
(
format_Date
)
arg
=
v
.
In
(
DefaultTimeLoc
)
.
Format
(
format_Date
)
}
else
{
arg
=
v
.
Format
(
format_DateTime
)
arg
=
v
.
In
(
tz
)
.
Format
(
format_DateTime
)
}
default
:
kind
:=
val
.
Kind
()
...
...
@@ -65,7 +65,7 @@ outFor:
}
if
len
(
args
)
>
0
{
p
:=
getFlatParams
(
fi
,
args
)
p
:=
getFlatParams
(
fi
,
args
,
tz
)
params
=
append
(
params
,
p
...
)
}
continue
outFor
...
...
orm/docs/zh/Models.md
View file @
1977d87d
...
...
@@ -164,27 +164,91 @@ type Profile struct {
```
## Struct Field 类型与数据库的对应
现在 orm 支持下面的字段形式
| go type | field type | mysql type
| :--- | :--- | :---
| bool | TypeBooleanField | tinyint
| string | TypeCharField | varchar
| string | TypeTextField | longtext
| time.Time | TypeDateField | date
| time.TIme | TypeDateTimeField | datetime
| int16 |TypeSmallIntegerField | int(4)
| int, int32 |TypeIntegerField | int(11)
| int64 |TypeBigIntegerField | bigint(20)
| uint, uint16 |TypePositiveSmallIntegerField | int(4) unsigned
| uint32 |TypePositiveIntegerField | int(11) unsigned
| uint64 |TypePositiveBigIntegerField | bigint(20) unsigned
| float32, float64 | TypeFloatField | double
| float32, float64 | TypeDecimalField | double(digits, decimals)
关系型的字段,其字段类型取决于对应的主键。
## 模型字段与数据库类型的对应
在此列出 orm 推荐的对应数据库类型,自动建表功能也会以此为标准。
默认所有的字段都是
**NOT NULL**
#### MySQL
| go |mysql
| :--- | :---
| bool | bool
| string - 设置 size 时 | varchar(size)
| string | longtext
| time.Time - 设置 type 为 date 时 | date
| time.TIme | datetime
| byte | tinyint unsigned
| rune | integer
| int | integer
| int8 | tinyint
| int16 | smallint
| int32 | integer
| int64 | bigint
| uint | integer unsigned
| uint8 | tinyint unsigned
| uint16 | smallint unsigned
| uint32 | integer unsigned
| uint64 | bigint unsigned
| float32 | double precision
| float64 | double precision
| float64 - 设置 digits, decimals 时 | numeric(digits, decimals)
#### Sqlite3
| go | sqlite3
| :--- | :---
| bool | bool
| string - 设置 size 时 | varchar(size)
| string | text
| time.Time - 设置 type 为 date 时 | date
| time.TIme | datetime
| byte | tinyint unsigned
| rune | integer
| int | integer
| int8 | tinyint
| int16 | smallint
| int32 | integer
| int64 | bigint
| uint | integer unsigned
| uint8 | tinyint unsigned
| uint16 | smallint unsigned
| uint32 | integer unsigned
| uint64 | bigint unsigned
| float32 | real
| float64 | real
| float64 - 设置 digits, decimals 时 | decimal
#### PostgreSQL
| go | postgres
| :--- | :---
| bool | bool
| string - 设置 size 时 | varchar(size)
| string | text
| time.Time - 设置 type 为 date 时 | date
| time.TIme | timestamp with time zone
| byte | smallint CHECK("column" >= 0 AND "column" <= 255)
| rune | integer
| int | integer
| int8 | smallint CHECK("column" >= -127 AND "column" <= 128)
| int16 | smallint
| int32 | integer
| int64 | bigint
| uint | bigint CHECK("column" >= 0)
| uint8 | smallint CHECK("column" >= 0 AND "column" <= 255)
| uint16 | integer CHECK("column" >= 0)
| uint32 | bigint CHECK("column" >= 0)
| uint64 | bigint CHECK("column" >= 0)
| float32 | double precision
| float64 | double precision
| float64 - 设置 digits, decimals 时 | numeric(digits, decimals)
## 关系型字段
其字段类型取决于对应的主键。
*
RelForeignKey
*
RelOneToOne
...
...
orm/docs/zh/Orm.md
View file @
1977d87d
...
...
@@ -80,7 +80,7 @@ import (
#### RegisterDriver
三种数据库类型
三种
默认
数据库类型
```
go
orm
.
DR_MySQL
...
...
@@ -93,7 +93,7 @@ orm.DR_Postgres
// 参数2 数据库类型
// 这个用来设置 driverName 对应的数据库类型
// mysql / sqlite3 / postgres 这三种是默认已经注册过的,所以可以无需设置
orm
.
RegisterDriver
(
"mysql"
,
orm
.
DR_MySQL
)
orm
.
RegisterDriver
(
"my
my
sql"
,
orm
.
DR_MySQL
)
```
#### RegisterDataBase
...
...
@@ -108,6 +108,56 @@ orm 必须注册一个名称为 `default` 的数据库,用以作为默认使
orm
.
RegisterDataBase
(
"default"
,
"mysql"
,
"root:root@/orm_test?charset=utf8"
,
30
)
```
#### 时区设置
orm 默认使用 time.Local 本地时区
*
作用于 orm 自动创建的时间
*
从数据库中取回的时间转换成 orm 本地时间
如果需要的话,你也可以进行更改
```
go
// 设置为 UTC 时间
orm
.
DefaultTimeLoc
=
time
.
UTC
```
orm 在进行 RegisterDataBase 的同时,会获取数据库使用的时区,然后在 time.Time 类型存取的时做相应转换,以匹配时间系统,从而保证时间不会出错。
**注意:**
鉴于 Sqlite3 的设计,存取默认都为 UTC 时间
## RegisterModel
如果使用 orm.QuerySeter 进行高级查询的话,这个是必须的。
反之,如果只使用 Raw 查询和 map struct,是无需这一步的。您可以去查看
[
Raw SQL 查询
](
Raw.md
)
将你定义的 Model 进行注册,最佳设计是有单独的 models.go 文件,在他的 init 函数中进行注册。
迷你版 models.go
```
go
package
main
import
"github.com/astaxie/beego/orm"
type
User
struct
{
Id
int
`orm:"auto"`
name
string
}
func
init
(){
orm
.
RegisterModel
(
new
(
User
))
}
```
RegisterModel 也可以同时注册多个 model
```
go
orm
.
RegisterModel
(
new
(
User
),
new
(
Profile
),
new
(
Post
))
```
## ORM 接口使用
使用 orm 必然接触的 Ormer 接口,我们来熟悉一下
...
...
orm/docs/zh/Query.md
View file @
1977d87d
...
...
@@ -15,7 +15,7 @@ qs = o.QueryTable(user) // 返回 QuerySeter
```
## expr
QuerySeter 中用于描述字段和 sql 操作符使用简单的 expr 查询方法
QuerySeter 中用于描述字段和 sql 操作符
,
使用简单的 expr 查询方法
字段组合的前后顺序依照表的关系,比如 User 表拥有 Profile 的外键,那么对 User 表查询对应的 Profile.Age 为条件,则使用
`Profile__Age`
注意,字段的分隔符号使用双下划线
`__`
,除了描述字段, expr 的尾部可以增加操作符以执行对应的 sql 操作。比如
`Profile__Age__gt`
代表 Profile.Age > 18 的条件查询。
...
...
orm/docs/zh/README.md
View file @
1977d87d
## 文档目录
1.
[
Orm 使用方法
](
Orm.md
)
-
[
数据库的设置
](
Orm.md#数据库的设置
)
*
[
驱动类型设置
](
Orm.md#registerdriver
)
*
[
参数设置
](
Orm.md#registerdataBase
)
*
[
时区设置
](
Orm.md#时区设置
)
-
[
注册 ORM 使用的模型
](
Orm.md#registermodel
)
-
[
ORM 接口使用
](
Orm.md#orm-接口使用
)
-
[
调试模式打印查询语句
](
Orm.md#调试模式打印查询语句
)
2.
[
对象的CRUD操作
](
Object.md
)
...
...
@@ -15,6 +18,12 @@
6.
[
模型定义
](
Models.md
)
-
[
Struct Tag 设置参数
](
Models.md#struct-tag-设置参数
)
-
[
表关系设置
](
Models.md#表关系设置
)
-
[
Struct Field 类型与数据库的对应
](
Models.md#struct-field-类型与数据库
的对应
)
-
[
模型字段与数据库类型的对应
](
Models.md#模型字段与数据库类型
的对应
)
7.
Custom Fields
8.
Faq
### 文档更新记录
*
2013-08-13: ORM 的
[
时区设置
](
Orm.md#时区设置
)
*
2013-08-13:
[
模型字段与数据库类型的对应
](
Models.md#模型字段与数据库类型的对应
)
推荐的数据库对应使用的类型
orm/models_fields.go
View file @
1977d87d
...
...
@@ -22,12 +22,16 @@ const (
// time.Time
TypeDateTimeField
// int8
TypeBitField
// int16
TypeSmallIntegerField
// int32
TypeIntegerField
// int64
TypeBigIntegerField
// uint8
TypePostiveBitField
// uint16
TypePositiveSmallIntegerField
// uint32
...
...
@@ -49,8 +53,8 @@ const (
const
(
IsIntegerField
=
^-
TypePositiveBigIntegerField
>>
4
<<
5
IsPostiveIntegerField
=
^-
TypePositiveBigIntegerField
>>
7
<<
8
IsRelField
=
^-
RelReverseMany
>>
1
2
<<
13
IsPostiveIntegerField
=
^-
TypePositiveBigIntegerField
>>
8
<<
9
IsRelField
=
^-
RelReverseMany
>>
1
4
<<
15
IsFieldType
=
^-
RelReverseMany
<<
1
+
1
)
...
...
orm/models_info_f.go
View file @
1977d87d
...
...
@@ -327,8 +327,8 @@ checkType:
case
TypeDecimalField
:
d1
:=
digits
d2
:=
decimals
v1
,
er1
:=
StrTo
(
d1
)
.
Int
16
()
v2
,
er2
:=
StrTo
(
d2
)
.
Int
16
()
v1
,
er1
:=
StrTo
(
d1
)
.
Int
8
()
v2
,
er2
:=
StrTo
(
d2
)
.
Int
8
()
if
er1
!=
nil
||
er2
!=
nil
{
err
=
fmt
.
Errorf
(
"wrong digits/decimals value %s/%s"
,
d2
,
d1
)
goto
end
...
...
@@ -383,12 +383,16 @@ checkType:
_
,
err
=
v
.
Bool
()
case
TypeFloatField
,
TypeDecimalField
:
_
,
err
=
v
.
Float64
()
case
TypeBitField
:
_
,
err
=
v
.
Int8
()
case
TypeSmallIntegerField
:
_
,
err
=
v
.
Int16
()
case
TypeIntegerField
:
_
,
err
=
v
.
Int32
()
case
TypeBigIntegerField
:
_
,
err
=
v
.
Int64
()
case
TypePostiveBitField
:
_
,
err
=
v
.
Uint8
()
case
TypePositiveSmallIntegerField
:
_
,
err
=
v
.
Uint16
()
case
TypePositiveIntegerField
:
...
...
orm/models_test.go
View file @
1977d87d
...
...
@@ -6,11 +6,60 @@ import (
"strings"
"time"
// _ "github.com/bylevel/pq"
_
"github.com/go-sql-driver/mysql"
_
"github.com/lib/pq"
_
"github.com/mattn/go-sqlite3"
)
type
Data
struct
{
Id
int
`orm:"auto"`
Boolean
bool
Char
string
`orm:"size(50)"`
Text
string
Date
time
.
Time
`orm:"type(date)"`
DateTime
time
.
Time
Byte
byte
Rune
rune
Int
int
Int8
int8
Int16
int16
Int32
int32
Int64
int64
Uint
uint
Uint8
uint8
Uint16
uint16
Uint32
uint32
Uint64
uint64
Float32
float32
Float64
float64
Decimal
float64
`orm:"digits(8);decimals(4)"`
}
type
DataNull
struct
{
Id
int
`orm:"auto"`
Boolean
bool
`orm:"null"`
Char
string
`orm:"size(50);null"`
Text
string
`orm:"null"`
Date
time
.
Time
`orm:"type(date);null"`
DateTime
time
.
Time
`orm:"null"`
Byte
byte
`orm:"null"`
Rune
rune
`orm:"null"`
Int
int
`orm:"null"`
Int8
int8
`orm:"null"`
Int16
int16
`orm:"null"`
Int32
int32
`orm:"null"`
Int64
int64
`orm:"null"`
Uint
uint
`orm:"null"`
Uint8
uint8
`orm:"null"`
Uint16
uint16
`orm:"null"`
Uint32
uint32
`orm:"null"`
Uint64
uint64
`orm:"null"`
Float32
float32
`orm:"null"`
Float64
float64
`orm:"null"`
Decimal
float64
`orm:"digits(8);decimals(4);null"`
}
type
User
struct
{
Id
int
`orm:"auto"`
UserName
string
`orm:"size(30);unique"`
...
...
@@ -111,6 +160,8 @@ var initSQLs = map[string]string{
"DROP TABLE IF EXISTS `tag`;
\n
"
+
"DROP TABLE IF EXISTS `post_tags`;
\n
"
+
"DROP TABLE IF EXISTS `comment`;
\n
"
+
"DROP TABLE IF EXISTS `data`;
\n
"
+
"DROP TABLE IF EXISTS `data_null`;
\n
"
+
"CREATE TABLE `user_profile` (
\n
"
+
" `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
\n
"
+
" `age` smallint NOT NULL,
\n
"
+
...
...
@@ -153,6 +204,52 @@ var initSQLs = map[string]string{
" `parent_id` integer,
\n
"
+
" `created` datetime NOT NULL
\n
"
+
") ENGINE=INNODB;
\n
"
+
"CREATE TABLE `data` (
\n
"
+
" `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
\n
"
+
" `boolean` bool NOT NULL,
\n
"
+
" `char` varchar(50) NOT NULL,
\n
"
+
" `text` longtext NOT NULL,
\n
"
+
" `date` date NOT NULL,
\n
"
+
" `date_time` datetime NOT NULL,
\n
"
+
" `byte` tinyint unsigned NOT NULL,
\n
"
+
" `rune` integer NOT NULL,
\n
"
+
" `int` integer NOT NULL,
\n
"
+
" `int8` tinyint NOT NULL,
\n
"
+
" `int16` smallint NOT NULL,
\n
"
+
" `int32` integer NOT NULL,
\n
"
+
" `int64` bigint NOT NULL,
\n
"
+
" `uint` integer unsigned NOT NULL,
\n
"
+
" `uint8` tinyint unsigned NULL,
\n
"
+
" `uint16` smallint unsigned NOT NULL,
\n
"
+
" `uint32` integer unsigned NOT NULL,
\n
"
+
" `uint64` bigint unsigned NOT NULL,
\n
"
+
" `float32` double precision NOT NULL,
\n
"
+
" `float64` double precision NOT NULL,
\n
"
+
" `decimal` numeric(8,4) NOT NULL
\n
"
+
") ENGINE=INNODB;
\n
"
+
"CREATE TABLE `data_null` (
\n
"
+
" `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
\n
"
+
" `boolean` bool,
\n
"
+
" `char` varchar(50),
\n
"
+
" `text` longtext,
\n
"
+
" `date` date,
\n
"
+
" `date_time` datetime,
\n
"
+
" `byte` tinyint unsigned,
\n
"
+
" `rune` integer,
\n
"
+
" `int` integer,
\n
"
+
" `int8` tinyint,
\n
"
+
" `int16` smallint,
\n
"
+
" `int32` integer,
\n
"
+
" `int64` bigint,
\n
"
+
" `uint` integer unsigned,
\n
"
+
" `uint8` tinyint unsigned,
\n
"
+
" `uint16` smallint unsigned,
\n
"
+
" `uint32` integer unsigned,
\n
"
+
" `uint64` bigint unsigned,
\n
"
+
" `float32` double precision,
\n
"
+
" `float64` double precision,
\n
"
+
" `decimal` numeric(8,4)
\n
"
+
") ENGINE=INNODB;
\n
"
+
"CREATE INDEX `user_141c6eec` ON `user` (`profile_id`);
\n
"
+
"CREATE INDEX `post_fbfc09f1` ON `post` (`user_id`);
\n
"
+
"CREATE INDEX `comment_699ae8ca` ON `comment` (`post_id`);
\n
"
+
...
...
@@ -165,6 +262,8 @@ DROP TABLE IF EXISTS "post";
DROP TABLE IF EXISTS "tag";
DROP TABLE IF EXISTS "post_tags";
DROP TABLE IF EXISTS "comment";
DROP TABLE IF EXISTS "data";
DROP TABLE IF EXISTS "data_null";
CREATE TABLE "user_profile" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"age" smallint NOT NULL,
...
...
@@ -207,6 +306,52 @@ CREATE TABLE "comment" (
"parent_id" integer,
"created" datetime NOT NULL
);
CREATE TABLE "data" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"boolean" bool NOT NULL,
"char" varchar(50) NOT NULL,
"text" text NOT NULL,
"date" date NOT NULL,
"date_time" datetime NOT NULL,
"byte" tinyint unsigned NOT NULL,
"rune" integer NOT NULL,
"int" integer NOT NULL,
"int8" tinyint NOT NULL,
"int16" smallint NOT NULL,
"int32" integer NOT NULL,
"int64" bigint NOT NULL,
"uint" integer unsigned NOT NULL,
"uint8" tinyint unsigned NOT NULL,
"uint16" smallint unsigned NOT NULL,
"uint32" integer unsigned NOT NULL,
"uint64" bigint unsigned NOT NULL,
"float32" real NOT NULL,
"float64" real NOT NULL,
"decimal" decimal
);
CREATE TABLE "data_null" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"boolean" bool,
"char" varchar(50),
"text" text,
"date" date,
"date_time" datetime,
"byte" tinyint unsigned,
"rune" integer,
"int" integer,
"int8" tinyint,
"int16" smallint,
"int32" integer,
"int64" bigint,
"uint" integer unsigned,
"uint8" tinyint unsigned,
"uint16" smallint unsigned,
"uint32" integer unsigned,
"uint64" bigint unsigned,
"float32" real,
"float64" real,
"decimal" decimal
);
CREATE INDEX "user_141c6eec" ON "user" ("profile_id");
CREATE INDEX "post_fbfc09f1" ON "post" ("user_id");
CREATE INDEX "comment_699ae8ca" ON "comment" ("post_id");
...
...
@@ -220,6 +365,8 @@ DROP TABLE IF EXISTS "post";
DROP TABLE IF EXISTS "tag";
DROP TABLE IF EXISTS "post_tags";
DROP TABLE IF EXISTS "comment";
DROP TABLE IF EXISTS "data";
DROP TABLE IF EXISTS "data_null";
CREATE TABLE "user_profile" (
"id" serial NOT NULL PRIMARY KEY,
"age" smallint NOT NULL,
...
...
@@ -262,6 +409,52 @@ CREATE TABLE "comment" (
"parent_id" integer,
"created" timestamp with time zone NOT NULL
);
CREATE TABLE "data" (
"id" serial NOT NULL PRIMARY KEY,
"boolean" bool NOT NULL,
"char" varchar(50) NOT NULL,
"text" text NOT NULL,
"date" date NOT NULL,
"date_time" timestamp with time zone NOT NULL,
"byte" smallint CHECK("byte" >= 0 AND "byte" <= 255) NOT NULL,
"rune" integer NOT NULL,
"int" integer NOT NULL,
"int8" smallint CHECK("int8" >= -127 AND "int8" <= 128) NOT NULL,
"int16" smallint NOT NULL,
"int32" integer NOT NULL,
"int64" bigint NOT NULL,
"uint" bigint CHECK("uint" >= 0) NOT NULL,
"uint8" smallint CHECK("uint8" >= 0 AND "uint8" <= 255) NOT NULL,
"uint16" integer CHECK("uint16" >= 0) NOT NULL,
"uint32" bigint CHECK("uint32" >= 0) NOT NULL,
"uint64" bigint CHECK("uint64" >= 0) NOT NULL,
"float32" double precision NOT NULL,
"float64" double precision NOT NULL,
"decimal" numeric(8, 4)
);
CREATE TABLE "data_null" (
"id" serial NOT NULL PRIMARY KEY,
"boolean" bool,
"char" varchar(50),
"text" text,
"date" date,
"date_time" timestamp with time zone,
"byte" smallint CHECK("byte" >= 0 AND "byte" <= 255),
"rune" integer,
"int" integer,
"int8" smallint CHECK("int8" >= -127 AND "int8" <= 128),
"int16" smallint,
"int32" integer,
"int64" bigint,
"uint" bigint CHECK("uint" >= 0),
"uint8" smallint CHECK("uint8" >= 0 AND "uint8" <= 255),
"uint16" integer CHECK("uint16" >= 0),
"uint32" bigint CHECK("uint32" >= 0),
"uint64" bigint CHECK("uint64" >= 0),
"float32" double precision,
"float64" double precision,
"decimal" numeric(8, 4)
);
CREATE INDEX "user_profile_id" ON "user" ("profile_id");
CREATE INDEX "post_user_id" ON "post" ("user_id");
CREATE INDEX "comment_post_id" ON "comment" ("post_id");
...
...
@@ -269,6 +462,10 @@ CREATE INDEX "comment_parent_id" ON "comment" ("parent_id");
`
}
func
init
()
{
// err := os.Setenv("TZ", "+00:00")
// fmt.Println(err)
RegisterModel
(
new
(
Data
),
new
(
DataNull
))
RegisterModel
(
new
(
User
))
RegisterModel
(
new
(
Profile
))
RegisterModel
(
new
(
Post
))
...
...
orm/models_utils.go
View file @
1977d87d
...
...
@@ -43,15 +43,19 @@ func getColumnName(ft int, addrField reflect.Value, sf reflect.StructField, col
func
getFieldType
(
val
reflect
.
Value
)
(
ft
int
,
err
error
)
{
elm
:=
reflect
.
Indirect
(
val
)
switch
elm
.
Kind
()
{
case
reflect
.
Int8
:
ft
=
TypeBitField
case
reflect
.
Int16
:
ft
=
TypeSmallIntegerField
case
reflect
.
Int32
,
reflect
.
Int
:
ft
=
TypeIntegerField
case
reflect
.
Int64
:
ft
=
TypeBigIntegerField
case
reflect
.
Uint8
:
ft
=
TypePostiveBitField
case
reflect
.
Uint16
:
ft
=
TypePositiveSmallIntegerField
case
reflect
.
Uint32
:
case
reflect
.
Uint32
,
reflect
.
Uint
:
ft
=
TypePositiveIntegerField
case
reflect
.
Uint64
:
ft
=
TypePositiveBigIntegerField
...
...
orm/orm.go
View file @
1977d87d
...
...
@@ -55,7 +55,7 @@ func (o *orm) getMiInd(md interface{}) (mi *modelInfo, ind reflect.Value) {
func
(
o
*
orm
)
Read
(
md
interface
{})
error
{
mi
,
ind
:=
o
.
getMiInd
(
md
)
err
:=
o
.
alias
.
DbBaser
.
Read
(
o
.
db
,
mi
,
ind
)
err
:=
o
.
alias
.
DbBaser
.
Read
(
o
.
db
,
mi
,
ind
,
o
.
alias
.
TZ
)
if
err
!=
nil
{
return
err
}
...
...
@@ -64,7 +64,7 @@ func (o *orm) Read(md interface{}) error {
func
(
o
*
orm
)
Insert
(
md
interface
{})
(
int64
,
error
)
{
mi
,
ind
:=
o
.
getMiInd
(
md
)
id
,
err
:=
o
.
alias
.
DbBaser
.
Insert
(
o
.
db
,
mi
,
ind
)
id
,
err
:=
o
.
alias
.
DbBaser
.
Insert
(
o
.
db
,
mi
,
ind
,
o
.
alias
.
TZ
)
if
err
!=
nil
{
return
id
,
err
}
...
...
@@ -78,7 +78,7 @@ func (o *orm) Insert(md interface{}) (int64, error) {
func
(
o
*
orm
)
Update
(
md
interface
{})
(
int64
,
error
)
{
mi
,
ind
:=
o
.
getMiInd
(
md
)
num
,
err
:=
o
.
alias
.
DbBaser
.
Update
(
o
.
db
,
mi
,
ind
)
num
,
err
:=
o
.
alias
.
DbBaser
.
Update
(
o
.
db
,
mi
,
ind
,
o
.
alias
.
TZ
)
if
err
!=
nil
{
return
num
,
err
}
...
...
@@ -87,7 +87,7 @@ func (o *orm) Update(md interface{}) (int64, error) {
func
(
o
*
orm
)
Delete
(
md
interface
{})
(
int64
,
error
)
{
mi
,
ind
:=
o
.
getMiInd
(
md
)
num
,
err
:=
o
.
alias
.
DbBaser
.
Delete
(
o
.
db
,
mi
,
ind
)
num
,
err
:=
o
.
alias
.
DbBaser
.
Delete
(
o
.
db
,
mi
,
ind
,
o
.
alias
.
TZ
)
if
err
!=
nil
{
return
num
,
err
}
...
...
orm/orm_object.go
View file @
1977d87d
...
...
@@ -28,7 +28,7 @@ func (o *insertSet) Insert(md interface{}) (int64, error) {
if
name
!=
o
.
mi
.
fullName
{
panic
(
fmt
.
Sprintf
(
"<Inserter.Insert> need model `%s` but found `%s`"
,
o
.
mi
.
fullName
,
name
))
}
id
,
err
:=
o
.
orm
.
alias
.
DbBaser
.
InsertStmt
(
o
.
stmt
,
o
.
mi
,
ind
)
id
,
err
:=
o
.
orm
.
alias
.
DbBaser
.
InsertStmt
(
o
.
stmt
,
o
.
mi
,
ind
,
o
.
orm
.
alias
.
TZ
)
if
err
!=
nil
{
return
id
,
err
}
...
...
orm/orm_queryset.go
View file @
1977d87d
...
...
@@ -77,15 +77,15 @@ func (o querySet) SetCond(cond *Condition) QuerySeter {
}
func
(
o
*
querySet
)
Count
()
(
int64
,
error
)
{
return
o
.
orm
.
alias
.
DbBaser
.
Count
(
o
.
orm
.
db
,
o
,
o
.
mi
,
o
.
cond
)
return
o
.
orm
.
alias
.
DbBaser
.
Count
(
o
.
orm
.
db
,
o
,
o
.
mi
,
o
.
cond
,
o
.
orm
.
alias
.
TZ
)
}
func
(
o
*
querySet
)
Update
(
values
Params
)
(
int64
,
error
)
{
return
o
.
orm
.
alias
.
DbBaser
.
UpdateBatch
(
o
.
orm
.
db
,
o
,
o
.
mi
,
o
.
cond
,
values
)
return
o
.
orm
.
alias
.
DbBaser
.
UpdateBatch
(
o
.
orm
.
db
,
o
,
o
.
mi
,
o
.
cond
,
values
,
o
.
orm
.
alias
.
TZ
)
}
func
(
o
*
querySet
)
Delete
()
(
int64
,
error
)
{
return
o
.
orm
.
alias
.
DbBaser
.
DeleteBatch
(
o
.
orm
.
db
,
o
,
o
.
mi
,
o
.
cond
)
return
o
.
orm
.
alias
.
DbBaser
.
DeleteBatch
(
o
.
orm
.
db
,
o
,
o
.
mi
,
o
.
cond
,
o
.
orm
.
alias
.
TZ
)
}
func
(
o
*
querySet
)
PrepareInsert
()
(
Inserter
,
error
)
{
...
...
@@ -93,11 +93,11 @@ func (o *querySet) PrepareInsert() (Inserter, error) {
}
func
(
o
*
querySet
)
All
(
container
interface
{})
(
int64
,
error
)
{
return
o
.
orm
.
alias
.
DbBaser
.
ReadBatch
(
o
.
orm
.
db
,
o
,
o
.
mi
,
o
.
cond
,
container
)
return
o
.
orm
.
alias
.
DbBaser
.
ReadBatch
(
o
.
orm
.
db
,
o
,
o
.
mi
,
o
.
cond
,
container
,
o
.
orm
.
alias
.
TZ
)
}
func
(
o
*
querySet
)
One
(
container
interface
{})
error
{
num
,
err
:=
o
.
orm
.
alias
.
DbBaser
.
ReadBatch
(
o
.
orm
.
db
,
o
,
o
.
mi
,
o
.
cond
,
container
)
num
,
err
:=
o
.
orm
.
alias
.
DbBaser
.
ReadBatch
(
o
.
orm
.
db
,
o
,
o
.
mi
,
o
.
cond
,
container
,
o
.
orm
.
alias
.
TZ
)
if
err
!=
nil
{
return
err
}
...
...
@@ -111,15 +111,15 @@ func (o *querySet) One(container interface{}) error {
}
func
(
o
*
querySet
)
Values
(
results
*
[]
Params
,
exprs
...
string
)
(
int64
,
error
)
{
return
o
.
orm
.
alias
.
DbBaser
.
ReadValues
(
o
.
orm
.
db
,
o
,
o
.
mi
,
o
.
cond
,
exprs
,
results
)
return
o
.
orm
.
alias
.
DbBaser
.
ReadValues
(
o
.
orm
.
db
,
o
,
o
.
mi
,
o
.
cond
,
exprs
,
results
,
o
.
orm
.
alias
.
TZ
)
}
func
(
o
*
querySet
)
ValuesList
(
results
*
[]
ParamsList
,
exprs
...
string
)
(
int64
,
error
)
{
return
o
.
orm
.
alias
.
DbBaser
.
ReadValues
(
o
.
orm
.
db
,
o
,
o
.
mi
,
o
.
cond
,
exprs
,
results
)
return
o
.
orm
.
alias
.
DbBaser
.
ReadValues
(
o
.
orm
.
db
,
o
,
o
.
mi
,
o
.
cond
,
exprs
,
results
,
o
.
orm
.
alias
.
TZ
)
}
func
(
o
*
querySet
)
ValuesFlat
(
result
*
ParamsList
,
expr
string
)
(
int64
,
error
)
{
return
o
.
orm
.
alias
.
DbBaser
.
ReadValues
(
o
.
orm
.
db
,
o
,
o
.
mi
,
o
.
cond
,
[]
string
{
expr
},
result
)
return
o
.
orm
.
alias
.
DbBaser
.
ReadValues
(
o
.
orm
.
db
,
o
,
o
.
mi
,
o
.
cond
,
[]
string
{
expr
},
result
,
o
.
orm
.
alias
.
TZ
)
}
func
newQuerySet
(
orm
*
orm
,
mi
*
modelInfo
)
QuerySeter
{
...
...
orm/orm_raw.go
View file @
1977d87d
...
...
@@ -60,7 +60,7 @@ func (o *rawSet) Exec() (sql.Result, error) {
query
:=
o
.
query
o
.
orm
.
alias
.
DbBaser
.
ReplaceMarks
(
&
query
)
args
:=
getFlatParams
(
nil
,
o
.
args
)
args
:=
getFlatParams
(
nil
,
o
.
args
,
o
.
orm
.
alias
.
TZ
)
return
o
.
orm
.
db
.
Exec
(
query
,
args
...
)
}
...
...
@@ -96,7 +96,7 @@ func (o *rawSet) readValues(container interface{}) (int64, error) {
query
:=
o
.
query
o
.
orm
.
alias
.
DbBaser
.
ReplaceMarks
(
&
query
)
args
:=
getFlatParams
(
nil
,
o
.
args
)
args
:=
getFlatParams
(
nil
,
o
.
args
,
o
.
orm
.
alias
.
TZ
)
var
rs
*
sql
.
Rows
if
r
,
err
:=
o
.
orm
.
db
.
Query
(
query
,
args
...
);
err
!=
nil
{
...
...
orm/orm_test.go
View file @
1977d87d
...
...
@@ -15,6 +15,11 @@ import (
var
_
=
os
.
PathSeparator
var
(
test_Date
=
format_Date
+
" -0700"
test_DateTime
=
format_DateTime
+
" -0700"
)
type
T_Code
int
const
(
...
...
@@ -141,7 +146,7 @@ func getCaller(skip int) string {
if
cur
==
line
{
flag
=
">>"
}
code
:=
fmt
.
Sprintf
(
" %s %5d: %s"
,
flag
,
cur
,
strings
.
TrimSpace
(
string
(
lines
[
o
+
i
])
))
code
:=
fmt
.
Sprintf
(
" %s %5d: %s"
,
flag
,
cur
,
strings
.
Replace
(
string
(
lines
[
o
+
i
]),
"
\t
"
,
" "
,
-
1
))
if
code
!=
""
{
codes
=
append
(
codes
,
code
)
}
...
...
@@ -158,7 +163,11 @@ func throwFail(t *testing.T, err error, args ...interface{}) {
if
err
!=
nil
{
con
:=
fmt
.
Sprintf
(
"
\t\n
Error: %s
\n
%s
\n
"
,
err
.
Error
(),
getCaller
(
2
))
if
len
(
args
)
>
0
{
con
+=
fmt
.
Sprint
(
args
...
)
parts
:=
make
([]
string
,
0
,
len
(
args
))
for
_
,
arg
:=
range
args
{
parts
=
append
(
parts
,
fmt
.
Sprintf
(
"%v"
,
arg
))
}
con
+=
" "
+
strings
.
Join
(
parts
,
", "
)
}
t
.
Error
(
con
)
t
.
Fail
()
...
...
@@ -169,7 +178,11 @@ func throwFailNow(t *testing.T, err error, args ...interface{}) {
if
err
!=
nil
{
con
:=
fmt
.
Sprintf
(
"
\t\n
Error: %s
\n
%s
\n
"
,
err
.
Error
(),
getCaller
(
2
))
if
len
(
args
)
>
0
{
con
+=
fmt
.
Sprint
(
args
...
)
parts
:=
make
([]
string
,
0
,
len
(
args
))
for
_
,
arg
:=
range
args
{
parts
=
append
(
parts
,
fmt
.
Sprintf
(
"%v"
,
arg
))
}
con
+=
" "
+
strings
.
Join
(
parts
,
", "
)
}
t
.
Error
(
con
)
t
.
FailNow
()
...
...
@@ -177,13 +190,100 @@ func throwFailNow(t *testing.T, err error, args ...interface{}) {
}
func
TestModelSyntax
(
t
*
testing
.
T
)
{
mi
,
ok
:=
modelCache
.
get
(
"user"
)
user
:=
&
User
{}
ind
:=
reflect
.
ValueOf
(
user
)
.
Elem
()
fn
:=
getFullName
(
ind
.
Type
())
mi
,
ok
:=
modelCache
.
getByFN
(
fn
)
throwFail
(
t
,
AssertIs
(
ok
,
T_Equal
,
true
))
mi
,
ok
=
modelCache
.
get
(
"user"
)
throwFail
(
t
,
AssertIs
(
ok
,
T_Equal
,
true
))
if
ok
{
throwFail
(
t
,
AssertIs
(
mi
.
fields
.
GetByName
(
"ShouldSkip"
)
==
nil
,
T_Equal
,
true
))
}
}
func
TestDataTypes
(
t
*
testing
.
T
)
{
values
:=
map
[
string
]
interface
{}{
"Boolean"
:
true
,
"Char"
:
"char"
,
"Text"
:
"text"
,
"Date"
:
time
.
Now
(),
"DateTime"
:
time
.
Now
(),
"Byte"
:
byte
(
1
<<
8
-
1
),
"Rune"
:
rune
(
1
<<
31
-
1
),
"Int"
:
int
(
1
<<
31
-
1
),
"Int8"
:
int8
(
1
<<
7
-
1
),
"Int16"
:
int16
(
1
<<
15
-
1
),
"Int32"
:
int32
(
1
<<
31
-
1
),
"Int64"
:
int64
(
1
<<
63
-
1
),
"Uint"
:
uint
(
1
<<
32
-
1
),
"Uint8"
:
uint8
(
1
<<
8
-
1
),
"Uint16"
:
uint16
(
1
<<
16
-
1
),
"Uint32"
:
uint32
(
1
<<
32
-
1
),
"Uint64"
:
uint64
(
1
<<
63
-
1
),
// uint64 values with high bit set are not supported
"Float32"
:
float32
(
100.1234
),
"Float64"
:
float64
(
100.1234
),
"Decimal"
:
float64
(
100.1234
),
}
d
:=
Data
{}
ind
:=
reflect
.
Indirect
(
reflect
.
ValueOf
(
&
d
))
for
name
,
value
:=
range
values
{
e
:=
ind
.
FieldByName
(
name
)
e
.
Set
(
reflect
.
ValueOf
(
value
))
}
id
,
err
:=
dORM
.
Insert
(
&
d
)
throwFail
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
id
,
T_Equal
,
1
))
d
=
Data
{
Id
:
1
}
err
=
dORM
.
Read
(
&
d
)
throwFail
(
t
,
err
)
ind
=
reflect
.
Indirect
(
reflect
.
ValueOf
(
&
d
))
for
name
,
value
:=
range
values
{
e
:=
ind
.
FieldByName
(
name
)
vu
:=
e
.
Interface
()
switch
name
{
case
"Date"
:
vu
=
vu
.
(
time
.
Time
)
.
In
(
DefaultTimeLoc
)
.
Format
(
test_Date
)
value
=
value
.
(
time
.
Time
)
.
In
(
DefaultTimeLoc
)
.
Format
(
test_Date
)
case
"DateTime"
:
vu
=
vu
.
(
time
.
Time
)
.
In
(
DefaultTimeLoc
)
.
Format
(
test_DateTime
)
value
=
value
.
(
time
.
Time
)
.
In
(
DefaultTimeLoc
)
.
Format
(
test_DateTime
)
}
throwFail
(
t
,
AssertIs
(
vu
==
value
,
T_Equal
,
true
),
value
,
vu
)
}
}
func
TestNullDataTypes
(
t
*
testing
.
T
)
{
d
:=
DataNull
{}
if
IsPostgres
{
// can removed when this fixed
// https://github.com/lib/pq/pull/125
d
.
DateTime
=
time
.
Now
()
}
id
,
err
:=
dORM
.
Insert
(
&
d
)
throwFail
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
id
,
T_Equal
,
1
))
d
=
DataNull
{
Id
:
1
}
err
=
dORM
.
Read
(
&
d
)
throwFail
(
t
,
err
)
_
,
err
=
dORM
.
Raw
(
`INSERT INTO data_null (boolean) VALUES (?)`
,
nil
)
.
Exec
()
throwFail
(
t
,
err
)
d
=
DataNull
{
Id
:
2
}
err
=
dORM
.
Read
(
&
d
)
throwFail
(
t
,
err
)
}
func
TestCRUD
(
t
*
testing
.
T
)
{
profile
:=
NewProfile
()
profile
.
Age
=
30
...
...
@@ -214,8 +314,8 @@ func TestCRUD(t *testing.T) {
throwFail
(
t
,
AssertIs
(
u
.
Status
,
T_Equal
,
3
))
throwFail
(
t
,
AssertIs
(
u
.
IsStaff
,
T_Equal
,
true
))
throwFail
(
t
,
AssertIs
(
u
.
IsActive
,
T_Equal
,
true
))
throwFail
(
t
,
AssertIs
(
u
.
Created
,
T_Equal
,
user
.
Created
,
forma
t_Date
))
throwFail
(
t
,
AssertIs
(
u
.
Updated
,
T_Equal
,
user
.
Updated
,
forma
t_DateTime
))
throwFail
(
t
,
AssertIs
(
u
.
Created
.
In
(
DefaultTimeLoc
),
T_Equal
,
user
.
Created
.
In
(
DefaultTimeLoc
),
tes
t_Date
))
throwFail
(
t
,
AssertIs
(
u
.
Updated
.
In
(
DefaultTimeLoc
),
T_Equal
,
user
.
Updated
.
In
(
DefaultTimeLoc
),
tes
t_DateTime
))
user
.
UserName
=
"astaxie"
user
.
Profile
=
profile
...
...
@@ -360,7 +460,9 @@ The program—and web server—godoc processes Go source files to extract docume
}
func
TestExpr
(
t
*
testing
.
T
)
{
qs
:=
dORM
.
QueryTable
(
"User"
)
user
:=
&
User
{}
qs
:=
dORM
.
QueryTable
(
user
)
qs
=
dORM
.
QueryTable
(
"User"
)
qs
=
dORM
.
QueryTable
(
"user"
)
num
,
err
:=
qs
.
Filter
(
"UserName"
,
"slene"
)
.
Filter
(
"user_name"
,
"slene"
)
.
Filter
(
"profile__Age"
,
28
)
.
Count
()
throwFail
(
t
,
err
)
...
...
@@ -369,6 +471,10 @@ func TestExpr(t *testing.T) {
num
,
err
=
qs
.
Filter
(
"created"
,
time
.
Now
())
.
Count
()
throwFail
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
num
,
T_Equal
,
3
))
num
,
err
=
qs
.
Filter
(
"created"
,
time
.
Now
()
.
Format
(
format_Date
))
.
Count
()
throwFail
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
num
,
T_Equal
,
3
))
}
func
TestOperators
(
t
*
testing
.
T
)
{
...
...
@@ -820,9 +926,11 @@ func TestRaw(t *testing.T) {
res
,
err
:=
dORM
.
Raw
(
`DELETE FROM "tag" WHERE "name" IN (?, ?, ?)`
,
[]
string
{
"name1"
,
"name2"
,
"name3"
})
.
Exec
()
throwFail
(
t
,
err
)
num
,
err
:=
res
.
RowsAffected
()
throwFail
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
num
,
T_Equal
,
3
))
if
err
==
nil
{
num
,
err
:=
res
.
RowsAffected
()
throwFail
(
t
,
err
)
throwFail
(
t
,
AssertIs
(
num
,
T_Equal
,
3
))
}
}
}
}
...
...
orm/types.go
View file @
1977d87d
...
...
@@ -3,6 +3,7 @@ package orm
import
(
"database/sql"
"reflect"
"time"
)
type
Driver
interface
{
...
...
@@ -110,23 +111,25 @@ type txEnder interface {
}
type
dbBaser
interface
{
Read
(
dbQuerier
,
*
modelInfo
,
reflect
.
Value
)
error
Insert
(
dbQuerier
,
*
modelInfo
,
reflect
.
Value
)
(
int64
,
error
)
InsertStmt
(
stmtQuerier
,
*
modelInfo
,
reflect
.
Value
)
(
int64
,
error
)
Update
(
dbQuerier
,
*
modelInfo
,
reflect
.
Value
)
(
int64
,
error
)
Delete
(
dbQuerier
,
*
modelInfo
,
reflect
.
Value
)
(
int64
,
error
)
ReadBatch
(
dbQuerier
,
*
querySet
,
*
modelInfo
,
*
Condition
,
interface
{})
(
int64
,
error
)
Read
(
dbQuerier
,
*
modelInfo
,
reflect
.
Value
,
*
time
.
Location
)
error
Insert
(
dbQuerier
,
*
modelInfo
,
reflect
.
Value
,
*
time
.
Location
)
(
int64
,
error
)
InsertStmt
(
stmtQuerier
,
*
modelInfo
,
reflect
.
Value
,
*
time
.
Location
)
(
int64
,
error
)
Update
(
dbQuerier
,
*
modelInfo
,
reflect
.
Value
,
*
time
.
Location
)
(
int64
,
error
)
Delete
(
dbQuerier
,
*
modelInfo
,
reflect
.
Value
,
*
time
.
Location
)
(
int64
,
error
)
ReadBatch
(
dbQuerier
,
*
querySet
,
*
modelInfo
,
*
Condition
,
interface
{}
,
*
time
.
Location
)
(
int64
,
error
)
SupportUpdateJoin
()
bool
UpdateBatch
(
dbQuerier
,
*
querySet
,
*
modelInfo
,
*
Condition
,
Params
)
(
int64
,
error
)
DeleteBatch
(
dbQuerier
,
*
querySet
,
*
modelInfo
,
*
Condition
)
(
int64
,
error
)
Count
(
dbQuerier
,
*
querySet
,
*
modelInfo
,
*
Condition
)
(
int64
,
error
)
UpdateBatch
(
dbQuerier
,
*
querySet
,
*
modelInfo
,
*
Condition
,
Params
,
*
time
.
Location
)
(
int64
,
error
)
DeleteBatch
(
dbQuerier
,
*
querySet
,
*
modelInfo
,
*
Condition
,
*
time
.
Location
)
(
int64
,
error
)
Count
(
dbQuerier
,
*
querySet
,
*
modelInfo
,
*
Condition
,
*
time
.
Location
)
(
int64
,
error
)
OperatorSql
(
string
)
string
GenerateOperatorSql
(
*
modelInfo
,
*
fieldInfo
,
string
,
[]
interface
{})
(
string
,
[]
interface
{})
GenerateOperatorLeftCol
(
string
,
*
string
)
GenerateOperatorSql
(
*
modelInfo
,
*
fieldInfo
,
string
,
[]
interface
{}
,
*
time
.
Location
)
(
string
,
[]
interface
{})
GenerateOperatorLeftCol
(
*
fieldInfo
,
string
,
*
string
)
PrepareInsert
(
dbQuerier
,
*
modelInfo
)
(
stmtQuerier
,
string
,
error
)
ReadValues
(
dbQuerier
,
*
querySet
,
*
modelInfo
,
*
Condition
,
[]
string
,
interface
{})
(
int64
,
error
)
ReadValues
(
dbQuerier
,
*
querySet
,
*
modelInfo
,
*
Condition
,
[]
string
,
interface
{}
,
*
time
.
Location
)
(
int64
,
error
)
MaxLimit
()
uint64
TableQuote
()
string
ReplaceMarks
(
*
string
)
HasReturningID
(
*
modelInfo
,
*
string
)
bool
TimeFromDB
(
*
time
.
Time
,
*
time
.
Location
)
TimeToDB
(
*
time
.
Time
,
*
time
.
Location
)
}
orm/utils.go
View file @
1977d87d
...
...
@@ -38,6 +38,11 @@ func (f StrTo) Float64() (float64, error) {
return
strconv
.
ParseFloat
(
f
.
String
(),
64
)
}
func
(
f
StrTo
)
Int8
()
(
int8
,
error
)
{
v
,
err
:=
strconv
.
ParseInt
(
f
.
String
(),
10
,
8
)
return
int8
(
v
),
err
}
func
(
f
StrTo
)
Int16
()
(
int16
,
error
)
{
v
,
err
:=
strconv
.
ParseInt
(
f
.
String
(),
10
,
16
)
return
int16
(
v
),
err
...
...
@@ -53,6 +58,11 @@ func (f StrTo) Int64() (int64, error) {
return
int64
(
v
),
err
}
func
(
f
StrTo
)
Uint8
()
(
uint8
,
error
)
{
v
,
err
:=
strconv
.
ParseUint
(
f
.
String
(),
10
,
8
)
return
uint8
(
v
),
err
}
func
(
f
StrTo
)
Uint16
()
(
uint16
,
error
)
{
v
,
err
:=
strconv
.
ParseUint
(
f
.
String
(),
10
,
16
)
return
uint16
(
v
),
err
...
...
@@ -85,6 +95,8 @@ func ToStr(value interface{}, args ...int) (s string) {
s
=
strconv
.
FormatFloat
(
v
,
'f'
,
argInt
(
args
)
.
Get
(
0
,
-
1
),
argInt
(
args
)
.
Get
(
1
,
64
))
case
int
:
s
=
strconv
.
FormatInt
(
int64
(
v
),
argInt
(
args
)
.
Get
(
0
,
10
))
case
int8
:
s
=
strconv
.
FormatInt
(
int64
(
v
),
argInt
(
args
)
.
Get
(
0
,
10
))
case
int16
:
s
=
strconv
.
FormatInt
(
int64
(
v
),
argInt
(
args
)
.
Get
(
0
,
10
))
case
int32
:
...
...
@@ -93,6 +105,8 @@ func ToStr(value interface{}, args ...int) (s string) {
s
=
strconv
.
FormatInt
(
v
,
argInt
(
args
)
.
Get
(
0
,
10
))
case
uint
:
s
=
strconv
.
FormatUint
(
uint64
(
v
),
argInt
(
args
)
.
Get
(
0
,
10
))
case
uint8
:
s
=
strconv
.
FormatUint
(
uint64
(
v
),
argInt
(
args
)
.
Get
(
0
,
10
))
case
uint16
:
s
=
strconv
.
FormatUint
(
uint64
(
v
),
argInt
(
args
)
.
Get
(
0
,
10
))
case
uint32
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment