@@ -406,25 +406,29 @@ func buildUniqueKeyMinMaxValuesPreparedQuery(databaseName, tableName string, uni
406
406
return query , nil
407
407
}
408
408
409
- func BuildDMLDeleteQuery (databaseName , tableName string , tableColumns , uniqueKeyColumns * ColumnList , args []interface {}) (result string , uniqueKeyArgs []interface {}, err error ) {
410
- if len (args ) != tableColumns .Len () {
411
- return result , uniqueKeyArgs , fmt .Errorf ("args count differs from table column count in BuildDMLDeleteQuery" )
412
- }
409
+ // DMLDeleteQueryBuilder can build DELETE queries for DML events.
410
+ // It holds the prepared query statement so it doesn't need to be recreated every time.
411
+ type DMLDeleteQueryBuilder struct {
412
+ tableColumns , uniqueKeyColumns * ColumnList
413
+ preparedStatement string
414
+ }
415
+
416
+ // NewDMLDeleteQueryBuilder creates a new DMLDeleteQueryBuilder.
417
+ // It prepares the DELETE query statement.
418
+ // Returns an error if no unique key columns are given
419
+ // or the prepared statement cannot be built.
420
+ func NewDMLDeleteQueryBuilder (databaseName , tableName string , tableColumns , uniqueKeyColumns * ColumnList ) (* DMLDeleteQueryBuilder , error ) {
413
421
if uniqueKeyColumns .Len () == 0 {
414
- return result , uniqueKeyArgs , fmt .Errorf ("No unique key columns found in BuildDMLDeleteQuery" )
415
- }
416
- for _ , column := range uniqueKeyColumns .Columns () {
417
- tableOrdinal := tableColumns .Ordinals [column .Name ]
418
- arg := column .convertArg (args [tableOrdinal ], true )
419
- uniqueKeyArgs = append (uniqueKeyArgs , arg )
422
+ return nil , fmt .Errorf ("no unique key columns found in NewDMLDeleteQueryBuilder" )
420
423
}
421
424
databaseName = EscapeName (databaseName )
422
425
tableName = EscapeName (tableName )
423
426
equalsComparison , err := BuildEqualsPreparedComparison (uniqueKeyColumns .Names ())
424
427
if err != nil {
425
- return result , uniqueKeyArgs , err
428
+ return nil , err
426
429
}
427
- result = fmt .Sprintf (`
430
+
431
+ stmt := fmt .Sprintf (`
428
432
delete /* gh-ost %s.%s */
429
433
from
430
434
%s.%s
@@ -434,35 +438,58 @@ func BuildDMLDeleteQuery(databaseName, tableName string, tableColumns, uniqueKey
434
438
databaseName , tableName ,
435
439
equalsComparison ,
436
440
)
437
- return result , uniqueKeyArgs , nil
441
+
442
+ b := & DMLDeleteQueryBuilder {
443
+ tableColumns : tableColumns ,
444
+ uniqueKeyColumns : uniqueKeyColumns ,
445
+ preparedStatement : stmt ,
446
+ }
447
+ return b , nil
438
448
}
439
449
440
- func BuildDMLInsertQuery (databaseName , tableName string , tableColumns , sharedColumns , mappedSharedColumns * ColumnList , args []interface {}) (result string , sharedArgs []interface {}, err error ) {
441
- if len (args ) != tableColumns .Len () {
442
- return result , args , fmt .Errorf ("args count differs from table column count in BuildDMLInsertQuery" )
450
+ // BuildQuery builds the arguments array for a DML event DELETE query.
451
+ // It returns the query string and the unique key arguments array.
452
+ // Returns an error if the number of arguments is not equal to the number of table columns.
453
+ func (b * DMLDeleteQueryBuilder ) BuildQuery (args []interface {}) (string , []interface {}, error ) {
454
+ if len (args ) != b .tableColumns .Len () {
455
+ return "" , nil , fmt .Errorf ("args count differs from table column count in BuildDMLDeleteQuery" )
443
456
}
457
+ uniqueKeyArgs := make ([]interface {}, 0 , b .uniqueKeyColumns .Len ())
458
+ for _ , column := range b .uniqueKeyColumns .Columns () {
459
+ tableOrdinal := b .tableColumns .Ordinals [column .Name ]
460
+ arg := column .convertArg (args [tableOrdinal ], true )
461
+ uniqueKeyArgs = append (uniqueKeyArgs , arg )
462
+ }
463
+ return b .preparedStatement , uniqueKeyArgs , nil
464
+ }
465
+
466
+ // DMLInsertQueryBuilder can build INSERT queries for DML events.
467
+ // It holds the prepared query statement so it doesn't need to be recreated every time.
468
+ type DMLInsertQueryBuilder struct {
469
+ tableColumns , sharedColumns * ColumnList
470
+ preparedStatement string
471
+ }
472
+
473
+ // NewDMLInsertQueryBuilder creates a new DMLInsertQueryBuilder.
474
+ // It prepares the INSERT query statement.
475
+ // Returns an error if no shared columns are given, the shared columns are not a subset of the table columns,
476
+ // or the prepared statement cannot be built.
477
+ func NewDMLInsertQueryBuilder (databaseName , tableName string , tableColumns , sharedColumns , mappedSharedColumns * ColumnList ) (* DMLInsertQueryBuilder , error ) {
444
478
if ! sharedColumns .IsSubsetOf (tableColumns ) {
445
- return result , args , fmt .Errorf ("shared columns is not a subset of table columns in BuildDMLInsertQuery " )
479
+ return nil , fmt .Errorf ("shared columns is not a subset of table columns in NewDMLInsertQueryBuilder " )
446
480
}
447
481
if sharedColumns .Len () == 0 {
448
- return result , args , fmt .Errorf ("No shared columns found in BuildDMLInsertQuery " )
482
+ return nil , fmt .Errorf ("no shared columns found in NewDMLInsertQueryBuilder " )
449
483
}
450
484
databaseName = EscapeName (databaseName )
451
485
tableName = EscapeName (tableName )
452
-
453
- for _ , column := range sharedColumns .Columns () {
454
- tableOrdinal := tableColumns .Ordinals [column .Name ]
455
- arg := column .convertArg (args [tableOrdinal ], false )
456
- sharedArgs = append (sharedArgs , arg )
457
- }
458
-
459
486
mappedSharedColumnNames := duplicateNames (mappedSharedColumns .Names ())
460
487
for i := range mappedSharedColumnNames {
461
488
mappedSharedColumnNames [i ] = EscapeName (mappedSharedColumnNames [i ])
462
489
}
463
490
preparedValues := buildColumnsPreparedValues (mappedSharedColumns )
464
491
465
- result = fmt .Sprintf (`
492
+ stmt : = fmt .Sprintf (`
466
493
replace /* gh-ost %s.%s */
467
494
into
468
495
%s.%s
@@ -474,53 +501,63 @@ func BuildDMLInsertQuery(databaseName, tableName string, tableColumns, sharedCol
474
501
strings .Join (mappedSharedColumnNames , ", " ),
475
502
strings .Join (preparedValues , ", " ),
476
503
)
477
- return result , sharedArgs , nil
504
+
505
+ return & DMLInsertQueryBuilder {
506
+ tableColumns : tableColumns ,
507
+ sharedColumns : sharedColumns ,
508
+ preparedStatement : stmt ,
509
+ }, nil
478
510
}
479
511
480
- func BuildDMLUpdateQuery (databaseName , tableName string , tableColumns , sharedColumns , mappedSharedColumns , uniqueKeyColumns * ColumnList , valueArgs , whereArgs []interface {}) (result string , sharedArgs , uniqueKeyArgs []interface {}, err error ) {
481
- if len (valueArgs ) != tableColumns .Len () {
482
- return result , sharedArgs , uniqueKeyArgs , fmt .Errorf ("value args count differs from table column count in BuildDMLUpdateQuery" )
512
+ // BuildQuery builds the arguments array for a DML event INSERT query.
513
+ // It returns the query string and the shared arguments array.
514
+ // Returns an error if the number of arguments differs from the number of table columns.
515
+ func (b * DMLInsertQueryBuilder ) BuildQuery (args []interface {}) (string , []interface {}, error ) {
516
+ if len (args ) != b .tableColumns .Len () {
517
+ return "" , nil , fmt .Errorf ("args count differs from table column count in BuildDMLInsertQuery" )
483
518
}
484
- if len (whereArgs ) != tableColumns .Len () {
485
- return result , sharedArgs , uniqueKeyArgs , fmt .Errorf ("where args count differs from table column count in BuildDMLUpdateQuery" )
519
+ sharedArgs := make ([]interface {}, 0 , b .sharedColumns .Len ())
520
+ for _ , column := range b .sharedColumns .Columns () {
521
+ tableOrdinal := b .tableColumns .Ordinals [column .Name ]
522
+ arg := column .convertArg (args [tableOrdinal ], false )
523
+ sharedArgs = append (sharedArgs , arg )
486
524
}
525
+ return b .preparedStatement , sharedArgs , nil
526
+ }
527
+
528
+ // DMLUpdateQueryBuilder can build UPDATE queries for DML events.
529
+ // It holds the prepared query statement so it doesn't need to be recreated every time.
530
+ type DMLUpdateQueryBuilder struct {
531
+ tableColumns , sharedColumns , uniqueKeyColumns * ColumnList
532
+ preparedStatement string
533
+ }
534
+
535
+ // NewDMLUpdateQueryBuilder creates a new DMLUpdateQueryBuilder.
536
+ // It prepares the UPDATE query statement.
537
+ // Returns an error if no shared columns are given, the shared columns are not a subset of the table columns,
538
+ // no unique key columns are given or the prepared statement cannot be built.
539
+ func NewDMLUpdateQueryBuilder (databaseName , tableName string , tableColumns , sharedColumns , mappedSharedColumns , uniqueKeyColumns * ColumnList ) (* DMLUpdateQueryBuilder , error ) {
487
540
if ! sharedColumns .IsSubsetOf (tableColumns ) {
488
- return result , sharedArgs , uniqueKeyArgs , fmt .Errorf ("shared columns is not a subset of table columns in BuildDMLUpdateQuery" )
489
- }
490
- if ! uniqueKeyColumns .IsSubsetOf (sharedColumns ) {
491
- return result , sharedArgs , uniqueKeyArgs , fmt .Errorf ("unique key columns is not a subset of shared columns in BuildDMLUpdateQuery" )
541
+ return nil , fmt .Errorf ("shared columns is not a subset of table columns in NewDMLUpdateQueryBuilder" )
492
542
}
493
543
if sharedColumns .Len () == 0 {
494
- return result , sharedArgs , uniqueKeyArgs , fmt .Errorf ("No shared columns found in BuildDMLUpdateQuery " )
544
+ return nil , fmt .Errorf ("no shared columns found in NewDMLUpdateQueryBuilder " )
495
545
}
496
546
if uniqueKeyColumns .Len () == 0 {
497
- return result , sharedArgs , uniqueKeyArgs , fmt .Errorf ("No unique key columns found in BuildDMLUpdateQuery " )
547
+ return nil , fmt .Errorf ("no unique key columns found in NewDMLUpdateQueryBuilder " )
498
548
}
499
549
databaseName = EscapeName (databaseName )
500
550
tableName = EscapeName (tableName )
501
-
502
- for _ , column := range sharedColumns .Columns () {
503
- tableOrdinal := tableColumns .Ordinals [column .Name ]
504
- arg := column .convertArg (valueArgs [tableOrdinal ], false )
505
- sharedArgs = append (sharedArgs , arg )
506
- }
507
-
508
- for _ , column := range uniqueKeyColumns .Columns () {
509
- tableOrdinal := tableColumns .Ordinals [column .Name ]
510
- arg := column .convertArg (whereArgs [tableOrdinal ], true )
511
- uniqueKeyArgs = append (uniqueKeyArgs , arg )
512
- }
513
-
514
551
setClause , err := BuildSetPreparedClause (mappedSharedColumns )
515
552
if err != nil {
516
- return "" , sharedArgs , uniqueKeyArgs , err
553
+ return nil , err
517
554
}
518
555
519
556
equalsComparison , err := BuildEqualsPreparedComparison (uniqueKeyColumns .Names ())
520
557
if err != nil {
521
- return "" , sharedArgs , uniqueKeyArgs , err
558
+ return nil , err
522
559
}
523
- result = fmt .Sprintf (`
560
+ stmt : = fmt .Sprintf (`
524
561
update /* gh-ost %s.%s */
525
562
%s.%s
526
563
set
@@ -532,5 +569,35 @@ func BuildDMLUpdateQuery(databaseName, tableName string, tableColumns, sharedCol
532
569
setClause ,
533
570
equalsComparison ,
534
571
)
535
- return result , sharedArgs , uniqueKeyArgs , nil
572
+ return & DMLUpdateQueryBuilder {
573
+ tableColumns : tableColumns ,
574
+ sharedColumns : sharedColumns ,
575
+ uniqueKeyColumns : uniqueKeyColumns ,
576
+ preparedStatement : stmt ,
577
+ }, nil
578
+ }
579
+
580
+ // BuildQuery builds the arguments array for a DML event UPDATE query.
581
+ // It returns the query string, the shared arguments array, and the unique key arguments array.
582
+ func (b * DMLUpdateQueryBuilder ) BuildQuery (valueArgs , whereArgs []interface {}) (string , []interface {}, []interface {}, error ) {
583
+ // TODO: move this check back to `NewDMLUpdateQueryBuilder()`, needs fix on generated columns.
584
+ if ! b .uniqueKeyColumns .IsSubsetOf (b .sharedColumns ) {
585
+ return "" , nil , nil , fmt .Errorf ("unique key columns is not a subset of shared columns in DMLUpdateQueryBuilder" )
586
+ }
587
+
588
+ sharedArgs := make ([]interface {}, 0 , b .sharedColumns .Len ())
589
+ for _ , column := range b .sharedColumns .Columns () {
590
+ tableOrdinal := b .tableColumns .Ordinals [column .Name ]
591
+ arg := column .convertArg (valueArgs [tableOrdinal ], false )
592
+ sharedArgs = append (sharedArgs , arg )
593
+ }
594
+
595
+ uniqueKeyArgs := make ([]interface {}, 0 , b .uniqueKeyColumns .Len ())
596
+ for _ , column := range b .uniqueKeyColumns .Columns () {
597
+ tableOrdinal := b .tableColumns .Ordinals [column .Name ]
598
+ arg := column .convertArg (whereArgs [tableOrdinal ], true )
599
+ uniqueKeyArgs = append (uniqueKeyArgs , arg )
600
+ }
601
+
602
+ return b .preparedStatement , sharedArgs , uniqueKeyArgs , nil
536
603
}
0 commit comments