6c41e6dd by slene

orm add sqlite3 support, may be support postgres in next commit

1 parent 9631c663
1 package orm 1 package orm
2 2
3 var mysqlOperators = map[string]string{
4 "exact": "= ?",
5 "iexact": "LIKE ?",
6 "contains": "LIKE BINARY ?",
7 "icontains": "LIKE ?",
8 // "regex": "REGEXP BINARY ?",
9 // "iregex": "REGEXP ?",
10 "gt": "> ?",
11 "gte": ">= ?",
12 "lt": "< ?",
13 "lte": "<= ?",
14 "startswith": "LIKE BINARY ?",
15 "endswith": "LIKE BINARY ?",
16 "istartswith": "LIKE ?",
17 "iendswith": "LIKE ?",
18 }
19
3 type dbBaseMysql struct { 20 type dbBaseMysql struct {
4 dbBase 21 dbBase
5 } 22 }
6 23
7 func (d *dbBaseMysql) GetOperatorSql(mi *modelInfo, operator string, args []interface{}) (sql string, params []interface{}) { 24 var _ dbBaser = new(dbBaseMysql)
8 return d.dbBase.GetOperatorSql(mi, operator, args) 25
26 func (d *dbBaseMysql) OperatorSql(operator string) string {
27 return mysqlOperators[operator]
9 } 28 }
10 29
11 func newdbBaseMysql() dbBaser { 30 func newdbBaseMysql() dbBaser {
......
...@@ -4,6 +4,12 @@ type dbBaseOracle struct { ...@@ -4,6 +4,12 @@ type dbBaseOracle struct {
4 dbBase 4 dbBase
5 } 5 }
6 6
7 var _ dbBaser = new(dbBaseOracle)
8
9 func (d *dbBase) OperatorSql(operator string) string {
10 return ""
11 }
12
7 func newdbBaseOracle() dbBaser { 13 func newdbBaseOracle() dbBaser {
8 b := new(dbBaseOracle) 14 b := new(dbBaseOracle)
9 b.ins = b 15 b.ins = b
......
1 package orm 1 package orm
2 2
3 import (
4 "strconv"
5 )
6
7 var postgresOperators = map[string]string{
8 "exact": "= ?",
9 "iexact": "= UPPER(?)",
10 "contains": "LIKE ?",
11 "icontains": "LIKE UPPER(?)",
12 "gt": "> ?",
13 "gte": ">= ?",
14 "lt": "< ?",
15 "lte": "<= ?",
16 "startswith": "LIKE ?",
17 "endswith": "LIKE ?",
18 "istartswith": "LIKE UPPER(?)",
19 "iendswith": "LIKE UPPER(?)",
20 }
21
3 type dbBasePostgres struct { 22 type dbBasePostgres struct {
4 dbBase 23 dbBase
5 } 24 }
6 25
26 var _ dbBaser = new(dbBasePostgres)
27
28 func (d *dbBasePostgres) OperatorSql(operator string) string {
29 return postgresOperators[operator]
30 }
31
32 func (d *dbBasePostgres) TableQuote() string {
33 return `"`
34 }
35
36 func (d *dbBasePostgres) ReplaceMarks(query *string) {
37 q := *query
38 num := 0
39 for _, c := range q {
40 if c == '?' {
41 num += 1
42 }
43 }
44 if num == 0 {
45 return
46 }
47 data := make([]byte, 0, len(q)+num)
48 num = 1
49 for i := 0; i < len(q); i++ {
50 c := q[i]
51 if c == '?' {
52 data = append(data, '$')
53 data = append(data, []byte(strconv.Itoa(num))...)
54 num += 1
55 } else {
56 data = append(data, c)
57 }
58 }
59 *query = string(data)
60 }
61
62 // func (d *dbBasePostgres)
63
7 func newdbBasePostgres() dbBaser { 64 func newdbBasePostgres() dbBaser {
8 b := new(dbBasePostgres) 65 b := new(dbBasePostgres)
9 b.ins = b 66 b.ins = b
......
1 package orm 1 package orm
2 2
3 var sqliteOperators = map[string]string{
4 "exact": "= ?",
5 "iexact": "LIKE ? ESCAPE '\\'",
6 "contains": "LIKE ? ESCAPE '\\'",
7 "icontains": "LIKE ? ESCAPE '\\'",
8 "gt": "> ?",
9 "gte": ">= ?",
10 "lt": "< ?",
11 "lte": "<= ?",
12 "startswith": "LIKE ? ESCAPE '\\'",
13 "endswith": "LIKE ? ESCAPE '\\'",
14 "istartswith": "LIKE ? ESCAPE '\\'",
15 "iendswith": "LIKE ? ESCAPE '\\'",
16 }
17
3 type dbBaseSqlite struct { 18 type dbBaseSqlite struct {
4 dbBase 19 dbBase
5 } 20 }
6 21
22 var _ dbBaser = new(dbBaseSqlite)
23
24 func (d *dbBaseSqlite) OperatorSql(operator string) string {
25 return sqliteOperators[operator]
26 }
27
28 func (d *dbBaseSqlite) SupportUpdateJoin() bool {
29 return false
30 }
31
32 func (d *dbBaseSqlite) MaxLimit() uint64 {
33 return 9223372036854775807
34 }
35
7 func newdbBaseSqlite() dbBaser { 36 func newdbBaseSqlite() dbBaser {
8 b := new(dbBaseSqlite) 37 b := new(dbBaseSqlite)
9 b.ins = b 38 b.ins = b
......
1 package orm
2
3 import (
4 "fmt"
5 "strings"
6 )
7
8 type dbTable struct {
9 id int
10 index string
11 name string
12 names []string
13 sel bool
14 inner bool
15 mi *modelInfo
16 fi *fieldInfo
17 jtl *dbTable
18 }
19
20 type dbTables struct {
21 tablesM map[string]*dbTable
22 tables []*dbTable
23 mi *modelInfo
24 base dbBaser
25 }
26
27 func (t *dbTables) set(names []string, mi *modelInfo, fi *fieldInfo, inner bool) *dbTable {
28 name := strings.Join(names, ExprSep)
29 if j, ok := t.tablesM[name]; ok {
30 j.name = name
31 j.mi = mi
32 j.fi = fi
33 j.inner = inner
34 } else {
35 i := len(t.tables) + 1
36 jt := &dbTable{i, fmt.Sprintf("T%d", i), name, names, false, inner, mi, fi, nil}
37 t.tablesM[name] = jt
38 t.tables = append(t.tables, jt)
39 }
40 return t.tablesM[name]
41 }
42
43 func (t *dbTables) add(names []string, mi *modelInfo, fi *fieldInfo, inner bool) (*dbTable, bool) {
44 name := strings.Join(names, ExprSep)
45 if _, ok := t.tablesM[name]; ok == false {
46 i := len(t.tables) + 1
47 jt := &dbTable{i, fmt.Sprintf("T%d", i), name, names, false, inner, mi, fi, nil}
48 t.tablesM[name] = jt
49 t.tables = append(t.tables, jt)
50 return jt, true
51 }
52 return t.tablesM[name], false
53 }
54
55 func (t *dbTables) get(name string) (*dbTable, bool) {
56 j, ok := t.tablesM[name]
57 return j, ok
58 }
59
60 func (t *dbTables) loopDepth(depth int, prefix string, fi *fieldInfo, related []string) []string {
61 if depth < 0 || fi.fieldType == RelManyToMany {
62 return related
63 }
64
65 if prefix == "" {
66 prefix = fi.name
67 } else {
68 prefix = prefix + ExprSep + fi.name
69 }
70 related = append(related, prefix)
71
72 depth--
73 for _, fi := range fi.relModelInfo.fields.fieldsRel {
74 related = t.loopDepth(depth, prefix, fi, related)
75 }
76
77 return related
78 }
79
80 func (t *dbTables) parseRelated(rels []string, depth int) {
81
82 relsNum := len(rels)
83 related := make([]string, relsNum)
84 copy(related, rels)
85
86 relDepth := depth
87
88 if relsNum != 0 {
89 relDepth = 0
90 }
91
92 relDepth--
93 for _, fi := range t.mi.fields.fieldsRel {
94 related = t.loopDepth(relDepth, "", fi, related)
95 }
96
97 for i, s := range related {
98 var (
99 exs = strings.Split(s, ExprSep)
100 names = make([]string, 0, len(exs))
101 mmi = t.mi
102 cansel = true
103 jtl *dbTable
104 )
105 for _, ex := range exs {
106 if fi, ok := mmi.fields.GetByAny(ex); ok && fi.rel && fi.fieldType != RelManyToMany {
107 names = append(names, fi.name)
108 mmi = fi.relModelInfo
109
110 jt := t.set(names, mmi, fi, fi.null == false)
111 jt.jtl = jtl
112
113 if fi.reverse {
114 cansel = false
115 }
116
117 if cansel {
118 jt.sel = depth > 0
119
120 if i < relsNum {
121 jt.sel = true
122 }
123 }
124
125 jtl = jt
126
127 } else {
128 panic(fmt.Sprintf("unknown model/table name `%s`", ex))
129 }
130 }
131 }
132 }
133
134 func (t *dbTables) getJoinSql() (join string) {
135 Q := t.base.TableQuote()
136
137 for _, jt := range t.tables {
138 if jt.inner {
139 join += "INNER JOIN "
140 } else {
141 join += "LEFT OUTER JOIN "
142 }
143 var (
144 table string
145 t1, t2 string
146 c1, c2 string
147 )
148 t1 = "T0"
149 if jt.jtl != nil {
150 t1 = jt.jtl.index
151 }
152 t2 = jt.index
153 table = jt.mi.table
154
155 switch {
156 case jt.fi.fieldType == RelManyToMany || jt.fi.reverse && jt.fi.reverseFieldInfo.fieldType == RelManyToMany:
157 c1 = jt.fi.mi.fields.pk.column
158 for _, ffi := range jt.mi.fields.fieldsRel {
159 if jt.fi.mi == ffi.relModelInfo {
160 c2 = ffi.column
161 break
162 }
163 }
164 default:
165 c1 = jt.fi.column
166 c2 = jt.fi.relModelInfo.fields.pk.column
167
168 if jt.fi.reverse {
169 c1 = jt.mi.fields.pk.column
170 c2 = jt.fi.reverseFieldInfo.column
171 }
172 }
173
174 join += fmt.Sprintf("%s%s%s %s ON %s.%s%s%s = %s.%s%s%s ", Q, table, Q, t2,
175 t2, Q, c2, Q, t1, Q, c1, Q)
176 }
177 return
178 }
179
180 func (d *dbTables) parseExprs(mi *modelInfo, exprs []string) (index, column, name string, info *fieldInfo, success bool) {
181 var (
182 ffi *fieldInfo
183 jtl *dbTable
184 mmi = mi
185 )
186
187 num := len(exprs) - 1
188 names := make([]string, 0)
189
190 for i, ex := range exprs {
191 exist := false
192
193 check:
194 fi, ok := mmi.fields.GetByAny(ex)
195
196 if ok {
197
198 if num != i {
199 names = append(names, fi.name)
200
201 switch {
202 case fi.rel:
203 mmi = fi.relModelInfo
204 if fi.fieldType == RelManyToMany {
205 mmi = fi.relThroughModelInfo
206 }
207 case fi.reverse:
208 mmi = fi.reverseFieldInfo.mi
209 if fi.reverseFieldInfo.fieldType == RelManyToMany {
210 mmi = fi.reverseFieldInfo.relThroughModelInfo
211 }
212 default:
213 return
214 }
215
216 jt, _ := d.add(names, mmi, fi, fi.null == false)
217 jt.jtl = jtl
218 jtl = jt
219
220 if fi.rel && fi.fieldType == RelManyToMany {
221 ex = fi.relModelInfo.name
222 goto check
223 }
224
225 if fi.reverse && fi.reverseFieldInfo.fieldType == RelManyToMany {
226 ex = fi.reverseFieldInfo.mi.name
227 goto check
228 }
229
230 exist = true
231
232 } else {
233
234 if ffi == nil {
235 index = "T0"
236 } else {
237 index = jtl.index
238 }
239 column = fi.column
240 info = fi
241 if jtl != nil {
242 name = jtl.name + ExprSep + fi.name
243 } else {
244 name = fi.name
245 }
246
247 switch fi.fieldType {
248 case RelManyToMany, RelReverseMany:
249 default:
250 exist = true
251 }
252 }
253
254 ffi = fi
255 }
256
257 if exist == false {
258 index = ""
259 column = ""
260 name = ""
261 success = false
262 return
263 }
264 }
265
266 success = index != "" && column != ""
267 return
268 }
269
270 func (d *dbTables) getCondSql(cond *Condition, sub bool) (where string, params []interface{}) {
271 if cond == nil || cond.IsEmpty() {
272 return
273 }
274
275 Q := d.base.TableQuote()
276
277 mi := d.mi
278
279 // outFor:
280 for i, p := range cond.params {
281 if i > 0 {
282 if p.isOr {
283 where += "OR "
284 } else {
285 where += "AND "
286 }
287 }
288 if p.isNot {
289 where += "NOT "
290 }
291 if p.isCond {
292 w, ps := d.getCondSql(p.cond, true)
293 if w != "" {
294 w = fmt.Sprintf("( %s) ", w)
295 }
296 where += w
297 params = append(params, ps...)
298 } else {
299 exprs := p.exprs
300
301 num := len(exprs) - 1
302 operator := ""
303 if operators[exprs[num]] {
304 operator = exprs[num]
305 exprs = exprs[:num]
306 }
307
308 index, column, _, _, suc := d.parseExprs(mi, exprs)
309 if suc == false {
310 panic(fmt.Errorf("unknown field/column name `%s`", strings.Join(p.exprs, ExprSep)))
311 }
312
313 if operator == "" {
314 operator = "exact"
315 }
316
317 operSql, args := d.base.GenerateOperatorSql(mi, operator, p.args)
318
319 where += fmt.Sprintf("%s.%s%s%s %s ", index, Q, column, Q, operSql)
320 params = append(params, args...)
321
322 }
323 }
324
325 if sub == false && where != "" {
326 where = "WHERE " + where
327 }
328
329 return
330 }
331
332 func (d *dbTables) getOrderSql(orders []string) (orderSql string) {
333 if len(orders) == 0 {
334 return
335 }
336
337 Q := d.base.TableQuote()
338
339 orderSqls := make([]string, 0, len(orders))
340 for _, order := range orders {
341 asc := "ASC"
342 if order[0] == '-' {
343 asc = "DESC"
344 order = order[1:]
345 }
346 exprs := strings.Split(order, ExprSep)
347
348 index, column, _, _, suc := d.parseExprs(d.mi, exprs)
349 if suc == false {
350 panic(fmt.Errorf("unknown field/column name `%s`", strings.Join(exprs, ExprSep)))
351 }
352
353 orderSqls = append(orderSqls, fmt.Sprintf("%s.%s%s%s %s", index, Q, column, Q, asc))
354 }
355
356 orderSql = fmt.Sprintf("ORDER BY %s ", strings.Join(orderSqls, ", "))
357 return
358 }
359
360 func (d *dbTables) getLimitSql(mi *modelInfo, offset int64, limit int) (limits string) {
361 if limit == 0 {
362 limit = DefaultRowsLimit
363 }
364 if limit < 0 {
365 // no limit
366 if offset > 0 {
367 maxLimit := d.base.MaxLimit()
368 limits = fmt.Sprintf("LIMIT %d OFFSET %d", maxLimit, offset)
369 }
370 } else if offset <= 0 {
371 limits = fmt.Sprintf("LIMIT %d", limit)
372 } else {
373 limits = fmt.Sprintf("LIMIT %d OFFSET %d", limit, offset)
374 }
375 return
376 }
377
378 func newDbTables(mi *modelInfo, base dbBaser) *dbTables {
379 tables := &dbTables{}
380 tables.tablesM = make(map[string]*dbTable)
381 tables.mi = mi
382 tables.base = base
383 return tables
384 }
...@@ -79,7 +79,7 @@ func newModelInfo(val reflect.Value) (info *modelInfo) { ...@@ -79,7 +79,7 @@ func newModelInfo(val reflect.Value) (info *modelInfo) {
79 func newM2MModelInfo(m1, m2 *modelInfo) (info *modelInfo) { 79 func newM2MModelInfo(m1, m2 *modelInfo) (info *modelInfo) {
80 info = new(modelInfo) 80 info = new(modelInfo)
81 info.fields = newFields() 81 info.fields = newFields()
82 info.table = m1.table + "_" + m2.table + "_rel" 82 info.table = m1.table + "_" + m2.table + "s"
83 info.name = camelString(info.table) 83 info.name = camelString(info.table)
84 info.fullName = m1.pkg + "." + info.name 84 info.fullName = m1.pkg + "." + info.name
85 85
......
...@@ -3,10 +3,11 @@ package orm ...@@ -3,10 +3,11 @@ package orm
3 import ( 3 import (
4 "fmt" 4 "fmt"
5 "os" 5 "os"
6 "strings"
6 "time" 7 "time"
7 8
8 _ "github.com/bmizerany/pq"
9 _ "github.com/go-sql-driver/mysql" 9 _ "github.com/go-sql-driver/mysql"
10 _ "github.com/lib/pq"
10 _ "github.com/mattn/go-sqlite3" 11 _ "github.com/mattn/go-sqlite3"
11 ) 12 )
12 13
...@@ -95,8 +96,178 @@ var DBARGS = struct { ...@@ -95,8 +96,178 @@ var DBARGS = struct {
95 os.Getenv("ORM_DEBUG"), 96 os.Getenv("ORM_DEBUG"),
96 } 97 }
97 98
99 var (
100 IsMysql = DBARGS.Driver == "mysql"
101 IsSqlite = DBARGS.Driver == "sqlite3"
102 IsPostgres = DBARGS.Driver == "postgres"
103 )
104
98 var dORM Ormer 105 var dORM Ormer
99 106
107 var initSQLs = map[string]string{
108 "mysql": "DROP TABLE IF EXISTS `user_profile`;\n" +
109 "DROP TABLE IF EXISTS `user`;\n" +
110 "DROP TABLE IF EXISTS `post`;\n" +
111 "DROP TABLE IF EXISTS `tag`;\n" +
112 "DROP TABLE IF EXISTS `post_tags`;\n" +
113 "DROP TABLE IF EXISTS `comment`;\n" +
114 "CREATE TABLE `user_profile` (\n" +
115 " `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,\n" +
116 " `age` smallint NOT NULL,\n" +
117 " `money` double precision NOT NULL\n" +
118 ") ENGINE=INNODB;\n" +
119 "CREATE TABLE `user` (\n" +
120 " `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,\n" +
121 " `user_name` varchar(30) NOT NULL UNIQUE,\n" +
122 " `email` varchar(100) NOT NULL,\n" +
123 " `password` varchar(100) NOT NULL,\n" +
124 " `status` smallint NOT NULL,\n" +
125 " `is_staff` bool NOT NULL,\n" +
126 " `is_active` bool NOT NULL,\n" +
127 " `created` date NOT NULL,\n" +
128 " `updated` datetime NOT NULL,\n" +
129 " `profile_id` integer\n" +
130 ") ENGINE=INNODB;\n" +
131 "CREATE TABLE `post` (\n" +
132 " `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,\n" +
133 " `user_id` integer NOT NULL,\n" +
134 " `title` varchar(60) NOT NULL,\n" +
135 " `content` longtext NOT NULL,\n" +
136 " `created` datetime NOT NULL,\n" +
137 " `updated` datetime NOT NULL\n" +
138 ") ENGINE=INNODB;\n" +
139 "CREATE TABLE `tag` (\n" +
140 " `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,\n" +
141 " `name` varchar(30) NOT NULL\n" +
142 ") ENGINE=INNODB;\n" +
143 "CREATE TABLE `post_tags` (\n" +
144 " `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,\n" +
145 " `post_id` integer NOT NULL,\n" +
146 " `tag_id` integer NOT NULL,\n" +
147 " UNIQUE (`post_id`, `tag_id`)\n" +
148 ") ENGINE=INNODB;\n" +
149 "CREATE TABLE `comment` (\n" +
150 " `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,\n" +
151 " `post_id` integer NOT NULL,\n" +
152 " `content` longtext NOT NULL,\n" +
153 " `parent_id` integer,\n" +
154 " `created` datetime NOT NULL\n" +
155 ") ENGINE=INNODB;\n" +
156 "CREATE INDEX `user_141c6eec` ON `user` (`profile_id`);\n" +
157 "CREATE INDEX `post_fbfc09f1` ON `post` (`user_id`);\n" +
158 "CREATE INDEX `comment_699ae8ca` ON `comment` (`post_id`);\n" +
159 "CREATE INDEX `comment_63f17a16` ON `comment` (`parent_id`);",
160
161 "sqlite3": `
162 DROP TABLE IF EXISTS "user_profile";
163 DROP TABLE IF EXISTS "user";
164 DROP TABLE IF EXISTS "post";
165 DROP TABLE IF EXISTS "tag";
166 DROP TABLE IF EXISTS "post_tags";
167 DROP TABLE IF EXISTS "comment";
168 CREATE TABLE "user_profile" (
169 "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
170 "age" smallint NOT NULL,
171 "money" real NOT NULL
172 );
173 CREATE TABLE "user" (
174 "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
175 "user_name" varchar(30) NOT NULL UNIQUE,
176 "email" varchar(100) NOT NULL,
177 "password" varchar(100) NOT NULL,
178 "status" smallint NOT NULL,
179 "is_staff" bool NOT NULL,
180 "is_active" bool NOT NULL,
181 "created" date NOT NULL,
182 "updated" datetime NOT NULL,
183 "profile_id" integer
184 );
185 CREATE TABLE "post" (
186 "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
187 "user_id" integer NOT NULL,
188 "title" varchar(60) NOT NULL,
189 "content" text NOT NULL,
190 "created" datetime NOT NULL,
191 "updated" datetime NOT NULL
192 );
193 CREATE TABLE "tag" (
194 "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
195 "name" varchar(30) NOT NULL
196 );
197 CREATE TABLE "post_tags" (
198 "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
199 "post_id" integer NOT NULL,
200 "tag_id" integer NOT NULL,
201 UNIQUE ("post_id", "tag_id")
202 );
203 CREATE TABLE "comment" (
204 "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
205 "post_id" integer NOT NULL,
206 "content" text NOT NULL,
207 "parent_id" integer,
208 "created" datetime NOT NULL
209 );
210 CREATE INDEX "user_141c6eec" ON "user" ("profile_id");
211 CREATE INDEX "post_fbfc09f1" ON "post" ("user_id");
212 CREATE INDEX "comment_699ae8ca" ON "comment" ("post_id");
213 CREATE INDEX "comment_63f17a16" ON "comment" ("parent_id");
214 `,
215
216 "postgres": `
217 DROP TABLE IF EXISTS "user_profile";
218 DROP TABLE IF EXISTS "user";
219 DROP TABLE IF EXISTS "post";
220 DROP TABLE IF EXISTS "tag";
221 DROP TABLE IF EXISTS "post_tags";
222 DROP TABLE IF EXISTS "comment";
223 CREATE TABLE "user_profile" (
224 "id" serial NOT NULL PRIMARY KEY,
225 "age" smallint NOT NULL,
226 "money" double precision NOT NULL
227 );
228 CREATE TABLE "user" (
229 "id" serial NOT NULL PRIMARY KEY,
230 "user_name" varchar(30) NOT NULL UNIQUE,
231 "email" varchar(100) NOT NULL,
232 "password" varchar(100) NOT NULL,
233 "status" smallint NOT NULL,
234 "is_staff" boolean NOT NULL,
235 "is_active" boolean NOT NULL,
236 "created" date NOT NULL,
237 "updated" timestamp with time zone NOT NULL,
238 "profile_id" integer
239 );
240 CREATE TABLE "post" (
241 "id" serial NOT NULL PRIMARY KEY,
242 "user_id" integer NOT NULL,
243 "title" varchar(60) NOT NULL,
244 "content" text NOT NULL,
245 "created" timestamp with time zone NOT NULL,
246 "updated" timestamp with time zone NOT NULL
247 );
248 CREATE TABLE "tag" (
249 "id" serial NOT NULL PRIMARY KEY,
250 "name" varchar(30) NOT NULL
251 );
252 CREATE TABLE "post_tags" (
253 "id" serial NOT NULL PRIMARY KEY,
254 "post_id" integer NOT NULL,
255 "tag_id" integer NOT NULL,
256 UNIQUE ("post_id", "tag_id")
257 );
258 CREATE TABLE "comment" (
259 "id" serial NOT NULL PRIMARY KEY,
260 "post_id" integer NOT NULL,
261 "content" text NOT NULL,
262 "parent_id" integer,
263 "created" timestamp with time zone NOT NULL
264 );
265 CREATE INDEX "user_profile_id" ON "user" ("profile_id");
266 CREATE INDEX "post_user_id" ON "post" ("user_id");
267 CREATE INDEX "comment_post_id" ON "comment" ("post_id");
268 CREATE INDEX "comment_parent_id" ON "comment" ("parent_id");
269 `}
270
100 func init() { 271 func init() {
101 RegisterModel(new(User)) 272 RegisterModel(new(User))
102 RegisterModel(new(Profile)) 273 RegisterModel(new(Profile))
...@@ -114,7 +285,7 @@ Default DB Drivers. ...@@ -114,7 +285,7 @@ Default DB Drivers.
114 driver: url 285 driver: url
115 mysql: https://github.com/go-sql-driver/mysql 286 mysql: https://github.com/go-sql-driver/mysql
116 sqlite3: https://github.com/mattn/go-sqlite3 287 sqlite3: https://github.com/mattn/go-sqlite3
117 postgres: https://github.com/bmizerany/pq 288 postgres: https://github.com/lib/pq
118 289
119 eg: mysql 290 eg: mysql
120 ORM_DRIVER=mysql ORM_SOURCE="root:root@/my_db?charset=utf8" go test github.com/astaxie/beego/orm 291 ORM_DRIVER=mysql ORM_SOURCE="root:root@/my_db?charset=utf8" go test github.com/astaxie/beego/orm
...@@ -126,20 +297,16 @@ ORM_DRIVER=mysql ORM_SOURCE="root:root@/my_db?charset=utf8" go test github.com/a ...@@ -126,20 +297,16 @@ ORM_DRIVER=mysql ORM_SOURCE="root:root@/my_db?charset=utf8" go test github.com/a
126 297
127 BootStrap() 298 BootStrap()
128 299
129 truncateTables()
130
131 dORM = NewOrm() 300 dORM = NewOrm()
132 }
133 301
134 func truncateTables() { 302 queries := strings.Split(initSQLs[DBARGS.Driver], ";")
135 logs := "truncate tables for test\n" 303
136 o := NewOrm() 304 for _, query := range queries {
137 for _, m := range modelCache.allOrdered() { 305 if strings.TrimSpace(query) == "" {
138 query := fmt.Sprintf("truncate table `%s`", m.table) 306 continue
139 _, err := o.Raw(query).Exec() 307 }
140 logs += query + "\n" 308 _, err := dORM.Raw(query).Exec()
141 if err != nil { 309 if err != nil {
142 fmt.Println(logs)
143 fmt.Println(err) 310 fmt.Println(err)
144 os.Exit(2) 311 os.Exit(2)
145 } 312 }
......
...@@ -135,7 +135,7 @@ func (d *dbQueryLog) Commit() error { ...@@ -135,7 +135,7 @@ func (d *dbQueryLog) Commit() error {
135 135
136 func (d *dbQueryLog) Rollback() error { 136 func (d *dbQueryLog) Rollback() error {
137 a := time.Now() 137 a := time.Now()
138 err := d.db.(txEnder).Commit() 138 err := d.db.(txEnder).Rollback()
139 debugLogQueies(d.alias, "tx.Rollback", "ROLLBACK", a, err) 139 debugLogQueies(d.alias, "tx.Rollback", "ROLLBACK", a, err)
140 return err 140 return err
141 } 141 }
......
...@@ -6,39 +6,17 @@ import ( ...@@ -6,39 +6,17 @@ import (
6 "reflect" 6 "reflect"
7 ) 7 )
8 8
9 func getResult(res sql.Result) (int64, error) {
10 if num, err := res.LastInsertId(); err != nil {
11 return 0, err
12 } else {
13 if num > 0 {
14 return num, nil
15 }
16 }
17 if num, err := res.RowsAffected(); err != nil {
18 return num, err
19 } else {
20 if num > 0 {
21 return num, nil
22 }
23 }
24 return 0, nil
25 }
26
27 type rawPrepare struct { 9 type rawPrepare struct {
28 rs *rawSet 10 rs *rawSet
29 stmt stmtQuerier 11 stmt stmtQuerier
30 closed bool 12 closed bool
31 } 13 }
32 14
33 func (o *rawPrepare) Exec(args ...interface{}) (int64, error) { 15 func (o *rawPrepare) Exec(args ...interface{}) (sql.Result, error) {
34 if o.closed { 16 if o.closed {
35 return 0, ErrStmtClosed 17 return nil, ErrStmtClosed
36 }
37 res, err := o.stmt.Exec(args...)
38 if err != nil {
39 return 0, err
40 } 18 }
41 return getResult(res) 19 return o.stmt.Exec(args...)
42 } 20 }
43 21
44 func (o *rawPrepare) Close() error { 22 func (o *rawPrepare) Close() error {
...@@ -74,12 +52,8 @@ func (o rawSet) SetArgs(args ...interface{}) RawSeter { ...@@ -74,12 +52,8 @@ func (o rawSet) SetArgs(args ...interface{}) RawSeter {
74 return &o 52 return &o
75 } 53 }
76 54
77 func (o *rawSet) Exec() (int64, error) { 55 func (o *rawSet) Exec() (sql.Result, error) {
78 res, err := o.orm.db.Exec(o.query, o.args...) 56 return o.orm.db.Exec(o.query, o.args...)
79 if err != nil {
80 return 0, err
81 }
82 return getResult(res)
83 } 57 }
84 58
85 func (o *rawSet) QueryRow(...interface{}) error { 59 func (o *rawSet) QueryRow(...interface{}) error {
......
...@@ -60,12 +60,12 @@ type QuerySeter interface { ...@@ -60,12 +60,12 @@ type QuerySeter interface {
60 } 60 }
61 61
62 type RawPreparer interface { 62 type RawPreparer interface {
63 Exec(...interface{}) (int64, error) 63 Exec(...interface{}) (sql.Result, error)
64 Close() error 64 Close() error
65 } 65 }
66 66
67 type RawSeter interface { 67 type RawSeter interface {
68 Exec() (int64, error) 68 Exec() (sql.Result, error)
69 QueryRow(...interface{}) error 69 QueryRow(...interface{}) error
70 QueryRows(...interface{}) (int64, error) 70 QueryRows(...interface{}) (int64, error)
71 SetArgs(...interface{}) RawSeter 71 SetArgs(...interface{}) RawSeter
...@@ -116,10 +116,15 @@ type dbBaser interface { ...@@ -116,10 +116,15 @@ type dbBaser interface {
116 Update(dbQuerier, *modelInfo, reflect.Value) (int64, error) 116 Update(dbQuerier, *modelInfo, reflect.Value) (int64, error)
117 Delete(dbQuerier, *modelInfo, reflect.Value) (int64, error) 117 Delete(dbQuerier, *modelInfo, reflect.Value) (int64, error)
118 ReadBatch(dbQuerier, *querySet, *modelInfo, *Condition, interface{}) (int64, error) 118 ReadBatch(dbQuerier, *querySet, *modelInfo, *Condition, interface{}) (int64, error)
119 SupportUpdateJoin() bool
119 UpdateBatch(dbQuerier, *querySet, *modelInfo, *Condition, Params) (int64, error) 120 UpdateBatch(dbQuerier, *querySet, *modelInfo, *Condition, Params) (int64, error)
120 DeleteBatch(dbQuerier, *querySet, *modelInfo, *Condition) (int64, error) 121 DeleteBatch(dbQuerier, *querySet, *modelInfo, *Condition) (int64, error)
121 Count(dbQuerier, *querySet, *modelInfo, *Condition) (int64, error) 122 Count(dbQuerier, *querySet, *modelInfo, *Condition) (int64, error)
122 GetOperatorSql(*modelInfo, string, []interface{}) (string, []interface{}) 123 OperatorSql(string) string
124 GenerateOperatorSql(*modelInfo, string, []interface{}) (string, []interface{})
123 PrepareInsert(dbQuerier, *modelInfo) (stmtQuerier, string, error) 125 PrepareInsert(dbQuerier, *modelInfo) (stmtQuerier, string, error)
124 ReadValues(dbQuerier, *querySet, *modelInfo, *Condition, []string, interface{}) (int64, error) 126 ReadValues(dbQuerier, *querySet, *modelInfo, *Condition, []string, interface{}) (int64, error)
127 MaxLimit() uint64
128 TableQuote() string
129 ReplaceMarks(*string)
125 } 130 }
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!