@@ -406,25 +406,29 @@ func buildUniqueKeyMinMaxValuesPreparedQuery(databaseName, tableName string, uni
406406 return query , nil
407407}
408408
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 ) {
413421 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" )
420423 }
421424 databaseName = EscapeName (databaseName )
422425 tableName = EscapeName (tableName )
423426 equalsComparison , err := BuildEqualsPreparedComparison (uniqueKeyColumns .Names ())
424427 if err != nil {
425- return result , uniqueKeyArgs , err
428+ return nil , err
426429 }
427- result = fmt .Sprintf (`
430+
431+ stmt := fmt .Sprintf (`
428432 delete /* gh-ost %s.%s */
429433 from
430434 %s.%s
@@ -434,35 +438,58 @@ func BuildDMLDeleteQuery(databaseName, tableName string, tableColumns, uniqueKey
434438 databaseName , tableName ,
435439 equalsComparison ,
436440 )
437- return result , uniqueKeyArgs , nil
441+
442+ b := & DMLDeleteQueryBuilder {
443+ tableColumns : tableColumns ,
444+ uniqueKeyColumns : uniqueKeyColumns ,
445+ preparedStatement : stmt ,
446+ }
447+ return b , nil
438448}
439449
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" )
443456 }
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 ) {
444478 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 " )
446480 }
447481 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 " )
449483 }
450484 databaseName = EscapeName (databaseName )
451485 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-
459486 mappedSharedColumnNames := duplicateNames (mappedSharedColumns .Names ())
460487 for i := range mappedSharedColumnNames {
461488 mappedSharedColumnNames [i ] = EscapeName (mappedSharedColumnNames [i ])
462489 }
463490 preparedValues := buildColumnsPreparedValues (mappedSharedColumns )
464491
465- result = fmt .Sprintf (`
492+ stmt : = fmt .Sprintf (`
466493 replace /* gh-ost %s.%s */
467494 into
468495 %s.%s
@@ -474,53 +501,63 @@ func BuildDMLInsertQuery(databaseName, tableName string, tableColumns, sharedCol
474501 strings .Join (mappedSharedColumnNames , ", " ),
475502 strings .Join (preparedValues , ", " ),
476503 )
477- return result , sharedArgs , nil
504+
505+ return & DMLInsertQueryBuilder {
506+ tableColumns : tableColumns ,
507+ sharedColumns : sharedColumns ,
508+ preparedStatement : stmt ,
509+ }, nil
478510}
479511
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" )
483518 }
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 )
486524 }
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 ) {
487540 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" )
492542 }
493543 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 " )
495545 }
496546 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 " )
498548 }
499549 databaseName = EscapeName (databaseName )
500550 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-
514551 setClause , err := BuildSetPreparedClause (mappedSharedColumns )
515552 if err != nil {
516- return "" , sharedArgs , uniqueKeyArgs , err
553+ return nil , err
517554 }
518555
519556 equalsComparison , err := BuildEqualsPreparedComparison (uniqueKeyColumns .Names ())
520557 if err != nil {
521- return "" , sharedArgs , uniqueKeyArgs , err
558+ return nil , err
522559 }
523- result = fmt .Sprintf (`
560+ stmt : = fmt .Sprintf (`
524561 update /* gh-ost %s.%s */
525562 %s.%s
526563 set
@@ -532,5 +569,35 @@ func BuildDMLUpdateQuery(databaseName, tableName string, tableColumns, sharedCol
532569 setClause ,
533570 equalsComparison ,
534571 )
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
536603}
0 commit comments