@@ -230,77 +230,92 @@ func (s *ParsedSetStatement) parseSetTransaction(sp *simpleParser, query string)
230
230
s .IsLocal = true
231
231
s .IsTransaction = true
232
232
233
+ var err error
234
+ s .Identifiers , s .Literals , err = parseTransactionOptions (sp )
235
+ if err != nil {
236
+ return err
237
+ }
238
+ return nil
239
+ }
240
+
241
+ func parseTransactionOptions (sp * simpleParser ) ([]Identifier , []Literal , error ) {
242
+ identifiers := make ([]Identifier , 0 , 2 )
243
+ literals := make ([]Literal , 0 , 2 )
244
+ var err error
233
245
for {
234
246
if sp .peekKeyword ("ISOLATION" ) {
235
- if err := s .parseSetTransactionIsolationLevel (sp , query ); err != nil {
236
- return err
247
+ identifiers , literals , err = parseTransactionIsolationLevel (sp , identifiers , literals )
248
+ if err != nil {
249
+ return nil , nil , err
237
250
}
238
251
} else if sp .peekKeyword ("READ" ) {
239
- if err := s .parseSetTransactionMode (sp , query ); err != nil {
240
- return err
252
+ identifiers , literals , err = parseTransactionMode (sp , identifiers , literals )
253
+ if err != nil {
254
+ return nil , nil , err
241
255
}
242
256
} else if sp .statementParser .Dialect == databasepb .DatabaseDialect_POSTGRESQL && (sp .peekKeyword ("DEFERRABLE" ) || sp .peekKeyword ("NOT" )) {
243
257
// https://www.postgresql.org/docs/current/sql-set-transaction.html
244
- if err := s .parseSetTransactionDeferrable (sp , query ); err != nil {
245
- return err
258
+ identifiers , literals , err = parseTransactionDeferrable (sp , identifiers , literals )
259
+ if err != nil {
260
+ return nil , nil , err
246
261
}
247
262
} else {
248
- return status .Error (codes .InvalidArgument , "invalid TRANSACTION option, expected one of ISOLATION LEVEL, READ WRITE, or READ ONLY" )
263
+ return nil , nil , status .Error (codes .InvalidArgument , "invalid TRANSACTION option, expected one of ISOLATION LEVEL, READ WRITE, or READ ONLY" )
249
264
}
250
265
if ! sp .hasMoreTokens () {
251
- return nil
266
+ return identifiers , literals , nil
252
267
}
253
268
// Eat and ignore any commas separating the various options.
254
269
sp .eatToken (',' )
255
270
}
256
271
}
257
272
258
- func ( s * ParsedSetStatement ) parseSetTransactionIsolationLevel ( sp * simpleParser , query string ) error {
273
+ func parseTransactionIsolationLevel ( sp * simpleParser , identifiers [] Identifier , literals [] Literal ) ([] Identifier , [] Literal , error ) {
259
274
if ! sp .eatKeywords ([]string {"ISOLATION" , "LEVEL" }) {
260
- return status .Errorf (codes .InvalidArgument , "syntax error: expected ISOLATION LEVEL" )
275
+ return nil , nil , status .Errorf (codes .InvalidArgument , "syntax error: expected ISOLATION LEVEL" )
261
276
}
262
277
var value Literal
263
278
if sp .eatKeyword ("SERIALIZABLE" ) {
264
279
value = Literal {Value : "serializable" }
265
280
} else if sp .eatKeywords ([]string {"REPEATABLE" , "READ" }) {
266
281
value = Literal {Value : "repeatable_read" }
267
282
} else {
268
- return status .Errorf (codes .InvalidArgument , "syntax error: expected SERIALIZABLE OR REPETABLE READ" )
283
+ return nil , nil , status .Errorf (codes .InvalidArgument , "syntax error: expected SERIALIZABLE OR REPETABLE READ" )
269
284
}
270
285
271
- s . Identifiers = append (s . Identifiers , Identifier {Parts : []string {"isolation_level" }})
272
- s . Literals = append (s . Literals , value )
273
- return nil
286
+ identifiers = append (identifiers , Identifier {Parts : []string {"isolation_level" }})
287
+ literals = append (literals , value )
288
+ return identifiers , literals , nil
274
289
}
275
290
276
- func ( s * ParsedSetStatement ) parseSetTransactionMode ( sp * simpleParser , query string ) error {
291
+ func parseTransactionMode ( sp * simpleParser , identifiers [] Identifier , literals [] Literal ) ([] Identifier , [] Literal , error ) {
277
292
readOnly := false
278
293
if sp .eatKeywords ([]string {"READ" , "ONLY" }) {
279
294
readOnly = true
280
295
} else if sp .eatKeywords ([]string {"READ" , "WRITE" }) {
281
296
readOnly = false
282
297
} else {
283
- return status .Errorf (codes .InvalidArgument , "syntax error: expected READ ONLY or READ WRITE" )
298
+ return nil , nil , status .Errorf (codes .InvalidArgument , "syntax error: expected READ ONLY or READ WRITE" )
284
299
}
285
300
286
- s . Identifiers = append (s . Identifiers , Identifier {Parts : []string {"transaction_read_only" }})
287
- s . Literals = append (s . Literals , Literal {Value : fmt .Sprintf ("%v" , readOnly )})
288
- return nil
301
+ identifiers = append (identifiers , Identifier {Parts : []string {"transaction_read_only" }})
302
+ literals = append (literals , Literal {Value : fmt .Sprintf ("%v" , readOnly )})
303
+ return identifiers , literals , nil
289
304
}
290
305
291
- func ( s * ParsedSetStatement ) parseSetTransactionDeferrable ( sp * simpleParser , query string ) error {
306
+ func parseTransactionDeferrable ( sp * simpleParser , identifiers [] Identifier , literals [] Literal ) ([] Identifier , [] Literal , error ) {
292
307
deferrable := false
293
308
if sp .eatKeywords ([]string {"NOT" , "DEFERRABLE" }) {
294
309
deferrable = false
295
310
} else if sp .eatKeyword ("DEFERRABLE" ) {
296
311
deferrable = true
297
312
} else {
298
- return status .Errorf (codes .InvalidArgument , "syntax error: expected [NOT] DEFERRABLE" )
313
+ return nil , nil , status .Errorf (codes .InvalidArgument , "syntax error: expected [NOT] DEFERRABLE" )
299
314
}
300
315
301
- s . Identifiers = append (s . Identifiers , Identifier {Parts : []string {"transaction_deferrable" }})
302
- s . Literals = append (s . Literals , Literal {Value : fmt .Sprintf ("%v" , deferrable )})
303
- return nil
316
+ identifiers = append (identifiers , Identifier {Parts : []string {"transaction_deferrable" }})
317
+ literals = append (literals , Literal {Value : fmt .Sprintf ("%v" , deferrable )})
318
+ return identifiers , literals , nil
304
319
}
305
320
306
321
// ParsedResetStatement is a statement of the form
@@ -496,6 +511,12 @@ func (s *ParsedAbortBatchStatement) parse(parser *StatementParser, query string)
496
511
497
512
type ParsedBeginStatement struct {
498
513
query string
514
+ // Identifiers contains the transaction properties that were included in the BEGIN statement. E.g. the statement
515
+ // BEGIN TRANSACTION READ ONLY contains the transaction property 'transaction_read_only'.
516
+ Identifiers []Identifier
517
+ // Literals contains the transaction property values that were included in the BEGIN statement. E.g. the statement
518
+ // BEGIN TRANSACTION READ ONLY contains the value 'true' for the property 'transaction_read_only'.
519
+ Literals []Literal
499
520
}
500
521
501
522
func (s * ParsedBeginStatement ) Name () string {
@@ -508,7 +529,7 @@ func (s *ParsedBeginStatement) Query() string {
508
529
509
530
func (s * ParsedBeginStatement ) parse (parser * StatementParser , query string ) error {
510
531
// Parse a statement of the form
511
- // GoogleSQL: BEGIN [TRANSACTION]
532
+ // GoogleSQL: BEGIN [TRANSACTION] [READ WRITE | READ ONLY | ISOLATION LEVEL {SERIALIZABLE | READ COMMITTED}]
512
533
// PostgreSQL: {START | BEGIN} [{TRANSACTION | WORK}] (https://www.postgresql.org/docs/current/sql-begin.html)
513
534
// TODO: Support transaction modes in the BEGIN / START statement.
514
535
sp := & simpleParser {sql : []byte (query ), statementParser : parser }
@@ -531,8 +552,13 @@ func (s *ParsedBeginStatement) parse(parser *StatementParser, query string) erro
531
552
}
532
553
533
554
if sp .hasMoreTokens () {
534
- return status .Errorf (codes .InvalidArgument , "unexpected tokens at position %d in %q" , sp .pos , sp .sql )
555
+ var err error
556
+ s .Identifiers , s .Literals , err = parseTransactionOptions (sp )
557
+ if err != nil {
558
+ return err
559
+ }
535
560
}
561
+
536
562
s .query = query
537
563
return nil
538
564
}
0 commit comments