github.com/RevenueMonster/sqlike@v1.0.6/sql/dialect/mysql/builder.go (about) 1 package mysql 2 3 import ( 4 "errors" 5 "reflect" 6 "strconv" 7 "strings" 8 9 "github.com/RevenueMonster/sqlike/reflext" 10 "github.com/RevenueMonster/sqlike/spatial" 11 "github.com/RevenueMonster/sqlike/sql" 12 "github.com/RevenueMonster/sqlike/sql/codec" 13 sqlstmt "github.com/RevenueMonster/sqlike/sql/stmt" 14 sqlutil "github.com/RevenueMonster/sqlike/sql/util" 15 "github.com/RevenueMonster/sqlike/sqlike/actions" 16 "github.com/RevenueMonster/sqlike/sqlike/primitive" 17 ) 18 19 var operatorMap = map[primitive.Operator]string{ 20 primitive.Equal: "=", 21 primitive.NotEqual: "<>", 22 primitive.In: "IN", 23 primitive.NotIn: "NOT IN", 24 primitive.Between: "BETWEEN", 25 primitive.NotBetween: "NOT BETWEEN", 26 primitive.IsNull: "IS NULL", 27 primitive.NotNull: "IS NOT NULL", 28 primitive.GreaterThan: ">", 29 primitive.GreaterOrEqual: ">=", 30 primitive.LesserThan: "<", 31 primitive.LesserOrEqual: "<=", 32 primitive.Or: "OR", 33 primitive.And: "AND", 34 } 35 36 type mySQLBuilder struct { 37 registry codec.Codecer 38 builder *sqlstmt.StatementBuilder 39 sqlutil.MySQLUtil 40 } 41 42 func (b mySQLBuilder) SetRegistryAndBuilders(rg codec.Codecer, blr *sqlstmt.StatementBuilder) { 43 if rg == nil { 44 panic("missing required registry") 45 } 46 if blr == nil { 47 panic("missing required parser") 48 } 49 blr.SetBuilder(reflect.TypeOf(primitive.CastAs{}), b.BuildCastAs) 50 blr.SetBuilder(reflect.TypeOf(primitive.Func{}), b.BuildFunction) 51 blr.SetBuilder(reflect.TypeOf(primitive.JSONFunc{}), b.BuildJSONFunction) 52 blr.SetBuilder(reflect.TypeOf(primitive.Field{}), b.BuildField) 53 blr.SetBuilder(reflect.TypeOf(primitive.Value{}), b.BuildValue) 54 blr.SetBuilder(reflect.TypeOf(primitive.As{}), b.BuildAs) 55 blr.SetBuilder(reflect.TypeOf(primitive.Nil{}), b.BuildNil) 56 blr.SetBuilder(reflect.TypeOf(primitive.Raw{}), b.BuildRaw) 57 blr.SetBuilder(reflect.TypeOf(primitive.Encoding{}), b.BuildEncoding) 58 blr.SetBuilder(reflect.TypeOf(primitive.Aggregate{}), b.BuildAggregate) 59 blr.SetBuilder(reflect.TypeOf(primitive.Column{}), b.BuildColumn) 60 blr.SetBuilder(reflect.TypeOf(primitive.JSONColumn{}), b.BuildJSONColumn) 61 blr.SetBuilder(reflect.TypeOf(primitive.C{}), b.BuildClause) 62 blr.SetBuilder(reflect.TypeOf(primitive.L{}), b.BuildLike) 63 blr.SetBuilder(reflect.TypeOf(primitive.TypeSafe{}), b.BuildTypeSafe) 64 blr.SetBuilder(reflect.TypeOf(primitive.Operator(0)), b.BuildOperator) 65 blr.SetBuilder(reflect.TypeOf(primitive.Group{}), b.BuildGroup) 66 blr.SetBuilder(reflect.TypeOf(primitive.R{}), b.BuildRange) 67 blr.SetBuilder(reflect.TypeOf(primitive.Sort{}), b.BuildSort) 68 blr.SetBuilder(reflect.TypeOf(primitive.KV{}), b.BuildKeyValue) 69 blr.SetBuilder(reflect.TypeOf(primitive.Math{}), b.BuildMath) 70 blr.SetBuilder(reflect.TypeOf(&primitive.Case{}), b.BuildCase) 71 blr.SetBuilder(reflect.TypeOf(spatial.Func{}), b.BuildSpatialFunc) 72 blr.SetBuilder(reflect.TypeOf(&sql.SelectStmt{}), b.BuildSelectStmt) 73 blr.SetBuilder(reflect.TypeOf(&sql.UpdateStmt{}), b.BuildUpdateStmt) 74 // blr.SetBuilder(reflect.TypeOf(&sql.DeleteStmt{}), b.BuildDeleteStmt) 75 blr.SetBuilder(reflect.TypeOf(&actions.FindActions{}), b.BuildFindActions) 76 blr.SetBuilder(reflect.TypeOf(&actions.UpdateActions{}), b.BuildUpdateActions) 77 blr.SetBuilder(reflect.TypeOf(&actions.DeleteActions{}), b.BuildDeleteActions) 78 blr.SetBuilder(reflect.String, b.BuildString) 79 b.registry = rg 80 b.builder = blr 81 } 82 83 // BuildCastAs : 84 func (b *mySQLBuilder) BuildCastAs(stmt sqlstmt.Stmt, it interface{}) error { 85 x := it.(primitive.CastAs) 86 stmt.WriteString("CAST(") 87 if err := b.builder.BuildStatement(stmt, x.Value); err != nil { 88 return err 89 } 90 stmt.WriteString(" AS ") 91 switch x.DataType { 92 case primitive.JSON: 93 stmt.WriteString("JSON") 94 default: 95 return errors.New("mysql: unsupported cast as data type") 96 } 97 stmt.WriteByte(')') 98 return nil 99 } 100 101 // BuildFunction : 102 func (b *mySQLBuilder) BuildFunction(stmt sqlstmt.Stmt, it interface{}) error { 103 x := it.(primitive.Func) 104 stmt.WriteString(x.Name) 105 stmt.WriteByte('(') 106 for i, args := range x.Args { 107 if i > 0 { 108 stmt.WriteByte(',') 109 } 110 if err := b.builder.BuildStatement(stmt, args); err != nil { 111 return err 112 } 113 } 114 stmt.WriteByte(')') 115 return nil 116 } 117 118 // BuildJSONFunction : 119 func (b *mySQLBuilder) BuildJSONFunction(stmt sqlstmt.Stmt, it interface{}) error { 120 x := it.(primitive.JSONFunc) 121 if x.Prefix != nil { 122 if err := b.getValue(stmt, x.Prefix); err != nil { 123 return err 124 } 125 stmt.WriteString(" ") 126 } 127 stmt.WriteString(x.Type.String()) 128 stmt.WriteByte('(') 129 for i, args := range x.Args { 130 if i > 0 { 131 stmt.WriteByte(',') 132 } 133 if err := b.builder.BuildStatement(stmt, args); err != nil { 134 return err 135 } 136 } 137 stmt.WriteByte(')') 138 return nil 139 } 140 141 // BuildString : 142 func (b *mySQLBuilder) BuildString(stmt sqlstmt.Stmt, it interface{}) error { 143 v := reflect.ValueOf(it) 144 stmt.WriteString(b.Quote(v.String())) 145 return nil 146 } 147 148 // BuildLike : 149 func (b *mySQLBuilder) BuildLike(stmt sqlstmt.Stmt, it interface{}) error { 150 x := it.(primitive.L) 151 if err := b.builder.BuildStatement(stmt, x.Field); err != nil { 152 return err 153 } 154 155 stmt.WriteByte(' ') 156 if x.IsNot { 157 stmt.WriteString("NOT LIKE") 158 } else { 159 stmt.WriteString("LIKE") 160 } 161 stmt.WriteByte(' ') 162 v := reflext.ValueOf(x.Value) 163 if !v.IsValid() { 164 stmt.WriteByte('?') 165 stmt.AppendArgs(nil) 166 return nil 167 } 168 169 t := v.Type() 170 if builder, ok := b.builder.LookupBuilder(t); ok { 171 if err := builder(stmt, x.Value); err != nil { 172 return err 173 } 174 return nil 175 } 176 177 stmt.WriteByte('?') 178 encoder, err := b.registry.LookupEncoder(v) 179 if err != nil { 180 return err 181 } 182 vv, err := encoder(nil, v) 183 if err != nil { 184 return err 185 } 186 switch vi := vv.(type) { 187 case string: 188 vv = escapeWildCard(vi) 189 case []byte: 190 vv = escapeWildCard(string(vi)) 191 } 192 stmt.AppendArgs(vv) 193 return nil 194 } 195 196 // BuildField : 197 func (b *mySQLBuilder) BuildField(stmt sqlstmt.Stmt, it interface{}) error { 198 x := it.(primitive.Field) 199 stmt.WriteString("FIELD") 200 stmt.WriteByte('(') 201 stmt.WriteString(b.Quote(x.Name)) 202 for _, v := range x.Values { 203 stmt.WriteByte(',') 204 if err := b.getValue(stmt, v); err != nil { 205 return err 206 } 207 } 208 stmt.WriteByte(')') 209 return nil 210 } 211 212 // BuildValue : 213 func (b *mySQLBuilder) BuildValue(stmt sqlstmt.Stmt, it interface{}) (err error) { 214 x := it.(primitive.Value) 215 v := reflext.ValueOf(x.Raw) 216 if !v.IsValid() { 217 stmt.WriteByte('?') 218 stmt.AppendArgs(nil) 219 return 220 } 221 222 encoder, err := b.registry.LookupEncoder(v) 223 if err != nil { 224 return err 225 } 226 vv, err := encoder(nil, v) 227 if err != nil { 228 return err 229 } 230 convertSpatial(stmt, vv) 231 // stmt.WriteRune('?') 232 // stmt.AppendArgs(vv) 233 return nil 234 } 235 236 // BuildColumn : 237 func (b *mySQLBuilder) BuildColumn(stmt sqlstmt.Stmt, it interface{}) error { 238 x := it.(primitive.Column) 239 if x.Table != "" { 240 stmt.WriteString(b.Quote(x.Table)) 241 stmt.WriteByte('.') 242 } 243 stmt.WriteString(b.Quote(x.Name)) 244 return nil 245 } 246 247 // BuildJSONColumn : 248 func (b *mySQLBuilder) BuildJSONColumn(stmt sqlstmt.Stmt, it interface{}) error { 249 /* 250 Expected columns ( JSON_EXTRACT ) 251 Column : Address 252 Nested : [ State, City ] 253 UnquoteResult : false 254 255 Result 256 `Address`->'$.State.City' 257 258 -------------------------------------------- 259 260 Expected columns ( JSON_EXTRACT(JSON_UNQUOTE) ) 261 Column : Address 262 Nested : [ State, City ] 263 UnquoteResult : true 264 265 Result 266 `Address`->>'$.State.City' 267 */ 268 x := it.(primitive.JSONColumn) 269 nested := strings.Join(x.Nested, ".") 270 operator := "->" 271 if !strings.HasPrefix(nested, "$.") { 272 nested = "$." + nested 273 } 274 if x.UnquoteResult { 275 operator += ">" 276 } 277 stmt.WriteString(b.Quote(x.Column) + operator + b.Wrap(nested)) 278 return nil 279 } 280 281 // BuildNil : 282 func (b *mySQLBuilder) BuildNil(stmt sqlstmt.Stmt, it interface{}) error { 283 x := it.(primitive.Nil) 284 if err := b.builder.BuildStatement(stmt, x.Field); err != nil { 285 return err 286 } 287 if x.IsNot { 288 stmt.WriteString(" IS NULL") 289 } else { 290 stmt.WriteString(" IS NOT NULL") 291 } 292 return nil 293 } 294 295 // BuildRaw : 296 func (b *mySQLBuilder) BuildRaw(stmt sqlstmt.Stmt, it interface{}) error { 297 x, ok := it.(primitive.Raw) 298 if ok { 299 stmt.WriteString(x.Value) 300 } 301 return nil 302 } 303 304 // BuildAs : 305 func (b *mySQLBuilder) BuildAs(stmt sqlstmt.Stmt, it interface{}) error { 306 stmt.WriteByte('(') 307 x := it.(primitive.As) 308 if err := b.getValue(stmt, x.Field); err != nil { 309 return err 310 } 311 stmt.WriteByte(')') 312 stmt.WriteString(" AS ") 313 stmt.WriteString(b.Quote(x.Name)) 314 return nil 315 } 316 317 // BuildAggregate : 318 func (b *mySQLBuilder) BuildAggregate(stmt sqlstmt.Stmt, it interface{}) error { 319 x := it.(primitive.Aggregate) 320 switch x.By { 321 case primitive.Sum: 322 stmt.WriteString("COALESCE(SUM(") 323 if err := b.getValue(stmt, x.Field); err != nil { 324 return err 325 } 326 stmt.WriteString("),0)") 327 return nil 328 case primitive.Average: 329 stmt.WriteString("AVG") 330 case primitive.Count: 331 stmt.WriteString("COUNT") 332 case primitive.Max: 333 stmt.WriteString("MAX") 334 case primitive.Min: 335 stmt.WriteString("MIN") 336 } 337 stmt.WriteByte('(') 338 if err := b.getValue(stmt, x.Field); err != nil { 339 return err 340 } 341 stmt.WriteByte(')') 342 return nil 343 } 344 345 // BuildOperator : 346 func (b *mySQLBuilder) BuildOperator(stmt sqlstmt.Stmt, it interface{}) error { 347 x := it.(primitive.Operator) 348 stmt.WriteByte(' ') 349 stmt.WriteString(operatorMap[x]) 350 stmt.WriteByte(' ') 351 return nil 352 } 353 354 // BuildClause : 355 func (b *mySQLBuilder) BuildClause(stmt sqlstmt.Stmt, it interface{}) error { 356 x := it.(primitive.C) 357 if err := b.builder.BuildStatement(stmt, x.Field); err != nil { 358 return err 359 } 360 361 stmt.WriteString(" " + operatorMap[x.Operator] + " ") 362 switch x.Operator { 363 case primitive.IsNull, primitive.NotNull: 364 return nil 365 } 366 367 if err := b.getValue(stmt, x.Value); err != nil { 368 return err 369 } 370 return nil 371 } 372 373 // BuildSort : 374 func (b *mySQLBuilder) BuildSort(stmt sqlstmt.Stmt, it interface{}) error { 375 x := it.(primitive.Sort) 376 if err := b.builder.BuildStatement(stmt, x.Field); err != nil { 377 return err 378 } 379 if x.Order == primitive.Descending { 380 stmt.WriteByte(' ') 381 stmt.WriteString("DESC") 382 } 383 return nil 384 } 385 386 // BuildKeyValue : 387 func (b *mySQLBuilder) BuildKeyValue(stmt sqlstmt.Stmt, it interface{}) (err error) { 388 x := it.(primitive.KV) 389 stmt.WriteString(b.Quote(string(x.Field))) 390 stmt.WriteString(" = ") 391 return b.getValue(stmt, x.Value) 392 } 393 394 // BuildMath : 395 func (b *mySQLBuilder) BuildMath(stmt sqlstmt.Stmt, it interface{}) (err error) { 396 x := it.(primitive.Math) 397 stmt.WriteString(b.Quote(string(x.Field)) + " ") 398 if x.Mode == primitive.Add { 399 stmt.WriteByte('+') 400 } else { 401 stmt.WriteByte('-') 402 } 403 stmt.WriteString(" " + strconv.Itoa(x.Value)) 404 return 405 } 406 407 // BuildCase : 408 func (b *mySQLBuilder) BuildCase(stmt sqlstmt.Stmt, it interface{}) error { 409 x := it.(*primitive.Case) 410 stmt.WriteByte('(') 411 stmt.WriteString("CASE") 412 for _, w := range x.WhenClauses { 413 stmt.WriteString(" WHEN ") 414 if err := b.builder.BuildStatement(stmt, w[0]); err != nil { 415 return err 416 } 417 stmt.WriteString(" THEN ") 418 if err := b.getValue(stmt, w[1]); err != nil { 419 return err 420 } 421 } 422 stmt.WriteString(" ELSE ") 423 if x.ElseClause != nil { 424 if err := b.getValue(stmt, x.ElseClause); err != nil { 425 return err 426 } 427 } 428 stmt.WriteString(" END") 429 stmt.WriteByte(')') 430 return nil 431 } 432 433 // BuildSpatialFunc : 434 func (b *mySQLBuilder) BuildSpatialFunc(stmt sqlstmt.Stmt, it interface{}) (err error) { 435 x := it.(spatial.Func) 436 stmt.WriteString(x.Type.String()) 437 stmt.WriteByte('(') 438 for i, arg := range x.Args { 439 if i > 0 { 440 stmt.WriteByte(',') 441 } 442 if err := b.builder.BuildStatement(stmt, arg); err != nil { 443 return err 444 } 445 } 446 stmt.WriteByte(')') 447 return 448 } 449 450 // BuildGroup : 451 func (b *mySQLBuilder) BuildGroup(stmt sqlstmt.Stmt, it interface{}) (err error) { 452 x := it.(primitive.Group) 453 for len(x.Values) > 0 { 454 if err := b.getValue(stmt, x.Values[0]); err != nil { 455 return err 456 } 457 x.Values = x.Values[1:] 458 } 459 return 460 } 461 462 // BuildRange : 463 func (b *mySQLBuilder) BuildRange(stmt sqlstmt.Stmt, it interface{}) (err error) { 464 x := it.(primitive.R) 465 v := reflext.ValueOf(x.From) 466 encoder, err := b.registry.LookupEncoder(v) 467 if err != nil { 468 return err 469 } 470 arg, err := encoder(nil, v) 471 if err != nil { 472 return err 473 } 474 stmt.AppendArgs(arg) 475 476 v = reflext.ValueOf(x.To) 477 encoder, err = b.registry.LookupEncoder(v) 478 if err != nil { 479 return err 480 } 481 arg, err = encoder(nil, v) 482 if err != nil { 483 return err 484 } 485 stmt.AppendArgs(arg) 486 stmt.WriteByte('?') 487 stmt.WriteString(" AND ") 488 stmt.WriteByte('?') 489 return 490 } 491 492 // BuildEncoding : 493 func (b *mySQLBuilder) BuildEncoding(stmt sqlstmt.Stmt, it interface{}) (err error) { 494 x := it.(primitive.Encoding) 495 if x.Charset != nil { 496 if (*x.Charset)[0] != '_' { 497 stmt.WriteString("_") 498 } 499 stmt.WriteString(*x.Charset + " ") 500 } 501 err = b.builder.BuildStatement(stmt, x.Column) 502 if err != nil { 503 return 504 } 505 stmt.WriteString(" COLLATE " + x.Collate) 506 return 507 } 508 509 // BuildTypeSafe : 510 func (b *mySQLBuilder) BuildTypeSafe(stmt sqlstmt.Stmt, it interface{}) (err error) { 511 ts := it.(primitive.TypeSafe) 512 switch ts.Type { 513 case reflect.String: 514 stmt.WriteString(strconv.Quote(ts.Value.(string))) 515 case reflect.Bool: 516 v := ts.Value.(bool) 517 if v { 518 stmt.WriteString("1") 519 } else { 520 stmt.WriteString("0") 521 } 522 case reflect.Int: 523 stmt.WriteString(strconv.FormatInt(int64(ts.Value.(int)), 10)) 524 case reflect.Int8: 525 stmt.WriteString(strconv.FormatInt(int64(ts.Value.(int8)), 10)) 526 case reflect.Int16: 527 stmt.WriteString(strconv.FormatInt(int64(ts.Value.(int16)), 10)) 528 case reflect.Int32: 529 stmt.WriteString(strconv.FormatInt(int64(ts.Value.(int32)), 10)) 530 case reflect.Int64: 531 stmt.WriteString(strconv.FormatInt(ts.Value.(int64), 10)) 532 case reflect.Uint: 533 stmt.WriteString(strconv.FormatUint(uint64(ts.Value.(uint)), 10)) 534 case reflect.Uint8: 535 stmt.WriteString(strconv.FormatUint(uint64(ts.Value.(uint8)), 10)) 536 case reflect.Uint16: 537 stmt.WriteString(strconv.FormatUint(uint64(ts.Value.(uint16)), 10)) 538 case reflect.Uint32: 539 stmt.WriteString(strconv.FormatUint(uint64(ts.Value.(uint32)), 10)) 540 case reflect.Uint64: 541 stmt.WriteString(strconv.FormatUint(ts.Value.(uint64), 10)) 542 case reflect.Float32: 543 stmt.WriteString(strconv.FormatFloat(float64(ts.Value.(float32)), 'e', -1, 64)) 544 case reflect.Float64: 545 stmt.WriteString(strconv.FormatFloat(ts.Value.(float64), 'e', -1, 64)) 546 } 547 return 548 } 549 550 // BuildSelectStmt : 551 func (b *mySQLBuilder) BuildSelectStmt(stmt sqlstmt.Stmt, it interface{}) error { 552 x := it.(*sql.SelectStmt) 553 stmt.WriteString("SELECT ") 554 if x.DistinctOn { 555 stmt.WriteString("DISTINCT ") 556 } 557 if err := b.appendSelect(stmt, x.Projections); err != nil { 558 return err 559 } 560 stmt.WriteString(" FROM ") 561 if err := b.appendTable(stmt, x.Tables); err != nil { 562 return err 563 } 564 if err := b.appendWhere(stmt, x.Conditions.Values); err != nil { 565 return err 566 } 567 if err := b.appendGroupBy(stmt, x.Groups); err != nil { 568 return err 569 } 570 if err := b.appendOrderBy(stmt, x.Sorts); err != nil { 571 return err 572 } 573 b.appendLimitNOffset(stmt, x.Max, x.Skip) 574 return nil 575 } 576 577 // BuildUpdateStmt : 578 func (b *mySQLBuilder) BuildUpdateStmt(stmt sqlstmt.Stmt, it interface{}) error { 579 x := it.(*sql.UpdateStmt) 580 stmt.WriteString("UPDATE " + b.TableName(x.Database, x.Table) + ` `) 581 if err := b.appendSet(stmt, x.Values); err != nil { 582 return err 583 } 584 if err := b.appendWhere(stmt, x.Conditions.Values); err != nil { 585 return err 586 } 587 if err := b.appendOrderBy(stmt, x.Sorts); err != nil { 588 return err 589 } 590 b.appendLimitNOffset(stmt, x.Max, 0) 591 return nil 592 } 593 594 // BuildFindActions : 595 func (b *mySQLBuilder) BuildFindActions(stmt sqlstmt.Stmt, it interface{}) error { 596 x := it.(*actions.FindActions) 597 x.Table = strings.TrimSpace(x.Table) 598 if x.Table == "" { 599 return errors.New("mysql: empty table name") 600 } 601 stmt.WriteString("SELECT ") 602 if x.DistinctOn { 603 stmt.WriteString("DISTINCT ") 604 } 605 if err := b.appendSelect(stmt, x.Projections); err != nil { 606 return err 607 } 608 stmt.WriteString(" FROM " + b.TableName(x.Database, x.Table)) 609 if err := b.appendWhere(stmt, x.Conditions.Values); err != nil { 610 return err 611 } 612 if err := b.appendGroupBy(stmt, x.GroupBys); err != nil { 613 return err 614 } 615 if err := b.appendOrderBy(stmt, x.Sorts); err != nil { 616 return err 617 } 618 b.appendLimitNOffset(stmt, x.Count, x.Skip) 619 620 return nil 621 } 622 623 // BuildUpdateActions : 624 func (b *mySQLBuilder) BuildUpdateActions(stmt sqlstmt.Stmt, it interface{}) error { 625 x, ok := it.(*actions.UpdateActions) 626 if !ok { 627 return errors.New("data type not match") 628 } 629 stmt.WriteString("UPDATE " + b.TableName(x.Database, x.Table) + ` `) 630 if err := b.appendSet(stmt, x.Values); err != nil { 631 return err 632 } 633 if err := b.appendWhere(stmt, x.Conditions); err != nil { 634 return err 635 } 636 if err := b.appendOrderBy(stmt, x.Sorts); err != nil { 637 return err 638 } 639 b.appendLimitNOffset(stmt, x.Record, 0) 640 return nil 641 } 642 643 // BuildDeleteActions : 644 func (b *mySQLBuilder) BuildDeleteActions(stmt sqlstmt.Stmt, it interface{}) error { 645 x := it.(*actions.DeleteActions) 646 stmt.WriteString("DELETE FROM " + b.TableName(x.Database, x.Table)) 647 if err := b.appendWhere(stmt, x.Conditions); err != nil { 648 return err 649 } 650 if err := b.appendOrderBy(stmt, x.Sorts); err != nil { 651 return err 652 } 653 b.appendLimitNOffset(stmt, x.Record, 0) 654 return nil 655 } 656 657 func (b *mySQLBuilder) getValue(stmt sqlstmt.Stmt, it interface{}) (err error) { 658 v := reflext.ValueOf(it) 659 if !v.IsValid() { 660 stmt.WriteByte('?') 661 stmt.AppendArgs(nil) 662 return 663 } 664 665 t := v.Type() 666 if builder, ok := b.builder.LookupBuilder(t); ok { 667 if err := builder(stmt, it); err != nil { 668 return err 669 } 670 return nil 671 } 672 673 encoder, err := b.registry.LookupEncoder(v) 674 if err != nil { 675 return err 676 } 677 vv, err := encoder(nil, v) 678 if err != nil { 679 return err 680 } 681 // stmt.WriteByte('?') 682 // stmt.AppendArgs(vv) 683 convertSpatial(stmt, vv) 684 return 685 } 686 687 func (b *mySQLBuilder) appendSelect(stmt sqlstmt.Stmt, pjs []interface{}) error { 688 if len(pjs) > 0 { 689 length := len(pjs) 690 for i := 0; i < length; i++ { 691 if i > 0 { 692 stmt.WriteByte(',') 693 } 694 if err := b.builder.BuildStatement(stmt, pjs[i]); err != nil { 695 return err 696 } 697 } 698 return nil 699 } 700 stmt.WriteString("*") 701 return nil 702 } 703 704 func (b *mySQLBuilder) appendTable(stmt sqlstmt.Stmt, fields []interface{}) error { 705 length := len(fields) 706 if length > 0 { 707 for i := 0; i < length; i++ { 708 if i > 0 { 709 stmt.WriteByte(' ') 710 } 711 if err := b.builder.BuildStatement(stmt, fields[i]); err != nil { 712 return err 713 } 714 } 715 } 716 return nil 717 } 718 719 func (b *mySQLBuilder) appendWhere(stmt sqlstmt.Stmt, conds []interface{}) error { 720 length := len(conds) 721 if length > 0 { 722 stmt.WriteString(" WHERE ") 723 for i := 0; i < length; i++ { 724 if err := b.builder.BuildStatement(stmt, conds[i]); err != nil { 725 return err 726 } 727 } 728 } 729 return nil 730 } 731 732 func (b *mySQLBuilder) appendGroupBy(stmt sqlstmt.Stmt, fields []interface{}) error { 733 length := len(fields) 734 if length > 0 { 735 stmt.WriteString(" GROUP BY ") 736 for i := 0; i < length; i++ { 737 if i > 0 { 738 stmt.WriteByte(',') 739 } 740 if err := b.builder.BuildStatement(stmt, fields[i]); err != nil { 741 return err 742 } 743 } 744 } 745 return nil 746 } 747 748 func (b *mySQLBuilder) appendOrderBy(stmt sqlstmt.Stmt, sorts []interface{}) error { 749 length := len(sorts) 750 if length < 1 { 751 return nil 752 } 753 stmt.WriteString(" ORDER BY ") 754 for i := 0; i < length; i++ { 755 if i > 0 { 756 stmt.WriteByte(',') 757 } 758 if err := b.builder.BuildStatement(stmt, sorts[i]); err != nil { 759 return err 760 } 761 } 762 return nil 763 } 764 765 func (b *mySQLBuilder) appendLimitNOffset(stmt sqlstmt.Stmt, limit, offset uint) { 766 if limit > 0 { 767 stmt.WriteString(" LIMIT " + strconv.FormatUint(uint64(limit), 10)) 768 } 769 if offset > 0 { 770 stmt.WriteString(" OFFSET " + strconv.FormatUint(uint64(offset), 10)) 771 } 772 } 773 774 func (b *mySQLBuilder) appendSet(stmt sqlstmt.Stmt, values []primitive.KV) error { 775 length := len(values) 776 if length > 0 { 777 stmt.WriteString("SET ") 778 for i := 0; i < length; i++ { 779 if i > 0 { 780 stmt.WriteByte(',') 781 } 782 if err := b.builder.BuildStatement(stmt, values[i]); err != nil { 783 return err 784 } 785 } 786 } 787 return nil 788 } 789 790 func escapeWildCard(n string) string { 791 length := len(n) - 1 792 if length < 1 { 793 return n 794 } 795 blr := new(strings.Builder) 796 for i := 0; i < length; i++ { 797 switch n[i] { 798 case '%': 799 blr.WriteString(`\%`) 800 case '_': 801 blr.WriteString(`\_`) 802 case '\\': 803 blr.WriteString(`\\`) 804 default: 805 blr.WriteByte(n[i]) 806 } 807 } 808 blr.WriteByte(n[length]) 809 return blr.String() 810 } 811 812 func unmatchedDataType(callback string) error { 813 return errors.New("mysql: invalid data type") 814 }