@@ -30,6 +30,12 @@ func parseStatement(parser *statementParser, keyword, query string) (parsedState
3030 stmt = & parsedCreateDatabaseStatement {}
3131 } else if isDropKeyword (keyword ) && isDropDatabase (parser , query ) {
3232 stmt = & parsedDropDatabaseStatement {}
33+ } else if isStartStatementKeyword (keyword ) {
34+ stmt = & parsedStartBatchStatement {}
35+ } else if isRunStatementKeyword (keyword ) {
36+ stmt = & parsedRunBatchStatement {}
37+ } else if isAbortStatementKeyword (keyword ) {
38+ stmt = & parsedAbortBatchStatement {}
3339 } else {
3440 return nil , nil
3541 }
@@ -400,3 +406,141 @@ func (s *parsedDropDatabaseStatement) executableStatement(c *conn) *executableCl
400406 },
401407 }
402408}
409+
410+ type parsedStartBatchStatement struct {
411+ query string
412+ tp batchType
413+ }
414+
415+ func (s * parsedStartBatchStatement ) parse (parser * statementParser , query string ) error {
416+ // Parse a statement of the form
417+ // START BATCH {DDL | DML}
418+ sp := & simpleParser {sql : []byte (query ), statementParser : parser }
419+ if ! sp .eatKeywords ([]string {"START" , "BATCH" }) {
420+ return status .Error (codes .InvalidArgument , "statement does not start with START BATCH" )
421+ }
422+ if _ , ok := sp .eatKeyword ("DML" ); ok {
423+ s .tp = dml
424+ } else if _ , ok := sp .eatKeyword ("DDL" ); ok {
425+ s .tp = ddl
426+ } else {
427+ return status .Errorf (codes .InvalidArgument , "unexpected token at pos %d in %q, expected DML or DDL" , sp .pos , sp .sql )
428+ }
429+ if sp .hasMoreTokens () {
430+ return status .Errorf (codes .InvalidArgument , "unexpected tokens at position %d in %q" , sp .pos , sp .sql )
431+ }
432+ s .query = query
433+ return nil
434+ }
435+
436+ func (s * parsedStartBatchStatement ) execContext (ctx context.Context , c * conn , params string , opts * ExecOptions , args []driver.NamedValue ) (driver.Result , error ) {
437+ switch s .tp {
438+ case dml :
439+ return c .startBatchDML ( /*automatic = */ false )
440+ case ddl :
441+ return c .startBatchDDL ()
442+ default :
443+ return nil , status .Errorf (codes .FailedPrecondition , "unknown batch type: %v" , s .tp )
444+ }
445+ }
446+
447+ func (s * parsedStartBatchStatement ) queryContext (ctx context.Context , c * conn , params string , opts * ExecOptions , args []driver.NamedValue ) (driver.Rows , error ) {
448+ if _ , err := s .execContext (ctx , c , params , opts , args ); err != nil {
449+ return nil , err
450+ }
451+ return createEmptyRows (opts ), nil
452+ }
453+
454+ func (s * parsedStartBatchStatement ) executableStatement (c * conn ) * executableClientSideStatement {
455+ return & executableClientSideStatement {
456+ conn : c ,
457+ query : s .query ,
458+ clientSideStatement : & clientSideStatement {
459+ Name : "START BATCH" ,
460+ execContext : s .execContext ,
461+ queryContext : s .queryContext ,
462+ },
463+ }
464+ }
465+
466+ type parsedRunBatchStatement struct {
467+ query string
468+ }
469+
470+ func (s * parsedRunBatchStatement ) parse (parser * statementParser , query string ) error {
471+ // Parse a statement of the form
472+ // RUN BATCH
473+ sp := & simpleParser {sql : []byte (query ), statementParser : parser }
474+ if ! sp .eatKeywords ([]string {"RUN" , "BATCH" }) {
475+ return status .Error (codes .InvalidArgument , "statement does not start with RUN BATCH" )
476+ }
477+ if sp .hasMoreTokens () {
478+ return status .Errorf (codes .InvalidArgument , "unexpected tokens at position %d in %q" , sp .pos , sp .sql )
479+ }
480+ s .query = query
481+ return nil
482+ }
483+
484+ func (s * parsedRunBatchStatement ) execContext (ctx context.Context , c * conn , params string , opts * ExecOptions , args []driver.NamedValue ) (driver.Result , error ) {
485+ return c .runBatch (ctx )
486+ }
487+
488+ func (s * parsedRunBatchStatement ) queryContext (ctx context.Context , c * conn , params string , opts * ExecOptions , args []driver.NamedValue ) (driver.Rows , error ) {
489+ if _ , err := s .execContext (ctx , c , params , opts , args ); err != nil {
490+ return nil , err
491+ }
492+ return createEmptyRows (opts ), nil
493+ }
494+
495+ func (s * parsedRunBatchStatement ) executableStatement (c * conn ) * executableClientSideStatement {
496+ return & executableClientSideStatement {
497+ conn : c ,
498+ query : s .query ,
499+ clientSideStatement : & clientSideStatement {
500+ Name : "RUN BATCH" ,
501+ execContext : s .execContext ,
502+ queryContext : s .queryContext ,
503+ },
504+ }
505+ }
506+
507+ type parsedAbortBatchStatement struct {
508+ query string
509+ }
510+
511+ func (s * parsedAbortBatchStatement ) parse (parser * statementParser , query string ) error {
512+ // Parse a statement of the form
513+ // ABORT BATCH
514+ sp := & simpleParser {sql : []byte (query ), statementParser : parser }
515+ if ! sp .eatKeywords ([]string {"ABORT" , "BATCH" }) {
516+ return status .Error (codes .InvalidArgument , "statement does not start with ABORT BATCH" )
517+ }
518+ if sp .hasMoreTokens () {
519+ return status .Errorf (codes .InvalidArgument , "unexpected tokens at position %d in %q" , sp .pos , sp .sql )
520+ }
521+ s .query = query
522+ return nil
523+ }
524+
525+ func (s * parsedAbortBatchStatement ) execContext (ctx context.Context , c * conn , params string , opts * ExecOptions , args []driver.NamedValue ) (driver.Result , error ) {
526+ return c .abortBatch ()
527+ }
528+
529+ func (s * parsedAbortBatchStatement ) queryContext (ctx context.Context , c * conn , params string , opts * ExecOptions , args []driver.NamedValue ) (driver.Rows , error ) {
530+ if _ , err := s .execContext (ctx , c , params , opts , args ); err != nil {
531+ return nil , err
532+ }
533+ return createEmptyRows (opts ), nil
534+ }
535+
536+ func (s * parsedAbortBatchStatement ) executableStatement (c * conn ) * executableClientSideStatement {
537+ return & executableClientSideStatement {
538+ conn : c ,
539+ query : s .query ,
540+ clientSideStatement : & clientSideStatement {
541+ Name : "ABORT BATCH" ,
542+ execContext : s .execContext ,
543+ queryContext : s .queryContext ,
544+ },
545+ }
546+ }
0 commit comments