@@ -25,6 +25,7 @@ import (
25
25
"github.com/cockroachdb/cockroach/pkg/sql/scanner"
26
26
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
27
27
"github.com/cockroachdb/cockroach/pkg/sql/types"
28
+ "github.com/cockroachdb/cockroach/pkg/util/buildutil"
28
29
"github.com/cockroachdb/errors"
29
30
)
30
31
@@ -47,6 +48,7 @@ type Parser struct {
47
48
type ParseOptions struct {
48
49
intType * types.T
49
50
retainComments bool
51
+ numAnnotations * tree.AnnotationIdx
50
52
}
51
53
52
54
var DefaultParseOptions = ParseOptions {
@@ -64,6 +66,18 @@ func (po ParseOptions) WithIntType(t *types.T) ParseOptions {
64
66
return po
65
67
}
66
68
69
+ // WithNumAnnotations overrides how annotations are handled. If this option is
70
+ // used, then
71
+ // - the given integer indicates the number of annotations already claimed, and
72
+ // - if multiple stmts are parsed, then unique annotation indexes are used
73
+ // across all stmts.
74
+ //
75
+ // When this option is not used, then each stmt is parsed indepedently.
76
+ func (po ParseOptions ) WithNumAnnotations (numAnnotations tree.AnnotationIdx ) ParseOptions {
77
+ po .numAnnotations = & numAnnotations
78
+ return po
79
+ }
80
+
67
81
// INT8 is the historical interpretation of INT. This should be left
68
82
// alone in the future, since there are many sql fragments stored
69
83
// in various descriptors. Any user input that was created after
@@ -168,14 +182,29 @@ func (p *Parser) parseWithDepth(
168
182
p .scanner .RetainComments ()
169
183
}
170
184
defer p .scanner .Cleanup ()
185
+ var numAnnotations tree.AnnotationIdx
186
+ if options .numAnnotations != nil {
187
+ numAnnotations = * options .numAnnotations
188
+ }
171
189
for {
172
190
sql , tokens , done := p .scanOneStmt ()
173
- stmt , err := p .parse (depth + 1 , sql , tokens , options .intType )
191
+ stmt , err := p .parse (depth + 1 , sql , tokens , options .intType , numAnnotations )
174
192
if err != nil {
175
193
return nil , err
176
194
}
177
195
if stmt .AST != nil {
178
196
stmts = append (stmts , stmt )
197
+ if options .numAnnotations != nil {
198
+ if buildutil .CrdbTestBuild && numAnnotations > stmt .NumAnnotations {
199
+ return nil , errors .AssertionFailedf (
200
+ "annotation index has regressed: numAnnotations=%d, stmt.NumAnnotations=%d " ,
201
+ numAnnotations , stmt .NumAnnotations ,
202
+ )
203
+ }
204
+ // If this stmt used any annotations, we need to advance the
205
+ // number of annotations accordingly.
206
+ numAnnotations = stmt .NumAnnotations
207
+ }
179
208
}
180
209
if done {
181
210
break
@@ -186,9 +215,13 @@ func (p *Parser) parseWithDepth(
186
215
187
216
// parse parses a statement from the given scanned tokens.
188
217
func (p * Parser ) parse (
189
- depth int , sql string , tokens []sqlSymType , nakedIntType * types.T ,
218
+ depth int ,
219
+ sql string ,
220
+ tokens []sqlSymType ,
221
+ nakedIntType * types.T ,
222
+ numAnnotations tree.AnnotationIdx ,
190
223
) (statements.Statement [tree.Statement ], error ) {
191
- p .lexer .init (sql , tokens , nakedIntType )
224
+ p .lexer .init (sql , tokens , nakedIntType , numAnnotations )
192
225
defer p .lexer .cleanup ()
193
226
if p .parserImpl .Parse (& p .lexer ) != 0 {
194
227
if p .lexer .lastError == nil {
@@ -371,27 +404,32 @@ func ParseTablePattern(sql string) (tree.TablePattern, error) {
371
404
// the results are undefined if the string contains invalid SQL
372
405
// syntax.
373
406
func ParseExprs (exprs []string ) (tree.Exprs , error ) {
374
- return ParseExprsWithOptions (exprs , DefaultParseOptions )
407
+ res , _ , err := ParseExprsWithOptions (exprs , DefaultParseOptions )
408
+ return res , err
375
409
}
376
410
377
411
// ParseExprsWithOptions parses a comma-delimited sequence of SQL scalar
378
412
// expressions with the provided options. The caller is responsible for
379
413
// ensuring that the input is, in fact, a comma-delimited sequence of SQL
380
414
// scalar expressions — the results are undefined if the string contains
381
415
// invalid SQL syntax.
382
- func ParseExprsWithOptions (exprs []string , opts ParseOptions ) (tree.Exprs , error ) {
416
+ //
417
+ // It also returns the number of annotations used.
418
+ func ParseExprsWithOptions (
419
+ exprs []string , opts ParseOptions ,
420
+ ) (tree.Exprs , tree.AnnotationIdx , error ) {
383
421
if len (exprs ) == 0 {
384
- return tree.Exprs {}, nil
422
+ return tree.Exprs {}, 0 , nil
385
423
}
386
424
stmt , err := ParseOneWithOptions (fmt .Sprintf ("SET ROW (%s)" , strings .Join (exprs , "," )), opts )
387
425
if err != nil {
388
- return nil , err
426
+ return nil , 0 , err
389
427
}
390
428
set , ok := stmt .AST .(* tree.SetVar )
391
429
if ! ok {
392
- return nil , errors .AssertionFailedf ("expected a SET statement, but found %T" , stmt )
430
+ return nil , 0 , errors .AssertionFailedf ("expected a SET statement, but found %T" , stmt )
393
431
}
394
- return set .Values , nil
432
+ return set .Values , stmt . NumAnnotations , nil
395
433
}
396
434
397
435
// ParseExpr parses a SQL scalar expression. The caller is responsible
0 commit comments