#384
Showing
2 changed files
with
214 additions
and
240 deletions
| ... | @@ -4,7 +4,6 @@ import ( | ... | @@ -4,7 +4,6 @@ import ( |
| 4 | "database/sql" | 4 | "database/sql" |
| 5 | "fmt" | 5 | "fmt" |
| 6 | "reflect" | 6 | "reflect" |
| 7 | "strings" | ||
| 8 | "time" | 7 | "time" |
| 9 | ) | 8 | ) |
| 10 | 9 | ||
| ... | @@ -164,65 +163,11 @@ func (o *rawSet) setFieldValue(ind reflect.Value, value interface{}) { | ... | @@ -164,65 +163,11 @@ func (o *rawSet) setFieldValue(ind reflect.Value, value interface{}) { |
| 164 | } | 163 | } |
| 165 | } | 164 | } |
| 166 | 165 | ||
| 167 | func (o *rawSet) loopInitRefs(typ reflect.Type, refsPtr *[]interface{}, sIdxesPtr *[][]int) { | 166 | func (o *rawSet) loopSetRefs(refs []interface{}, sInds []reflect.Value, nIndsPtr *[]reflect.Value, eTyps []reflect.Type, init bool) { |
| 168 | sIdxes := *sIdxesPtr | ||
| 169 | refs := *refsPtr | ||
| 170 | |||
| 171 | if typ.Kind() == reflect.Struct { | ||
| 172 | if typ.String() == "time.Time" { | ||
| 173 | var ref interface{} | ||
| 174 | refs = append(refs, &ref) | ||
| 175 | sIdxes = append(sIdxes, []int{0}) | ||
| 176 | } else { | ||
| 177 | idxs := []int{} | ||
| 178 | outFor: | ||
| 179 | for idx := 0; idx < typ.NumField(); idx++ { | ||
| 180 | ctyp := typ.Field(idx) | ||
| 181 | |||
| 182 | tag := ctyp.Tag.Get(defaultStructTagName) | ||
| 183 | for _, v := range strings.Split(tag, defaultStructTagDelim) { | ||
| 184 | if v == "-" { | ||
| 185 | continue outFor | ||
| 186 | } | ||
| 187 | } | ||
| 188 | |||
| 189 | tp := ctyp.Type | ||
| 190 | if tp.Kind() == reflect.Ptr { | ||
| 191 | tp = tp.Elem() | ||
| 192 | } | ||
| 193 | |||
| 194 | if tp.String() == "time.Time" { | ||
| 195 | var ref interface{} | ||
| 196 | refs = append(refs, &ref) | ||
| 197 | |||
| 198 | } else if tp.Kind() != reflect.Struct { | ||
| 199 | var ref interface{} | ||
| 200 | refs = append(refs, &ref) | ||
| 201 | |||
| 202 | } else { | ||
| 203 | // skip other type | ||
| 204 | continue | ||
| 205 | } | ||
| 206 | |||
| 207 | idxs = append(idxs, idx) | ||
| 208 | } | ||
| 209 | sIdxes = append(sIdxes, idxs) | ||
| 210 | } | ||
| 211 | } else { | ||
| 212 | var ref interface{} | ||
| 213 | refs = append(refs, &ref) | ||
| 214 | sIdxes = append(sIdxes, []int{0}) | ||
| 215 | } | ||
| 216 | |||
| 217 | *sIdxesPtr = sIdxes | ||
| 218 | *refsPtr = refs | ||
| 219 | } | ||
| 220 | |||
| 221 | func (o *rawSet) loopSetRefs(refs []interface{}, sIdxes [][]int, sInds []reflect.Value, nIndsPtr *[]reflect.Value, eTyps []reflect.Type, init bool) { | ||
| 222 | nInds := *nIndsPtr | 167 | nInds := *nIndsPtr |
| 223 | 168 | ||
| 224 | cur := 0 | 169 | cur := 0 |
| 225 | for i, idxs := range sIdxes { | 170 | for i := 0; i < len(sInds); i++ { |
| 226 | sInd := sInds[i] | 171 | sInd := sInds[i] |
| 227 | eTyp := eTyps[i] | 172 | eTyp := eTyps[i] |
| 228 | 173 | ||
| ... | @@ -258,32 +203,8 @@ func (o *rawSet) loopSetRefs(refs []interface{}, sIdxes [][]int, sInds []reflect | ... | @@ -258,32 +203,8 @@ func (o *rawSet) loopSetRefs(refs []interface{}, sIdxes [][]int, sInds []reflect |
| 258 | o.setFieldValue(ind, value) | 203 | o.setFieldValue(ind, value) |
| 259 | } | 204 | } |
| 260 | cur++ | 205 | cur++ |
| 261 | } else { | ||
| 262 | hasValue := false | ||
| 263 | for _, idx := range idxs { | ||
| 264 | tind := ind.Field(idx) | ||
| 265 | value := reflect.ValueOf(refs[cur]).Elem().Interface() | ||
| 266 | if value != nil { | ||
| 267 | hasValue = true | ||
| 268 | } | ||
| 269 | if tind.Kind() == reflect.Ptr { | ||
| 270 | if value == nil { | ||
| 271 | tindV := reflect.New(tind.Type()).Elem() | ||
| 272 | tind.Set(tindV) | ||
| 273 | } else { | ||
| 274 | tindV := reflect.New(tind.Type().Elem()) | ||
| 275 | o.setFieldValue(tindV.Elem(), value) | ||
| 276 | tind.Set(tindV) | ||
| 277 | } | ||
| 278 | } else { | ||
| 279 | o.setFieldValue(tind, value) | ||
| 280 | } | ||
| 281 | cur++ | ||
| 282 | } | ||
| 283 | if hasValue == false && isPtr { | ||
| 284 | val = reflect.New(val.Type()).Elem() | ||
| 285 | } | ||
| 286 | } | 206 | } |
| 207 | |||
| 287 | } else { | 208 | } else { |
| 288 | value := reflect.ValueOf(refs[cur]).Elem().Interface() | 209 | value := reflect.ValueOf(refs[cur]).Elem().Interface() |
| 289 | if isPtr && value == nil { | 210 | if isPtr && value == nil { |
| ... | @@ -313,15 +234,12 @@ func (o *rawSet) loopSetRefs(refs []interface{}, sIdxes [][]int, sInds []reflect | ... | @@ -313,15 +234,12 @@ func (o *rawSet) loopSetRefs(refs []interface{}, sIdxes [][]int, sInds []reflect |
| 313 | } | 234 | } |
| 314 | 235 | ||
| 315 | func (o *rawSet) QueryRow(containers ...interface{}) error { | 236 | func (o *rawSet) QueryRow(containers ...interface{}) error { |
| 316 | if len(containers) == 0 { | ||
| 317 | panic(fmt.Errorf("<RawSeter.QueryRow> need at least one arg")) | ||
| 318 | } | ||
| 319 | |||
| 320 | refs := make([]interface{}, 0, len(containers)) | 237 | refs := make([]interface{}, 0, len(containers)) |
| 321 | sIdxes := make([][]int, 0) | ||
| 322 | sInds := make([]reflect.Value, 0) | 238 | sInds := make([]reflect.Value, 0) |
| 323 | eTyps := make([]reflect.Type, 0) | 239 | eTyps := make([]reflect.Type, 0) |
| 324 | 240 | ||
| 241 | structMode := false | ||
| 242 | var sMi *modelInfo | ||
| 325 | for _, container := range containers { | 243 | for _, container := range containers { |
| 326 | val := reflect.ValueOf(container) | 244 | val := reflect.ValueOf(container) |
| 327 | ind := reflect.Indirect(val) | 245 | ind := reflect.Indirect(val) |
| ... | @@ -335,44 +253,120 @@ func (o *rawSet) QueryRow(containers ...interface{}) error { | ... | @@ -335,44 +253,120 @@ func (o *rawSet) QueryRow(containers ...interface{}) error { |
| 335 | if typ.Kind() == reflect.Ptr { | 253 | if typ.Kind() == reflect.Ptr { |
| 336 | typ = typ.Elem() | 254 | typ = typ.Elem() |
| 337 | } | 255 | } |
| 338 | if typ.Kind() == reflect.Ptr { | ||
| 339 | typ = typ.Elem() | ||
| 340 | } | ||
| 341 | 256 | ||
| 342 | sInds = append(sInds, ind) | 257 | sInds = append(sInds, ind) |
| 343 | eTyps = append(eTyps, etyp) | 258 | eTyps = append(eTyps, etyp) |
| 344 | 259 | ||
| 345 | o.loopInitRefs(typ, &refs, &sIdxes) | 260 | if typ.Kind() == reflect.Struct && typ.String() != "time.Time" { |
| 261 | if len(containers) > 1 { | ||
| 262 | panic(fmt.Errorf("<RawSeter.QueryRow> now support one struct only. see #384")) | ||
| 263 | } | ||
| 264 | |||
| 265 | structMode = true | ||
| 266 | fn := getFullName(typ) | ||
| 267 | if mi, ok := modelCache.getByFN(fn); ok { | ||
| 268 | sMi = mi | ||
| 269 | } | ||
| 270 | } else { | ||
| 271 | var ref interface{} | ||
| 272 | refs = append(refs, &ref) | ||
| 273 | } | ||
| 346 | } | 274 | } |
| 347 | 275 | ||
| 348 | query := o.query | 276 | query := o.query |
| 349 | o.orm.alias.DbBaser.ReplaceMarks(&query) | 277 | o.orm.alias.DbBaser.ReplaceMarks(&query) |
| 350 | 278 | ||
| 351 | args := getFlatParams(nil, o.args, o.orm.alias.TZ) | 279 | args := getFlatParams(nil, o.args, o.orm.alias.TZ) |
| 352 | row := o.orm.db.QueryRow(query, args...) | 280 | rows, err := o.orm.db.Query(query, args...) |
| 353 | 281 | if err != nil { | |
| 354 | if err := row.Scan(refs...); err == sql.ErrNoRows { | 282 | if err == sql.ErrNoRows { |
| 355 | return ErrNoRows | 283 | return ErrNoRows |
| 356 | } else if err != nil { | 284 | } |
| 285 | return err | ||
| 286 | } | ||
| 287 | |||
| 288 | if rows.Next() { | ||
| 289 | if structMode { | ||
| 290 | columns, err := rows.Columns() | ||
| 291 | if err != nil { | ||
| 292 | return err | ||
| 293 | } | ||
| 294 | |||
| 295 | columnsMp := make(map[string]interface{}, len(columns)) | ||
| 296 | |||
| 297 | refs = make([]interface{}, 0, len(columns)) | ||
| 298 | for _, col := range columns { | ||
| 299 | var ref interface{} | ||
| 300 | columnsMp[col] = &ref | ||
| 301 | refs = append(refs, &ref) | ||
| 302 | } | ||
| 303 | |||
| 304 | if err := rows.Scan(refs...); err != nil { | ||
| 305 | return err | ||
| 306 | } | ||
| 307 | |||
| 308 | ind := sInds[0] | ||
| 309 | |||
| 310 | if ind.Kind() == reflect.Ptr { | ||
| 311 | if ind.IsNil() || !ind.IsValid() { | ||
| 312 | ind.Set(reflect.New(eTyps[0].Elem())) | ||
| 313 | } | ||
| 314 | ind = ind.Elem() | ||
| 315 | } | ||
| 316 | |||
| 317 | if sMi != nil { | ||
| 318 | for _, col := range columns { | ||
| 319 | if fi := sMi.fields.GetByColumn(col); fi != nil { | ||
| 320 | value := reflect.ValueOf(columnsMp[col]).Elem().Interface() | ||
| 321 | o.setFieldValue(ind.FieldByIndex([]int{fi.fieldIndex}), value) | ||
| 322 | } | ||
| 323 | } | ||
| 324 | } else { | ||
| 325 | for i := 0; i < ind.NumField(); i++ { | ||
| 326 | f := ind.Field(i) | ||
| 327 | fe := ind.Type().Field(i) | ||
| 328 | |||
| 329 | var attrs map[string]bool | ||
| 330 | var tags map[string]string | ||
| 331 | parseStructTag(fe.Tag.Get("orm"), &attrs, &tags) | ||
| 332 | var col string | ||
| 333 | if col = tags["column"]; len(col) == 0 { | ||
| 334 | col = snakeString(fe.Name) | ||
| 335 | } | ||
| 336 | if v, ok := columnsMp[col]; ok { | ||
| 337 | value := reflect.ValueOf(v).Elem().Interface() | ||
| 338 | o.setFieldValue(f, value) | ||
| 339 | } | ||
| 340 | } | ||
| 341 | } | ||
| 342 | |||
| 343 | } else { | ||
| 344 | if err := rows.Scan(refs...); err != nil { | ||
| 357 | return err | 345 | return err |
| 358 | } | 346 | } |
| 359 | 347 | ||
| 360 | nInds := make([]reflect.Value, len(sInds)) | 348 | nInds := make([]reflect.Value, len(sInds)) |
| 361 | o.loopSetRefs(refs, sIdxes, sInds, &nInds, eTyps, true) | 349 | o.loopSetRefs(refs, sInds, &nInds, eTyps, true) |
| 362 | for i, sInd := range sInds { | 350 | for i, sInd := range sInds { |
| 363 | nInd := nInds[i] | 351 | nInd := nInds[i] |
| 364 | sInd.Set(nInd) | 352 | sInd.Set(nInd) |
| 365 | } | 353 | } |
| 354 | } | ||
| 355 | |||
| 356 | } else { | ||
| 357 | return ErrNoRows | ||
| 358 | } | ||
| 366 | 359 | ||
| 367 | return nil | 360 | return nil |
| 368 | } | 361 | } |
| 369 | 362 | ||
| 370 | func (o *rawSet) QueryRows(containers ...interface{}) (int64, error) { | 363 | func (o *rawSet) QueryRows(containers ...interface{}) (int64, error) { |
| 371 | refs := make([]interface{}, 0) | 364 | refs := make([]interface{}, 0, len(containers)) |
| 372 | sIdxes := make([][]int, 0) | ||
| 373 | sInds := make([]reflect.Value, 0) | 365 | sInds := make([]reflect.Value, 0) |
| 374 | eTyps := make([]reflect.Type, 0) | 366 | eTyps := make([]reflect.Type, 0) |
| 375 | 367 | ||
| 368 | structMode := false | ||
| 369 | var sMi *modelInfo | ||
| 376 | for _, container := range containers { | 370 | for _, container := range containers { |
| 377 | val := reflect.ValueOf(container) | 371 | val := reflect.ValueOf(container) |
| 378 | sInd := reflect.Indirect(val) | 372 | sInd := reflect.Indirect(val) |
| ... | @@ -389,7 +383,20 @@ func (o *rawSet) QueryRows(containers ...interface{}) (int64, error) { | ... | @@ -389,7 +383,20 @@ func (o *rawSet) QueryRows(containers ...interface{}) (int64, error) { |
| 389 | sInds = append(sInds, sInd) | 383 | sInds = append(sInds, sInd) |
| 390 | eTyps = append(eTyps, etyp) | 384 | eTyps = append(eTyps, etyp) |
| 391 | 385 | ||
| 392 | o.loopInitRefs(typ, &refs, &sIdxes) | 386 | if typ.Kind() == reflect.Struct && typ.String() != "time.Time" { |
| 387 | if len(containers) > 1 { | ||
| 388 | panic(fmt.Errorf("<RawSeter.QueryRow> now support one struct only. see #384")) | ||
| 389 | } | ||
| 390 | |||
| 391 | structMode = true | ||
| 392 | fn := getFullName(typ) | ||
| 393 | if mi, ok := modelCache.getByFN(fn); ok { | ||
| 394 | sMi = mi | ||
| 395 | } | ||
| 396 | } else { | ||
| 397 | var ref interface{} | ||
| 398 | refs = append(refs, &ref) | ||
| 399 | } | ||
| 393 | } | 400 | } |
| 394 | 401 | ||
| 395 | query := o.query | 402 | query := o.query |
| ... | @@ -403,23 +410,99 @@ func (o *rawSet) QueryRows(containers ...interface{}) (int64, error) { | ... | @@ -403,23 +410,99 @@ func (o *rawSet) QueryRows(containers ...interface{}) (int64, error) { |
| 403 | 410 | ||
| 404 | nInds := make([]reflect.Value, len(sInds)) | 411 | nInds := make([]reflect.Value, len(sInds)) |
| 405 | 412 | ||
| 413 | sInd := sInds[0] | ||
| 414 | |||
| 406 | var cnt int64 | 415 | var cnt int64 |
| 407 | for rows.Next() { | 416 | for rows.Next() { |
| 417 | |||
| 418 | if structMode { | ||
| 419 | columns, err := rows.Columns() | ||
| 420 | if err != nil { | ||
| 421 | return 0, err | ||
| 422 | } | ||
| 423 | |||
| 424 | columnsMp := make(map[string]interface{}, len(columns)) | ||
| 425 | |||
| 426 | refs = make([]interface{}, 0, len(columns)) | ||
| 427 | for _, col := range columns { | ||
| 428 | var ref interface{} | ||
| 429 | columnsMp[col] = &ref | ||
| 430 | refs = append(refs, &ref) | ||
| 431 | } | ||
| 432 | |||
| 408 | if err := rows.Scan(refs...); err != nil { | 433 | if err := rows.Scan(refs...); err != nil { |
| 409 | return 0, err | 434 | return 0, err |
| 410 | } | 435 | } |
| 411 | 436 | ||
| 412 | o.loopSetRefs(refs, sIdxes, sInds, &nInds, eTyps, cnt == 0) | 437 | if cnt == 0 && !sInd.IsNil() { |
| 438 | sInd.Set(reflect.New(sInd.Type()).Elem()) | ||
| 439 | } | ||
| 440 | |||
| 441 | var ind reflect.Value | ||
| 442 | if eTyps[0].Kind() == reflect.Ptr { | ||
| 443 | ind = reflect.New(eTyps[0].Elem()) | ||
| 444 | } else { | ||
| 445 | ind = reflect.New(eTyps[0]) | ||
| 446 | } | ||
| 447 | |||
| 448 | if ind.Kind() == reflect.Ptr { | ||
| 449 | ind = ind.Elem() | ||
| 450 | } | ||
| 451 | |||
| 452 | if sMi != nil { | ||
| 453 | for _, col := range columns { | ||
| 454 | if fi := sMi.fields.GetByColumn(col); fi != nil { | ||
| 455 | value := reflect.ValueOf(columnsMp[col]).Elem().Interface() | ||
| 456 | o.setFieldValue(ind.FieldByIndex([]int{fi.fieldIndex}), value) | ||
| 457 | } | ||
| 458 | } | ||
| 459 | } else { | ||
| 460 | for i := 0; i < ind.NumField(); i++ { | ||
| 461 | f := ind.Field(i) | ||
| 462 | fe := ind.Type().Field(i) | ||
| 463 | |||
| 464 | var attrs map[string]bool | ||
| 465 | var tags map[string]string | ||
| 466 | parseStructTag(fe.Tag.Get("orm"), &attrs, &tags) | ||
| 467 | var col string | ||
| 468 | if col = tags["column"]; len(col) == 0 { | ||
| 469 | col = snakeString(fe.Name) | ||
| 470 | } | ||
| 471 | if v, ok := columnsMp[col]; ok { | ||
| 472 | value := reflect.ValueOf(v).Elem().Interface() | ||
| 473 | o.setFieldValue(f, value) | ||
| 474 | } | ||
| 475 | } | ||
| 476 | } | ||
| 477 | |||
| 478 | if eTyps[0].Kind() == reflect.Ptr { | ||
| 479 | ind = ind.Addr() | ||
| 480 | } | ||
| 481 | |||
| 482 | sInd = reflect.Append(sInd, ind) | ||
| 483 | |||
| 484 | } else { | ||
| 485 | if err := rows.Scan(refs...); err != nil { | ||
| 486 | return 0, err | ||
| 487 | } | ||
| 488 | |||
| 489 | o.loopSetRefs(refs, sInds, &nInds, eTyps, cnt == 0) | ||
| 490 | } | ||
| 413 | 491 | ||
| 414 | cnt++ | 492 | cnt++ |
| 415 | } | 493 | } |
| 416 | 494 | ||
| 417 | if cnt > 0 { | 495 | if cnt > 0 { |
| 496 | |||
| 497 | if structMode { | ||
| 498 | sInds[0].Set(sInd) | ||
| 499 | } else { | ||
| 418 | for i, sInd := range sInds { | 500 | for i, sInd := range sInds { |
| 419 | nInd := nInds[i] | 501 | nInd := nInds[i] |
| 420 | sInd.Set(nInd) | 502 | sInd.Set(nInd) |
| 421 | } | 503 | } |
| 422 | } | 504 | } |
| 505 | } | ||
| 423 | 506 | ||
| 424 | return cnt, nil | 507 | return cnt, nil |
| 425 | } | 508 | } | ... | ... |
| ... | @@ -1322,58 +1322,6 @@ func TestRawQueryRow(t *testing.T) { | ... | @@ -1322,58 +1322,6 @@ func TestRawQueryRow(t *testing.T) { |
| 1322 | } | 1322 | } |
| 1323 | } | 1323 | } |
| 1324 | 1324 | ||
| 1325 | type Tmp struct { | ||
| 1326 | Skip0 string | ||
| 1327 | Id int | ||
| 1328 | Char *string | ||
| 1329 | Skip1 int `orm:"-"` | ||
| 1330 | Date time.Time | ||
| 1331 | DateTime time.Time | ||
| 1332 | } | ||
| 1333 | |||
| 1334 | Boolean = false | ||
| 1335 | Text = "" | ||
| 1336 | Int64 = 0 | ||
| 1337 | Uint = 0 | ||
| 1338 | |||
| 1339 | tmp := new(Tmp) | ||
| 1340 | |||
| 1341 | cols = []string{ | ||
| 1342 | "int", "char", "date", "datetime", "boolean", "text", "int64", "uint", | ||
| 1343 | } | ||
| 1344 | query = fmt.Sprintf("SELECT NULL, %s%s%s FROM data WHERE id = ?", Q, strings.Join(cols, sep), Q) | ||
| 1345 | values = []interface{}{ | ||
| 1346 | tmp, &Boolean, &Text, &Int64, &Uint, | ||
| 1347 | } | ||
| 1348 | err = dORM.Raw(query, 1).QueryRow(values...) | ||
| 1349 | throwFailNow(t, err) | ||
| 1350 | |||
| 1351 | for _, col := range cols { | ||
| 1352 | switch col { | ||
| 1353 | case "id": | ||
| 1354 | throwFail(t, AssertIs(tmp.Id, data_values[col])) | ||
| 1355 | case "char": | ||
| 1356 | c := tmp.Char | ||
| 1357 | throwFail(t, AssertIs(*c, data_values[col])) | ||
| 1358 | case "date": | ||
| 1359 | v := tmp.Date.In(DefaultTimeLoc) | ||
| 1360 | value := data_values[col].(time.Time).In(DefaultTimeLoc) | ||
| 1361 | throwFail(t, AssertIs(v, value, test_Date)) | ||
| 1362 | case "datetime": | ||
| 1363 | v := tmp.DateTime.In(DefaultTimeLoc) | ||
| 1364 | value := data_values[col].(time.Time).In(DefaultTimeLoc) | ||
| 1365 | throwFail(t, AssertIs(v, value, test_DateTime)) | ||
| 1366 | case "boolean": | ||
| 1367 | throwFail(t, AssertIs(Boolean, data_values[col])) | ||
| 1368 | case "text": | ||
| 1369 | throwFail(t, AssertIs(Text, data_values[col])) | ||
| 1370 | case "int64": | ||
| 1371 | throwFail(t, AssertIs(Int64, data_values[col])) | ||
| 1372 | case "uint": | ||
| 1373 | throwFail(t, AssertIs(Uint, data_values[col])) | ||
| 1374 | } | ||
| 1375 | } | ||
| 1376 | |||
| 1377 | var ( | 1325 | var ( |
| 1378 | uid int | 1326 | uid int |
| 1379 | status *int | 1327 | status *int |
| ... | @@ -1394,22 +1342,13 @@ func TestRawQueryRow(t *testing.T) { | ... | @@ -1394,22 +1342,13 @@ func TestRawQueryRow(t *testing.T) { |
| 1394 | func TestQueryRows(t *testing.T) { | 1342 | func TestQueryRows(t *testing.T) { |
| 1395 | Q := dDbBaser.TableQuote() | 1343 | Q := dDbBaser.TableQuote() |
| 1396 | 1344 | ||
| 1397 | cols := []string{ | ||
| 1398 | "id", "boolean", "char", "text", "date", "datetime", "byte", "rune", "int", "int8", "int16", "int32", | ||
| 1399 | "int64", "uint", "uint8", "uint16", "uint32", "uint64", "float32", "float64", "decimal", | ||
| 1400 | } | ||
| 1401 | |||
| 1402 | var datas []*Data | 1345 | var datas []*Data |
| 1403 | var dids []int | ||
| 1404 | 1346 | ||
| 1405 | sep := fmt.Sprintf("%s, %s", Q, Q) | 1347 | query := fmt.Sprintf("SELECT * FROM %sdata%s", Q, Q) |
| 1406 | query := fmt.Sprintf("SELECT %s%s%s, id FROM %sdata%s", Q, strings.Join(cols, sep), Q, Q, Q) | 1348 | num, err := dORM.Raw(query).QueryRows(&datas) |
| 1407 | num, err := dORM.Raw(query).QueryRows(&datas, &dids) | ||
| 1408 | throwFailNow(t, err) | 1349 | throwFailNow(t, err) |
| 1409 | throwFailNow(t, AssertIs(num, 1)) | 1350 | throwFailNow(t, AssertIs(num, 1)) |
| 1410 | throwFailNow(t, AssertIs(len(datas), 1)) | 1351 | throwFailNow(t, AssertIs(len(datas), 1)) |
| 1411 | throwFailNow(t, AssertIs(len(dids), 1)) | ||
| 1412 | throwFailNow(t, AssertIs(dids[0], 1)) | ||
| 1413 | 1352 | ||
| 1414 | ind := reflect.Indirect(reflect.ValueOf(datas[0])) | 1353 | ind := reflect.Indirect(reflect.ValueOf(datas[0])) |
| 1415 | 1354 | ||
| ... | @@ -1427,90 +1366,42 @@ func TestQueryRows(t *testing.T) { | ... | @@ -1427,90 +1366,42 @@ func TestQueryRows(t *testing.T) { |
| 1427 | throwFail(t, AssertIs(vu == value, true), value, vu) | 1366 | throwFail(t, AssertIs(vu == value, true), value, vu) |
| 1428 | } | 1367 | } |
| 1429 | 1368 | ||
| 1430 | type Tmp struct { | 1369 | var datas2 []Data |
| 1431 | Id int | ||
| 1432 | Name string | ||
| 1433 | Skiped0 string `orm:"-"` | ||
| 1434 | Pid *int | ||
| 1435 | Skiped1 Data | ||
| 1436 | Skiped2 *Data | ||
| 1437 | } | ||
| 1438 | 1370 | ||
| 1439 | var ( | 1371 | query = fmt.Sprintf("SELECT * FROM %sdata%s", Q, Q) |
| 1440 | ids []int | 1372 | num, err = dORM.Raw(query).QueryRows(&datas2) |
| 1441 | userNames []string | ||
| 1442 | profileIds1 []int | ||
| 1443 | profileIds2 []*int | ||
| 1444 | createds []time.Time | ||
| 1445 | updateds []time.Time | ||
| 1446 | tmps1 []*Tmp | ||
| 1447 | tmps2 []Tmp | ||
| 1448 | ) | ||
| 1449 | cols = []string{ | ||
| 1450 | "id", "user_name", "profile_id", "profile_id", "id", "user_name", "profile_id", "id", "user_name", "profile_id", "created", "updated", | ||
| 1451 | } | ||
| 1452 | query = fmt.Sprintf("SELECT %s%s%s FROM %suser%s ORDER BY id", Q, strings.Join(cols, sep), Q, Q, Q) | ||
| 1453 | num, err = dORM.Raw(query).QueryRows(&ids, &userNames, &profileIds1, &profileIds2, &tmps1, &tmps2, &createds, &updateds) | ||
| 1454 | throwFailNow(t, err) | 1373 | throwFailNow(t, err) |
| 1455 | throwFailNow(t, AssertIs(num, 3)) | 1374 | throwFailNow(t, AssertIs(num, 1)) |
| 1456 | 1375 | throwFailNow(t, AssertIs(len(datas2), 1)) | |
| 1457 | var users []User | ||
| 1458 | dORM.QueryTable("user").OrderBy("Id").All(&users) | ||
| 1459 | |||
| 1460 | for i := 0; i < 3; i++ { | ||
| 1461 | id := ids[i] | ||
| 1462 | name := userNames[i] | ||
| 1463 | pid1 := profileIds1[i] | ||
| 1464 | pid2 := profileIds2[i] | ||
| 1465 | created := createds[i] | ||
| 1466 | updated := updateds[i] | ||
| 1467 | |||
| 1468 | user := users[i] | ||
| 1469 | throwFailNow(t, AssertIs(id, user.Id)) | ||
| 1470 | throwFailNow(t, AssertIs(name, user.UserName)) | ||
| 1471 | if user.Profile != nil { | ||
| 1472 | throwFailNow(t, AssertIs(pid1, user.Profile.Id)) | ||
| 1473 | throwFailNow(t, AssertIs(*pid2, user.Profile.Id)) | ||
| 1474 | } else { | ||
| 1475 | throwFailNow(t, AssertIs(pid1, 0)) | ||
| 1476 | throwFailNow(t, AssertIs(pid2, nil)) | ||
| 1477 | } | ||
| 1478 | throwFailNow(t, AssertIs(created, user.Created, test_Date)) | ||
| 1479 | throwFailNow(t, AssertIs(updated, user.Updated, test_DateTime)) | ||
| 1480 | 1376 | ||
| 1481 | tmp := tmps1[i] | 1377 | ind = reflect.Indirect(reflect.ValueOf(datas2[0])) |
| 1482 | tmp1 := *tmp | ||
| 1483 | throwFailNow(t, AssertIs(tmp1.Id, user.Id)) | ||
| 1484 | throwFailNow(t, AssertIs(tmp1.Name, user.UserName)) | ||
| 1485 | if user.Profile != nil { | ||
| 1486 | pid := tmp1.Pid | ||
| 1487 | throwFailNow(t, AssertIs(*pid, user.Profile.Id)) | ||
| 1488 | } else { | ||
| 1489 | throwFailNow(t, AssertIs(tmp1.Pid, nil)) | ||
| 1490 | } | ||
| 1491 | 1378 | ||
| 1492 | tmp2 := tmps2[i] | 1379 | for name, value := range Data_Values { |
| 1493 | throwFailNow(t, AssertIs(tmp2.Id, user.Id)) | 1380 | e := ind.FieldByName(name) |
| 1494 | throwFailNow(t, AssertIs(tmp2.Name, user.UserName)) | 1381 | vu := e.Interface() |
| 1495 | if user.Profile != nil { | 1382 | switch name { |
| 1496 | pid := tmp2.Pid | 1383 | case "Date": |
| 1497 | throwFailNow(t, AssertIs(*pid, user.Profile.Id)) | 1384 | vu = vu.(time.Time).In(DefaultTimeLoc).Format(test_Date) |
| 1498 | } else { | 1385 | value = value.(time.Time).In(DefaultTimeLoc).Format(test_Date) |
| 1499 | throwFailNow(t, AssertIs(tmp2.Pid, nil)) | 1386 | case "DateTime": |
| 1500 | } | 1387 | vu = vu.(time.Time).In(DefaultTimeLoc).Format(test_DateTime) |
| 1388 | value = value.(time.Time).In(DefaultTimeLoc).Format(test_DateTime) | ||
| 1501 | } | 1389 | } |
| 1502 | 1390 | throwFail(t, AssertIs(vu == value, true), value, vu) | |
| 1503 | type Sec struct { | ||
| 1504 | Id int | ||
| 1505 | Name string | ||
| 1506 | } | 1391 | } |
| 1507 | 1392 | ||
| 1508 | var tmp []*Sec | 1393 | var ids []int |
| 1509 | query = fmt.Sprintf("SELECT NULL, NULL FROM %suser%s LIMIT 1", Q, Q) | 1394 | var usernames []string |
| 1510 | num, err = dORM.Raw(query).QueryRows(&tmp) | 1395 | num, err = dORM.Raw("SELECT id, user_name FROM user ORDER BY id asc").QueryRows(&ids, &usernames) |
| 1511 | throwFail(t, err) | 1396 | throwFailNow(t, err) |
| 1512 | throwFail(t, AssertIs(num, 1)) | 1397 | throwFailNow(t, AssertIs(num, 3)) |
| 1513 | throwFail(t, AssertIs(tmp[0], nil)) | 1398 | throwFailNow(t, AssertIs(len(ids), 3)) |
| 1399 | throwFailNow(t, AssertIs(ids[0], 2)) | ||
| 1400 | throwFailNow(t, AssertIs(usernames[0], "slene")) | ||
| 1401 | throwFailNow(t, AssertIs(ids[1], 3)) | ||
| 1402 | throwFailNow(t, AssertIs(usernames[1], "astaxie")) | ||
| 1403 | throwFailNow(t, AssertIs(ids[2], 4)) | ||
| 1404 | throwFailNow(t, AssertIs(usernames[2], "nobody")) | ||
| 1514 | } | 1405 | } |
| 1515 | 1406 | ||
| 1516 | func TestRawValues(t *testing.T) { | 1407 | func TestRawValues(t *testing.T) { | ... | ... |
-
Please register or sign in to post a comment