github.com/cockroachdb/cockroachdb-parser@v0.23.3-0.20240213214944-911057d40c9a/patches/0005-delete-plpgsql-files.patch (about) 1 From 6f5dc3ecb62864562a1a715962e4c70d0e19c91e Mon Sep 17 00:00:00 2001 2 From: Jeremy Yang <jyang@cockroachlabs.com> 3 Date: Mon, 12 Feb 2024 13:19:27 -0800 4 Subject: [PATCH] delete plpgsql files 5 6 --- 7 pkg/sql/plpgsql/parser/lexbase/keywords.go | 356 ----- 8 pkg/sql/plpgsql/parser/lexbase/tokens.go | 134 -- 9 pkg/sql/plpgsql/parser/lexbase/utils.go | 12 - 10 pkg/sql/plpgsql/parser/lexer.go | 501 ------ 11 pkg/sql/plpgsql/parser/parse.go | 136 -- 12 pkg/sql/plpgsql/parser/plpgsql.y | 1647 -------------------- 13 pkg/sql/scanner/plpgsql_scan.go | 246 --- 14 7 files changed, 3032 deletions(-) 15 delete mode 100644 pkg/sql/plpgsql/parser/lexbase/keywords.go 16 delete mode 100644 pkg/sql/plpgsql/parser/lexbase/tokens.go 17 delete mode 100644 pkg/sql/plpgsql/parser/lexbase/utils.go 18 delete mode 100644 pkg/sql/plpgsql/parser/lexer.go 19 delete mode 100644 pkg/sql/plpgsql/parser/parse.go 20 delete mode 100644 pkg/sql/plpgsql/parser/plpgsql.y 21 delete mode 100644 pkg/sql/scanner/plpgsql_scan.go 22 23 diff --git a/pkg/sql/plpgsql/parser/lexbase/keywords.go b/pkg/sql/plpgsql/parser/lexbase/keywords.go 24 deleted file mode 100644 25 index 8cd3bc1..0000000 26 --- a/pkg/sql/plpgsql/parser/lexbase/keywords.go 27 +++ /dev/null 28 @@ -1,356 +0,0 @@ 29 -// Code generated by pkg/sql/lexbase/allkeywords. DO NOT EDIT. 30 - 31 -package lexbase 32 - 33 -var KeywordsCategories = map[string]string{ 34 -"absolute": "U", 35 -"alias": "U", 36 -"all": "R", 37 -"and": "U", 38 -"array": "U", 39 -"assert": "U", 40 -"backward": "U", 41 -"begin": "R", 42 -"by": "R", 43 -"call": "U", 44 -"case": "R", 45 -"chain": "U", 46 -"close": "U", 47 -"collate": "U", 48 -"column": "U", 49 -"column_name": "U", 50 -"commit": "U", 51 -"constant": "U", 52 -"constraint": "U", 53 -"constraint_name": "U", 54 -"continue": "U", 55 -"current": "U", 56 -"cursor": "U", 57 -"datatype": "U", 58 -"debug": "U", 59 -"declare": "R", 60 -"default": "U", 61 -"detail": "U", 62 -"diagnostics": "U", 63 -"do": "U", 64 -"dump": "U", 65 -"else": "R", 66 -"elsif": "U", 67 -"end": "R", 68 -"end_case": "R", 69 -"end_if": "R", 70 -"errcode": "U", 71 -"error": "U", 72 -"exception": "U", 73 -"execute": "R", 74 -"exit": "U", 75 -"fetch": "U", 76 -"first": "U", 77 -"for": "R", 78 -"foreach": "R", 79 -"forward": "U", 80 -"from": "R", 81 -"get": "U", 82 -"hint": "U", 83 -"if": "R", 84 -"import": "U", 85 -"in": "R", 86 -"info": "U", 87 -"insert": "U", 88 -"into": "R", 89 -"is": "U", 90 -"last": "U", 91 -"log": "U", 92 -"loop": "R", 93 -"merge": "U", 94 -"message": "U", 95 -"message_text": "U", 96 -"move": "U", 97 -"next": "U", 98 -"no": "U", 99 -"not": "R", 100 -"notice": "U", 101 -"no_scroll": "U", 102 -"null": "R", 103 -"open": "U", 104 -"option": "U", 105 -"or": "R", 106 -"perform": "U", 107 -"pg_context": "U", 108 -"pg_datatype_name": "U", 109 -"pg_exception_context": "U", 110 -"pg_exception_detail": "U", 111 -"pg_exception_hint": "U", 112 -"print_strict_params": "U", 113 -"prior": "U", 114 -"query": "U", 115 -"raise": "U", 116 -"relative": "U", 117 -"return": "U", 118 -"returned_sqlstate": "U", 119 -"return_next": "U", 120 -"return_query": "U", 121 -"reverse": "U", 122 -"rollback": "U", 123 -"rowtype": "U", 124 -"row_count": "U", 125 -"schema": "U", 126 -"schema_name": "U", 127 -"scroll": "U", 128 -"slice": "U", 129 -"sqlstate": "U", 130 -"stacked": "U", 131 -"strict": "R", 132 -"table": "U", 133 -"table_name": "U", 134 -"then": "R", 135 -"to": "R", 136 -"type": "U", 137 -"upsert": "U", 138 -"use_column": "U", 139 -"use_variable": "U", 140 -"using": "R", 141 -"variable_conflict": "U", 142 -"warning": "U", 143 -"when": "R", 144 -"while": "R", 145 -} 146 - 147 -// KeywordNames contains all keywords sorted, so that pg_get_keywords returns 148 -// deterministic results. 149 -var KeywordNames = []string{ 150 -"absolute", 151 -"alias", 152 -"all", 153 -"and", 154 -"array", 155 -"assert", 156 -"backward", 157 -"begin", 158 -"by", 159 -"call", 160 -"case", 161 -"chain", 162 -"close", 163 -"collate", 164 -"column", 165 -"column_name", 166 -"commit", 167 -"constant", 168 -"constraint", 169 -"constraint_name", 170 -"continue", 171 -"current", 172 -"cursor", 173 -"datatype", 174 -"debug", 175 -"declare", 176 -"default", 177 -"detail", 178 -"diagnostics", 179 -"do", 180 -"dump", 181 -"else", 182 -"elsif", 183 -"end", 184 -"end_case", 185 -"end_if", 186 -"errcode", 187 -"error", 188 -"exception", 189 -"execute", 190 -"exit", 191 -"fetch", 192 -"first", 193 -"for", 194 -"foreach", 195 -"forward", 196 -"from", 197 -"get", 198 -"hint", 199 -"if", 200 -"import", 201 -"in", 202 -"info", 203 -"insert", 204 -"into", 205 -"is", 206 -"last", 207 -"log", 208 -"loop", 209 -"merge", 210 -"message", 211 -"message_text", 212 -"move", 213 -"next", 214 -"no", 215 -"not", 216 -"notice", 217 -"no_scroll", 218 -"null", 219 -"open", 220 -"option", 221 -"or", 222 -"perform", 223 -"pg_context", 224 -"pg_datatype_name", 225 -"pg_exception_context", 226 -"pg_exception_detail", 227 -"pg_exception_hint", 228 -"print_strict_params", 229 -"prior", 230 -"query", 231 -"raise", 232 -"relative", 233 -"return", 234 -"returned_sqlstate", 235 -"return_next", 236 -"return_query", 237 -"reverse", 238 -"rollback", 239 -"rowtype", 240 -"row_count", 241 -"schema", 242 -"schema_name", 243 -"scroll", 244 -"slice", 245 -"sqlstate", 246 -"stacked", 247 -"strict", 248 -"table", 249 -"table_name", 250 -"then", 251 -"to", 252 -"type", 253 -"upsert", 254 -"use_column", 255 -"use_variable", 256 -"using", 257 -"variable_conflict", 258 -"warning", 259 -"when", 260 -"while", 261 -} 262 - 263 -// GetKeywordID returns the lex id of the SQL keyword k or IDENT if k is 264 -// not a keyword. 265 -func GetKeywordID(k string) int32 { 266 - // The previous implementation generated a map that did a string -> 267 - // id lookup. Various ideas were benchmarked and the implementation below 268 - // was the fastest of those, between 3% and 10% faster (at parsing, so the 269 - // scanning speedup is even more) than the map implementation. 270 - switch k { 271 - case "absolute": return ABSOLUTE 272 - case "alias": return ALIAS 273 - case "all": return ALL 274 - case "and": return AND 275 - case "array": return ARRAY 276 - case "assert": return ASSERT 277 - case "backward": return BACKWARD 278 - case "begin": return BEGIN 279 - case "by": return BY 280 - case "call": return CALL 281 - case "case": return CASE 282 - case "chain": return CHAIN 283 - case "close": return CLOSE 284 - case "collate": return COLLATE 285 - case "column": return COLUMN 286 - case "column_name": return COLUMN_NAME 287 - case "commit": return COMMIT 288 - case "constant": return CONSTANT 289 - case "constraint": return CONSTRAINT 290 - case "constraint_name": return CONSTRAINT_NAME 291 - case "continue": return CONTINUE 292 - case "current": return CURRENT 293 - case "cursor": return CURSOR 294 - case "datatype": return DATATYPE 295 - case "debug": return DEBUG 296 - case "declare": return DECLARE 297 - case "default": return DEFAULT 298 - case "detail": return DETAIL 299 - case "diagnostics": return DIAGNOSTICS 300 - case "do": return DO 301 - case "dump": return DUMP 302 - case "else": return ELSE 303 - case "elsif": return ELSIF 304 - case "end": return END 305 - case "end_case": return END_CASE 306 - case "end_if": return END_IF 307 - case "errcode": return ERRCODE 308 - case "error": return ERROR 309 - case "exception": return EXCEPTION 310 - case "execute": return EXECUTE 311 - case "exit": return EXIT 312 - case "fetch": return FETCH 313 - case "first": return FIRST 314 - case "for": return FOR 315 - case "foreach": return FOREACH 316 - case "forward": return FORWARD 317 - case "from": return FROM 318 - case "get": return GET 319 - case "hint": return HINT 320 - case "if": return IF 321 - case "import": return IMPORT 322 - case "in": return IN 323 - case "info": return INFO 324 - case "insert": return INSERT 325 - case "into": return INTO 326 - case "is": return IS 327 - case "last": return LAST 328 - case "log": return LOG 329 - case "loop": return LOOP 330 - case "merge": return MERGE 331 - case "message": return MESSAGE 332 - case "message_text": return MESSAGE_TEXT 333 - case "move": return MOVE 334 - case "next": return NEXT 335 - case "no": return NO 336 - case "not": return NOT 337 - case "notice": return NOTICE 338 - case "no_scroll": return NO_SCROLL 339 - case "null": return NULL 340 - case "open": return OPEN 341 - case "option": return OPTION 342 - case "or": return OR 343 - case "perform": return PERFORM 344 - case "pg_context": return PG_CONTEXT 345 - case "pg_datatype_name": return PG_DATATYPE_NAME 346 - case "pg_exception_context": return PG_EXCEPTION_CONTEXT 347 - case "pg_exception_detail": return PG_EXCEPTION_DETAIL 348 - case "pg_exception_hint": return PG_EXCEPTION_HINT 349 - case "print_strict_params": return PRINT_STRICT_PARAMS 350 - case "prior": return PRIOR 351 - case "query": return QUERY 352 - case "raise": return RAISE 353 - case "relative": return RELATIVE 354 - case "return": return RETURN 355 - case "returned_sqlstate": return RETURNED_SQLSTATE 356 - case "return_next": return RETURN_NEXT 357 - case "return_query": return RETURN_QUERY 358 - case "reverse": return REVERSE 359 - case "rollback": return ROLLBACK 360 - case "rowtype": return ROWTYPE 361 - case "row_count": return ROW_COUNT 362 - case "schema": return SCHEMA 363 - case "schema_name": return SCHEMA_NAME 364 - case "scroll": return SCROLL 365 - case "slice": return SLICE 366 - case "sqlstate": return SQLSTATE 367 - case "stacked": return STACKED 368 - case "strict": return STRICT 369 - case "table": return TABLE 370 - case "table_name": return TABLE_NAME 371 - case "then": return THEN 372 - case "to": return TO 373 - case "type": return TYPE 374 - case "upsert": return UPSERT 375 - case "use_column": return USE_COLUMN 376 - case "use_variable": return USE_VARIABLE 377 - case "using": return USING 378 - case "variable_conflict": return VARIABLE_CONFLICT 379 - case "warning": return WARNING 380 - case "when": return WHEN 381 - case "while": return WHILE 382 - default: return IDENT 383 - } 384 -} 385 diff --git a/pkg/sql/plpgsql/parser/lexbase/tokens.go b/pkg/sql/plpgsql/parser/lexbase/tokens.go 386 deleted file mode 100644 387 index 56ac04c..0000000 388 --- a/pkg/sql/plpgsql/parser/lexbase/tokens.go 389 +++ /dev/null 390 @@ -1,134 +0,0 @@ 391 -// Code generated by make. DO NOT EDIT. 392 -// GENERATED FILE DO NOT EDIT 393 - 394 -package lexbase 395 - 396 -const IDENT = 57346 397 -const UIDENT = 57347 398 -const FCONST = 57348 399 -const SCONST = 57349 400 -const USCONST = 57350 401 -const BCONST = 57351 402 -const XCONST = 57352 403 -const ICONST = 57354 404 -const PARAM = 57355 405 -const TYPECAST = 57356 406 -const DOT_DOT = 57357 407 -const COLON_EQUALS = 57358 408 -const EQUALS_GREATER = 57359 409 -const LESS_EQUALS = 57360 410 -const GREATER_EQUALS = 57361 411 -const NOT_EQUALS = 57362 412 -const LESS_LESS = 57363 413 -const GREATER_GREATER = 57364 414 -const ABSOLUTE = 57365 415 -const ALIAS = 57366 416 -const ALL = 57367 417 -const AND = 57368 418 -const ARRAY = 57369 419 -const ASSERT = 57370 420 -const BACKWARD = 57371 421 -const BEGIN = 57372 422 -const BY = 57373 423 -const CALL = 57374 424 -const CASE = 57375 425 -const CHAIN = 57376 426 -const CLOSE = 57377 427 -const COLLATE = 57378 428 -const COLUMN = 57379 429 -const COLUMN_NAME = 57380 430 -const COMMIT = 57381 431 -const CONSTANT = 57382 432 -const CONSTRAINT = 57383 433 -const CONSTRAINT_NAME = 57384 434 -const CONTINUE = 57385 435 -const CURRENT = 57386 436 -const CURSOR = 57387 437 -const DATATYPE = 57388 438 -const DEBUG = 57389 439 -const DECLARE = 57390 440 -const DEFAULT = 57391 441 -const DETAIL = 57392 442 -const DIAGNOSTICS = 57393 443 -const DO = 57394 444 -const DUMP = 57395 445 -const ELSE = 57396 446 -const ELSIF = 57397 447 -const END = 57398 448 -const END_CASE = 57399 449 -const END_IF = 57400 450 -const ERRCODE = 57401 451 -const ERROR = 57402 452 -const EXCEPTION = 57403 453 -const EXECUTE = 57404 454 -const EXIT = 57405 455 -const FETCH = 57406 456 -const FIRST = 57407 457 -const FOR = 57408 458 -const FOREACH = 57409 459 -const FORWARD = 57410 460 -const FROM = 57411 461 -const GET = 57412 462 -const HINT = 57413 463 -const IF = 57414 464 -const IMPORT = 57415 465 -const IN = 57416 466 -const INFO = 57417 467 -const INSERT = 57418 468 -const INTO = 57419 469 -const IS = 57420 470 -const LAST = 57421 471 -const LOG = 57422 472 -const LOOP = 57423 473 -const MERGE = 57424 474 -const MESSAGE = 57425 475 -const MESSAGE_TEXT = 57426 476 -const MOVE = 57427 477 -const NEXT = 57428 478 -const NO = 57429 479 -const NO_SCROLL = 57430 480 -const NOT = 57431 481 -const NOTICE = 57432 482 -const NULL = 57433 483 -const OPEN = 57434 484 -const OPTION = 57435 485 -const OR = 57436 486 -const PERFORM = 57437 487 -const PG_CONTEXT = 57438 488 -const PG_DATATYPE_NAME = 57439 489 -const PG_EXCEPTION_CONTEXT = 57440 490 -const PG_EXCEPTION_DETAIL = 57441 491 -const PG_EXCEPTION_HINT = 57442 492 -const PRINT_STRICT_PARAMS = 57443 493 -const PRIOR = 57444 494 -const QUERY = 57445 495 -const RAISE = 57446 496 -const RELATIVE = 57447 497 -const RETURN = 57448 498 -const RETURN_NEXT = 57449 499 -const RETURN_QUERY = 57450 500 -const RETURNED_SQLSTATE = 57451 501 -const REVERSE = 57452 502 -const ROLLBACK = 57453 503 -const ROW_COUNT = 57454 504 -const ROWTYPE = 57455 505 -const SCHEMA = 57456 506 -const SCHEMA_NAME = 57457 507 -const SCROLL = 57458 508 -const SLICE = 57459 509 -const SQLSTATE = 57460 510 -const STACKED = 57461 511 -const STRICT = 57462 512 -const TABLE = 57463 513 -const TABLE_NAME = 57464 514 -const THEN = 57465 515 -const TO = 57466 516 -const TYPE = 57467 517 -const UPSERT = 57468 518 -const USE_COLUMN = 57469 519 -const USE_VARIABLE = 57470 520 -const USING = 57471 521 -const VARIABLE_CONFLICT = 57472 522 -const WARNING = 57473 523 -const WHEN = 57474 524 -const WHILE = 57475 525 diff --git a/pkg/sql/plpgsql/parser/lexbase/utils.go b/pkg/sql/plpgsql/parser/lexbase/utils.go 526 deleted file mode 100644 527 index 66596bf..0000000 528 --- a/pkg/sql/plpgsql/parser/lexbase/utils.go 529 +++ /dev/null 530 @@ -1,12 +0,0 @@ 531 -// Copyright 2023 The Cockroach Authors. 532 -// 533 -// Use of this software is governed by the Business Source License 534 -// included in the file licenses/BSL.txt. 535 -// 536 -// As of the Change Date specified in that file, in accordance with 537 -// the Business Source License, use of this software will be governed 538 -// by the Apache License, Version 2.0, included in the file 539 -// licenses/APL.txt. 540 - 541 -// Package lexbase contains utilities for lexing plpgsql. 542 -package lexbase 543 diff --git a/pkg/sql/plpgsql/parser/lexer.go b/pkg/sql/plpgsql/parser/lexer.go 544 deleted file mode 100644 545 index 9201b03..0000000 546 --- a/pkg/sql/plpgsql/parser/lexer.go 547 +++ /dev/null 548 @@ -1,501 +0,0 @@ 549 -// Copyright 2023 The Cockroach Authors. 550 -// 551 -// Use of this software is governed by the Business Source License 552 -// included in the file licenses/BSL.txt. 553 -// 554 -// As of the Change Date specified in that file, in accordance with 555 -// the Business Source License, use of this software will be governed 556 -// by the Apache License, Version 2.0, included in the file 557 -// licenses/APL.txt. 558 - 559 -package parser 560 - 561 -import ( 562 - "strings" 563 - 564 - "github.com/cockroachdb/cockroachdb-parser/pkg/sql/parser" 565 - "github.com/cockroachdb/cockroachdb-parser/pkg/sql/pgwire/pgcode" 566 - "github.com/cockroachdb/cockroachdb-parser/pkg/sql/pgwire/pgerror" 567 - "github.com/cockroachdb/cockroachdb-parser/pkg/sql/sem/plpgsqltree" 568 - "github.com/cockroachdb/cockroachdb-parser/pkg/sql/sem/tree" 569 - "github.com/cockroachdb/cockroachdb-parser/pkg/sql/types" 570 - unimp "github.com/cockroachdb/cockroachdb-parser/pkg/util/errorutil/unimplemented" 571 - "github.com/cockroachdb/errors" 572 -) 573 - 574 -type lexer struct { 575 - in string 576 - // tokens contains tokens generated by the scanner. 577 - tokens []plpgsqlSymType 578 - 579 - // The type that should be used when an INT or SERIAL is encountered. 580 - nakedIntType *types.T 581 - 582 - // lastPos is the position into the tokens slice of the last 583 - // token returned by Lex(). 584 - lastPos int 585 - 586 - stmt *plpgsqltree.Block 587 - 588 - // numPlaceholders is 1 + the highest placeholder index encountered. 589 - numPlaceholders int 590 - numAnnotations tree.AnnotationIdx 591 - 592 - lastError error 593 - 594 - parser plpgsqlParser 595 -} 596 - 597 -func (l *lexer) init(sql string, tokens []plpgsqlSymType, nakedIntType *types.T, p plpgsqlParser) { 598 - l.in = sql 599 - l.tokens = tokens 600 - l.lastPos = -1 601 - l.stmt = nil 602 - l.numPlaceholders = 0 603 - l.numAnnotations = 0 604 - l.lastError = nil 605 - l.nakedIntType = nakedIntType 606 - l.parser = p 607 -} 608 - 609 -// cleanup is used to avoid holding on to memory unnecessarily (for the cases 610 -// where we reuse a scanner). 611 -func (l *lexer) cleanup() { 612 - l.tokens = nil 613 - l.stmt = nil 614 - l.lastError = nil 615 -} 616 - 617 -// Lex lexes a token from input. 618 -// to push the tokens back (move l.pos back). 619 -func (l *lexer) Lex(lval *plpgsqlSymType) int { 620 - l.lastPos++ 621 - // The core lexing takes place in the scanner. Here we do a small bit of post 622 - // processing of the lexical tokens so that the grammar only requires 623 - // one-token lookahead despite SQL requiring multi-token lookahead in some 624 - // cases. These special cases are handled below and the returned tokens are 625 - // adjusted to reflect the lookahead (LA) that occurred. 626 - if l.lastPos >= len(l.tokens) { 627 - lval.id = 0 628 - lval.pos = int32(len(l.in)) 629 - lval.str = "EOF" 630 - return 0 631 - } 632 - *lval = l.tokens[l.lastPos] 633 - 634 - switch lval.id { 635 - case RETURN: 636 - nextToken := plpgsqlSymType{} 637 - if l.lastPos+1 < len(l.tokens) { 638 - nextToken = l.tokens[l.lastPos+1] 639 - } 640 - switch nextToken.id { 641 - case NEXT: 642 - lval.id = RETURN_NEXT 643 - case QUERY: 644 - lval.id = RETURN_QUERY 645 - } 646 - case END: 647 - nextToken := plpgsqlSymType{} 648 - if l.lastPos+1 < len(l.tokens) { 649 - nextToken = l.tokens[l.lastPos+1] 650 - } 651 - switch nextToken.id { 652 - case IF: 653 - lval.id = END_IF 654 - case CASE: 655 - lval.id = END_CASE 656 - } 657 - case NO: 658 - nextToken := plpgsqlSymType{} 659 - if l.lastPos+1 < len(l.tokens) { 660 - nextToken = l.tokens[l.lastPos+1] 661 - } 662 - switch nextToken.id { 663 - case SCROLL: 664 - lval.id = NO_SCROLL 665 - } 666 - } 667 - 668 - return int(lval.id) 669 -} 670 - 671 -// MakeExecSqlStmt makes an Execute node. 672 -func (l *lexer) MakeExecSqlStmt() (*plpgsqltree.Execute, error) { 673 - if l.parser.Lookahead() != -1 { 674 - // Push back the lookahead token so that it can be included. 675 - l.PushBack(1) 676 - } 677 - // Push back the first token so that it's included in the SQL string. 678 - l.PushBack(1) 679 - startPos, endPos, _, err := l.readSQLConstruct(false /* isExpr */, ';') 680 - if err != nil { 681 - return nil, err 682 - } 683 - // Move past the semicolon. 684 - l.lastPos++ 685 - 686 - var haveInto, haveStrict bool 687 - var intoStartPos, intoEndPos int 688 - var target []plpgsqltree.Variable 689 - firstTok := l.tokens[startPos] 690 - tok := firstTok 691 - for pos := startPos; pos < endPos; pos++ { 692 - prevTok := tok 693 - tok = l.tokens[pos] 694 - if tok.id == INTO { 695 - if prevTok.id == INSERT || prevTok.id == UPSERT || 696 - prevTok.id == MERGE || firstTok.id == IMPORT { 697 - // INSERT INTO, UPSERT INTO, MERGE INTO, and IMPORT ... INTO are not 698 - // INTO-targets. 699 - continue 700 - } 701 - if haveInto { 702 - return nil, errors.New("INTO specified more than once") 703 - } 704 - haveInto = true 705 - intoStartPos = pos 706 - pos++ 707 - if pos+1 < endPos && l.tokens[pos].id == STRICT { 708 - haveStrict = true 709 - pos++ 710 - } 711 - // Read in one or more comma-separated variables as the INTO target. 712 - for ; pos < endPos; pos += 2 { 713 - tok = l.tokens[pos] 714 - if tok.id != IDENT { 715 - return nil, errors.Newf("\"%s\" is not a scalar variable", tok.str) 716 - } 717 - variable := plpgsqltree.Variable(strings.TrimSpace(l.getStr(pos, pos+1))) 718 - target = append(target, variable) 719 - if pos+1 == endPos || l.tokens[pos+1].id != ',' { 720 - // This is the end of the target list. 721 - break 722 - } 723 - } 724 - intoEndPos = pos + 1 725 - } 726 - } 727 - 728 - var sql string 729 - if haveInto { 730 - sql = l.getStr(startPos, intoStartPos) + l.getStr(intoEndPos, endPos) 731 - } else { 732 - sql = l.getStr(startPos, endPos) 733 - } 734 - sqlStmt, err := parser.ParseOne(sql) 735 - if err != nil { 736 - return nil, err 737 - } 738 - 739 - // Note: PG disallows directly writing SQL statements that return rows, like 740 - // a SELECT or a mutation with RETURNING. It is difficult to determine this 741 - // for all possible statements, and execution is able to handle it, so we 742 - // allow SQL statements that return rows. 743 - if target != nil && sqlStmt.AST.StatementReturnType() != tree.Rows { 744 - return nil, pgerror.New(pgcode.Syntax, "INTO used with a command that cannot return data") 745 - } 746 - return &plpgsqltree.Execute{ 747 - SqlStmt: sqlStmt.AST, 748 - Strict: haveStrict, 749 - Target: target, 750 - }, nil 751 -} 752 - 753 -func (l *lexer) MakeDynamicExecuteStmt() (*plpgsqltree.DynamicExecute, error) { 754 - cmdStr, _, err := l.ReadSqlStatement(INTO, USING, ';') 755 - if err != nil { 756 - return nil, err 757 - } 758 - ret := &plpgsqltree.DynamicExecute{ 759 - Query: cmdStr, 760 - } 761 - 762 - var lval plpgsqlSymType 763 - l.Lex(&lval) 764 - for { 765 - if lval.id == INTO { 766 - if ret.Into { 767 - return nil, errors.New("multiple INTO keywords") 768 - } 769 - ret.Into = true 770 - nextTok := l.Peek() 771 - if nextTok.id == int32(STRICT) { 772 - l.Lex(&lval) 773 - ret.Strict = true 774 - } 775 - // TODO we need to read each "INTO" variable name instead of just a 776 - // string. 777 - _, _, err = l.ReadSqlExpr(USING, ';') 778 - if err != nil { 779 - return nil, err 780 - } 781 - l.Lex(&lval) 782 - } else if lval.id == USING { 783 - if ret.Params != nil { 784 - return nil, errors.New("multiple USING keywords") 785 - } 786 - ret.Params = make([]plpgsqltree.Expr, 0) 787 - for { 788 - _, _, err = l.ReadSqlExpr(',', ';', INTO) 789 - if err != nil { 790 - return nil, err 791 - } 792 - ret.Params = append(ret.Params, nil) 793 - l.Lex(&lval) 794 - if lval.id == ';' { 795 - break 796 - } 797 - } 798 - } else if lval.id == ';' { 799 - break 800 - } else { 801 - return nil, errors.Newf("unexpected token: %s", lval.id) 802 - } 803 - } 804 - 805 - return ret, nil 806 -} 807 - 808 -func (l *lexer) readSQLConstruct( 809 - isExpr bool, terminator1 int, terminators ...int, 810 -) (startPos, endPos, terminatorMet int, err error) { 811 - if l.parser.Lookahead() != -1 { 812 - // Push back the lookahead token so that it can be included. 813 - l.PushBack(1) 814 - } 815 - parenLevel := 0 816 - startPos = l.lastPos + 1 817 - for l.lastPos < len(l.tokens) { 818 - tok := l.Peek() 819 - if int(tok.id) == terminator1 && parenLevel == 0 { 820 - terminatorMet = terminator1 821 - break 822 - } 823 - for _, term := range terminators { 824 - if int(tok.id) == term && parenLevel == 0 { 825 - terminatorMet = term 826 - } 827 - } 828 - if terminatorMet != 0 { 829 - break 830 - } 831 - if tok.id == '(' || tok.id == '[' { 832 - parenLevel++ 833 - } else if tok.id == ')' || tok.id == ']' { 834 - parenLevel-- 835 - if parenLevel < 0 { 836 - return 0, 0, 0, errors.New("mismatched parentheses") 837 - } 838 - } 839 - l.lastPos++ 840 - } 841 - if parenLevel != 0 { 842 - return 0, 0, 0, errors.New("mismatched parentheses") 843 - } 844 - endPos = l.lastPos + 1 845 - if endPos > len(l.tokens) { 846 - endPos = len(l.tokens) 847 - } 848 - if endPos <= startPos { 849 - if isExpr { 850 - return 0, 0, 0, errors.New("missing expression") 851 - } else { 852 - return 0, 0, 0, errors.New("missing SQL statement") 853 - } 854 - } 855 - return startPos, endPos, terminatorMet, nil 856 -} 857 - 858 -func (l *lexer) MakeFetchOrMoveStmt(isMove bool) (plpgsqltree.Statement, error) { 859 - if l.parser.Lookahead() != -1 { 860 - // Push back the lookahead token so that it can be included. 861 - l.PushBack(1) 862 - } 863 - prefix := "FETCH " 864 - if isMove { 865 - prefix = "MOVE " 866 - } 867 - sqlStr, terminator, err := l.ReadSqlStatement(INTO, ';') 868 - if err != nil { 869 - return nil, err 870 - } 871 - sqlStr = prefix + sqlStr 872 - sqlStmt, err := parser.ParseOne(sqlStr) 873 - if err != nil { 874 - return nil, err 875 - } 876 - var cursor tree.CursorStmt 877 - switch t := sqlStmt.AST.(type) { 878 - case *tree.FetchCursor: 879 - cursor = t.CursorStmt 880 - case *tree.MoveCursor: 881 - cursor = t.CursorStmt 882 - default: 883 - return nil, errors.Newf("invalid FETCH or MOVE syntax") 884 - } 885 - var target []plpgsqltree.Variable 886 - if !isMove { 887 - if terminator != INTO { 888 - return nil, errors.Newf("invalid syntax for FETCH") 889 - } 890 - // Read past the INTO. 891 - l.lastPos++ 892 - startPos, endPos, _, err := l.readSQLConstruct(true /* isExpr */, ';') 893 - if err != nil { 894 - return nil, err 895 - } 896 - for pos := startPos; pos < endPos; pos += 2 { 897 - tok := l.tokens[pos] 898 - if tok.id != IDENT { 899 - return nil, errors.Newf("\"%s\" is not a scalar variable", tok.str) 900 - } 901 - if pos+1 != endPos && l.tokens[pos+1].id != ',' { 902 - return nil, errors.Newf("expected INTO target to be a comma-separated list") 903 - } 904 - variable := plpgsqltree.Variable(strings.TrimSpace(l.getStr(pos, pos+1))) 905 - target = append(target, variable) 906 - } 907 - if len(target) == 0 { 908 - return nil, errors.Newf("expected INTO target") 909 - } 910 - } 911 - // Move past the semicolon. 912 - l.lastPos++ 913 - return &plpgsqltree.Fetch{ 914 - Cursor: cursor, 915 - Target: target, 916 - IsMove: isMove, 917 - }, nil 918 -} 919 - 920 -func (l *lexer) ReadSqlExpr( 921 - terminator1 int, terminators ...int, 922 -) (sqlStr string, terminatorMet int, err error) { 923 - var startPos, endPos int 924 - startPos, endPos, terminatorMet, err = l.readSQLConstruct( 925 - true /* isExpr */, terminator1, terminators..., 926 - ) 927 - return l.getStr(startPos, endPos), terminatorMet, err 928 -} 929 - 930 -func (l *lexer) ReadSqlStatement( 931 - terminator1 int, terminators ...int, 932 -) (sqlStr string, terminatorMet int, err error) { 933 - var startPos, endPos int 934 - startPos, endPos, terminatorMet, err = l.readSQLConstruct( 935 - false /* isExpr */, terminator1, terminators..., 936 - ) 937 - return l.getStr(startPos, endPos), terminatorMet, err 938 -} 939 - 940 -func (l *lexer) getStr(startPos, endPos int) string { 941 - if endPos <= startPos { 942 - return "" 943 - } 944 - end := len(l.in) 945 - if endPos < len(l.tokens) { 946 - end = int(l.tokens[endPos].Pos()) 947 - } 948 - start := int(l.tokens[startPos].Pos()) 949 - return l.in[start:end] 950 -} 951 - 952 -// Peek peeks 953 -func (l *lexer) Peek() plpgsqlSymType { 954 - if l.lastPos+1 < len(l.tokens) { 955 - return l.tokens[l.lastPos+1] 956 - } 957 - return plpgsqlSymType{} 958 -} 959 - 960 -// PushBack rewinds the lexer by n tokens. 961 -func (l *lexer) PushBack(n int) { 962 - if n < 0 { 963 - panic(errors.AssertionFailedf("negative n provided to PushBack")) 964 - } 965 - l.lastPos -= n 966 - if l.lastPos < -1 { 967 - // Return to the initialized state. 968 - l.lastPos = -1 969 - } 970 - if n >= 1 { 971 - // Invalidate the parser lookahead token. 972 - l.parser.(*plpgsqlParserImpl).char = -1 973 - } 974 -} 975 - 976 -func (l *lexer) lastToken() plpgsqlSymType { 977 - if l.lastPos < 0 { 978 - return plpgsqlSymType{} 979 - } 980 - 981 - if l.lastPos >= len(l.tokens) { 982 - return plpgsqlSymType{ 983 - id: 0, 984 - pos: int32(len(l.in)), 985 - str: "EOF", 986 - } 987 - } 988 - return l.tokens[l.lastPos] 989 -} 990 - 991 -// SetStmt is called from the parser when the statement is constructed. 992 -func (l *lexer) SetStmt(stmt plpgsqltree.Statement) { 993 - l.stmt = stmt.(*plpgsqltree.Block) 994 -} 995 - 996 -// setErr is called from parsing action rules to register an error observed 997 -// while running the action. That error becomes the actual "cause" of the 998 -// syntax error. 999 -func (l *lexer) setErr(err error) { 1000 - err = pgerror.WithCandidateCode(err, pgcode.Syntax) 1001 - l.lastError = err 1002 - lastTok := l.lastToken() 1003 - l.lastError = parser.PopulateErrorDetails(lastTok.id, lastTok.str, lastTok.pos, l.lastError, l.in) 1004 -} 1005 - 1006 -func (l *lexer) Error(e string) { 1007 - e = strings.TrimPrefix(e, "syntax error: ") // we'll add it again below. 1008 - err := pgerror.WithCandidateCode(errors.Newf("%s", e), pgcode.Syntax) 1009 - lastTok := l.lastToken() 1010 - l.lastError = parser.PopulateErrorDetails(lastTok.id, lastTok.str, lastTok.pos, err, l.in) 1011 -} 1012 - 1013 -// Unimplemented wraps Error, setting lastUnimplementedError. 1014 -func (l *lexer) Unimplemented(feature string) { 1015 - l.lastError = unimp.New(feature, "this syntax") 1016 - lastTok := l.lastToken() 1017 - l.lastError = parser.PopulateErrorDetails(lastTok.id, lastTok.str, lastTok.pos, l.lastError, l.in) 1018 - l.lastError = &tree.UnsupportedError{ 1019 - Err: l.lastError, 1020 - FeatureName: feature, 1021 - } 1022 -} 1023 - 1024 -func (l *lexer) GetTypeFromValidSQLSyntax(sqlStr string) (tree.ResolvableTypeReference, error) { 1025 - return parser.GetTypeFromValidSQLSyntax(sqlStr) 1026 -} 1027 - 1028 -func (l *lexer) ParseExpr(sqlStr string) (plpgsqltree.Expr, error) { 1029 - // Use ParseExprs instead of ParseExpr in order to correctly handle the case 1030 - // when multiple expressions are incorrectly passed. 1031 - exprs, err := parser.ParseExprs([]string{sqlStr}) 1032 - if err != nil { 1033 - return nil, err 1034 - } 1035 - if len(exprs) != 1 { 1036 - return nil, pgerror.Newf(pgcode.Syntax, "query returned %d columns", len(exprs)) 1037 - } 1038 - return exprs[0], nil 1039 -} 1040 - 1041 -func checkLoopLabels(start, end string) error { 1042 - if start == "" && end != "" { 1043 - return errors.Newf("end label \"%s\" specified for unlabeled block", end) 1044 - } 1045 - if end != "" && start != end { 1046 - return errors.Newf("end label \"%s\" differs from block's label \"%s\"", end, start) 1047 - } 1048 - return nil 1049 -} 1050 diff --git a/pkg/sql/plpgsql/parser/parse.go b/pkg/sql/plpgsql/parser/parse.go 1051 deleted file mode 100644 1052 index 520830a..0000000 1053 --- a/pkg/sql/plpgsql/parser/parse.go 1054 +++ /dev/null 1055 @@ -1,136 +0,0 @@ 1056 -// Copyright 2023 The Cockroach Authors. 1057 -// 1058 -// Use of this software is governed by the Business Source License 1059 -// included in the file licenses/BSL.txt. 1060 -// 1061 -// As of the Change Date specified in that file, in accordance with 1062 -// the Business Source License, use of this software will be governed 1063 -// by the Apache License, Version 2.0, included in the file 1064 -// licenses/APL.txt. 1065 - 1066 -// Package parser exposes a parser for plpgsql. 1067 -package parser 1068 - 1069 -import ( 1070 - "go/constant" 1071 - 1072 - "github.com/cockroachdb/cockroachdb-parser/pkg/sql/parser/statements" 1073 - "github.com/cockroachdb/cockroachdb-parser/pkg/sql/scanner" 1074 - "github.com/cockroachdb/cockroachdb-parser/pkg/sql/sem/tree" 1075 - "github.com/cockroachdb/cockroachdb-parser/pkg/sql/types" 1076 - "github.com/cockroachdb/errors" 1077 -) 1078 - 1079 -func init() { 1080 - scanner.NewNumValFn = func(a constant.Value, s string, b bool) interface{} { return tree.NewNumVal(a, s, b) } 1081 - scanner.NewPlaceholderFn = func(s string) (interface{}, error) { return tree.NewPlaceholder(s) } 1082 -} 1083 - 1084 -// Parser wraps a scanner, parser and other utilities present in the parser 1085 -// package. 1086 -type Parser struct { 1087 - scanner scanner.PLpgSQLScanner 1088 - lexer lexer 1089 - parserImpl plpgsqlParserImpl 1090 - tokBuf [8]plpgsqlSymType 1091 -} 1092 - 1093 -// INT8 is the historical interpretation of INT. This should be left 1094 -// alone in the future, since there are many sql fragments stored 1095 -// in various descriptors. Any user input that was created after 1096 -// INT := INT4 will simply use INT4 in any resulting code. 1097 -var defaultNakedIntType = types.Int 1098 - 1099 -// Parse parses the sql and returns a list of statements. 1100 -func (p *Parser) Parse(sql string) (statements.PLpgStatement, error) { 1101 - return p.parseWithDepth(1, sql, defaultNakedIntType) 1102 -} 1103 - 1104 -func (p *Parser) scanFnBlock() (sql string, tokens []plpgsqlSymType, done bool) { 1105 - var lval plpgsqlSymType 1106 - tokens = p.tokBuf[:0] 1107 - 1108 - // Scan the first token. 1109 - p.scanner.Scan(&lval) 1110 - if lval.id == 0 { 1111 - return "", nil, true 1112 - } 1113 - 1114 - startPos := lval.pos 1115 - // We make the resulting token positions match the returned string. 1116 - lval.pos = 0 1117 - tokens = append(tokens, lval) 1118 - for { 1119 - if lval.id == ERROR { 1120 - return p.scanner.In()[startPos:], tokens, true 1121 - } 1122 - // Reset the plpgsqlSymType struct before scanning. 1123 - lval = plpgsqlSymType{} 1124 - posBeforeScan := p.scanner.Pos() 1125 - p.scanner.Scan(&lval) 1126 - if lval.id == 0 { 1127 - return p.scanner.In()[startPos:posBeforeScan], tokens, (lval.id == 0) 1128 - } 1129 - lval.pos -= startPos 1130 - tokens = append(tokens, lval) 1131 - } 1132 -} 1133 - 1134 -func (p *Parser) parseWithDepth( 1135 - depth int, plpgsql string, nakedIntType *types.T, 1136 -) (statements.PLpgStatement, error) { 1137 - p.scanner.Init(plpgsql) 1138 - defer p.scanner.Cleanup() 1139 - sql, tokens, done := p.scanFnBlock() 1140 - stmt, err := p.parse(depth+1, sql, tokens, nakedIntType) 1141 - if err != nil { 1142 - return statements.PLpgStatement{}, err 1143 - } 1144 - if !done { 1145 - return statements.PLpgStatement{}, errors.AssertionFailedf("invalid plpgsql function: %s", plpgsql) 1146 - } 1147 - return stmt, nil 1148 -} 1149 - 1150 -// parse parses a statement from the given scanned tokens. 1151 -func (p *Parser) parse( 1152 - depth int, sql string, tokens []plpgsqlSymType, nakedIntType *types.T, 1153 -) (statements.PLpgStatement, error) { 1154 - p.lexer.init(sql, tokens, nakedIntType, &p.parserImpl) 1155 - defer p.lexer.cleanup() 1156 - if p.parserImpl.Parse(&p.lexer) != 0 { 1157 - if p.lexer.lastError == nil { 1158 - // This should never happen -- there should be an error object 1159 - // every time Parse() returns nonzero. We're just playing safe 1160 - // here. 1161 - p.lexer.Error("syntax error") 1162 - } 1163 - err := p.lexer.lastError 1164 - 1165 - // Compatibility with 19.1 telemetry: prefix the telemetry keys 1166 - // with the "syntax." prefix. 1167 - // TODO(knz): move the auto-prefixing of feature names to a 1168 - // higher level in the call stack. 1169 - tkeys := errors.GetTelemetryKeys(err) 1170 - if len(tkeys) > 0 { 1171 - for i := range tkeys { 1172 - tkeys[i] = "syntax." + tkeys[i] 1173 - } 1174 - err = errors.WithTelemetry(err, tkeys...) 1175 - } 1176 - 1177 - return statements.PLpgStatement{}, err 1178 - } 1179 - return statements.PLpgStatement{ 1180 - AST: p.lexer.stmt, 1181 - SQL: sql, 1182 - NumPlaceholders: p.lexer.numPlaceholders, 1183 - NumAnnotations: p.lexer.numAnnotations, 1184 - }, nil 1185 -} 1186 - 1187 -// Parse parses a sql statement string and returns a list of Statements. 1188 -func Parse(sql string) (statements.PLpgStatement, error) { 1189 - var p Parser 1190 - return p.parseWithDepth(1, sql, defaultNakedIntType) 1191 -} 1192 diff --git a/pkg/sql/plpgsql/parser/plpgsql.y b/pkg/sql/plpgsql/parser/plpgsql.y 1193 deleted file mode 100644 1194 index 8ee4069..0000000 1195 --- a/pkg/sql/plpgsql/parser/plpgsql.y 1196 +++ /dev/null 1197 @@ -1,1647 +0,0 @@ 1198 -%{ 1199 -package parser 1200 - 1201 -import ( 1202 - "github.com/cockroachdb/cockroach/pkg/sql/parser" 1203 - "github.com/cockroachdb/cockroach/pkg/sql/scanner" 1204 - "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" 1205 - "github.com/cockroachdb/cockroach/pkg/sql/sem/plpgsqltree" 1206 - "github.com/cockroachdb/errors" 1207 - "github.com/cockroachdb/redact" 1208 -) 1209 -%} 1210 - 1211 -%{ 1212 -func setErr(plpgsqllex plpgsqlLexer, err error) int { 1213 - plpgsqllex.(*lexer).setErr(err) 1214 - return 1 1215 -} 1216 - 1217 -func unimplemented(plpgsqllex plpgsqlLexer, feature string) int { 1218 - plpgsqllex.(*lexer).Unimplemented(feature) 1219 - return 1 1220 -} 1221 - 1222 -//functions to cast plpgsqlSymType/sqlSymUnion to other types. 1223 -var _ scanner.ScanSymType = &plpgsqlSymType{} 1224 - 1225 -func (s *plpgsqlSymType) ID() int32 { 1226 - return s.id 1227 -} 1228 - 1229 -func (s *plpgsqlSymType) SetID(id int32) { 1230 - s.id = id 1231 -} 1232 - 1233 -func (s *plpgsqlSymType) Pos() int32 { 1234 - return s.pos 1235 -} 1236 - 1237 -func (s *plpgsqlSymType) SetPos(pos int32) { 1238 - s.pos = pos 1239 -} 1240 - 1241 -func (s *plpgsqlSymType) Str() string { 1242 - return s.str 1243 -} 1244 - 1245 -func (s *plpgsqlSymType) SetStr(str string) { 1246 - s.str = str 1247 -} 1248 - 1249 -func (s *plpgsqlSymType) UnionVal() interface{} { 1250 - return s.union.val 1251 -} 1252 - 1253 -func (s *plpgsqlSymType) SetUnionVal(val interface{}) { 1254 - s.union.val = val 1255 -} 1256 - 1257 -func (s *plpgsqlSymType) plpgsqlScanSymType() {} 1258 - 1259 -type plpgsqlSymUnion struct { 1260 - val interface{} 1261 -} 1262 - 1263 -func (u *plpgsqlSymUnion) block() *plpgsqltree.Block { 1264 - return u.val.(*plpgsqltree.Block) 1265 -} 1266 - 1267 -func (u *plpgsqlSymUnion) caseWhen() *plpgsqltree.CaseWhen { 1268 - return u.val.(*plpgsqltree.CaseWhen) 1269 -} 1270 - 1271 -func (u *plpgsqlSymUnion) caseWhens() []*plpgsqltree.CaseWhen { 1272 - return u.val.([]*plpgsqltree.CaseWhen) 1273 -} 1274 - 1275 -func (u *plpgsqlSymUnion) statement() plpgsqltree.Statement { 1276 - return u.val.(plpgsqltree.Statement) 1277 -} 1278 - 1279 -func (u *plpgsqlSymUnion) statements() []plpgsqltree.Statement { 1280 - return u.val.([]plpgsqltree.Statement) 1281 -} 1282 - 1283 -func (u *plpgsqlSymUnion) int32() int32 { 1284 - return u.val.(int32) 1285 -} 1286 - 1287 -func (u *plpgsqlSymUnion) uint32() uint32 { 1288 - return u.val.(uint32) 1289 -} 1290 - 1291 -func (u *plpgsqlSymUnion) bool() bool { 1292 - return u.val.(bool) 1293 -} 1294 - 1295 -func (u *plpgsqlSymUnion) numVal() *tree.NumVal { 1296 - return u.val.(*tree.NumVal) 1297 -} 1298 - 1299 -func (u *plpgsqlSymUnion) typ() tree.ResolvableTypeReference { 1300 - return u.val.(tree.ResolvableTypeReference) 1301 -} 1302 - 1303 -func (u *plpgsqlSymUnion) getDiagnosticsKind() plpgsqltree.GetDiagnosticsKind { 1304 - return u.val.(plpgsqltree.GetDiagnosticsKind) 1305 -} 1306 - 1307 -func (u *plpgsqlSymUnion) getDiagnosticsItem() *plpgsqltree.GetDiagnosticsItem { 1308 - return u.val.(*plpgsqltree.GetDiagnosticsItem) 1309 -} 1310 - 1311 -func (u *plpgsqlSymUnion) getDiagnosticsItemList() plpgsqltree.GetDiagnosticsItemList { 1312 - return u.val.(plpgsqltree.GetDiagnosticsItemList) 1313 -} 1314 - 1315 -func (u *plpgsqlSymUnion) elseIf() []plpgsqltree.ElseIf { 1316 - return u.val.([]plpgsqltree.ElseIf) 1317 -} 1318 - 1319 -func (u *plpgsqlSymUnion) open() *plpgsqltree.Open { 1320 - return u.val.(*plpgsqltree.Open) 1321 -} 1322 - 1323 -func (u *plpgsqlSymUnion) expr() plpgsqltree.Expr { 1324 - if u.val == nil { 1325 - return nil 1326 - } 1327 - return u.val.(plpgsqltree.Expr) 1328 -} 1329 - 1330 -func (u *plpgsqlSymUnion) exprs() []plpgsqltree.Expr { 1331 - return u.val.([]plpgsqltree.Expr) 1332 -} 1333 - 1334 -func (u *plpgsqlSymUnion) raiseOption() *plpgsqltree.RaiseOption { 1335 - return u.val.(*plpgsqltree.RaiseOption) 1336 -} 1337 - 1338 -func (u *plpgsqlSymUnion) raiseOptions() []plpgsqltree.RaiseOption { 1339 - return u.val.([]plpgsqltree.RaiseOption) 1340 -} 1341 - 1342 - 1343 -func (u *plpgsqlSymUnion) exception() *plpgsqltree.Exception { 1344 - return u.val.(*plpgsqltree.Exception) 1345 -} 1346 - 1347 -func (u *plpgsqlSymUnion) exceptions() []plpgsqltree.Exception { 1348 - return u.val.([]plpgsqltree.Exception) 1349 -} 1350 - 1351 -func (u *plpgsqlSymUnion) condition() *plpgsqltree.Condition { 1352 - return u.val.(*plpgsqltree.Condition) 1353 -} 1354 - 1355 -func (u *plpgsqlSymUnion) conditions() []plpgsqltree.Condition { 1356 - return u.val.([]plpgsqltree.Condition) 1357 -} 1358 - 1359 -func (u *plpgsqlSymUnion) cursorScrollOption() tree.CursorScrollOption { 1360 - return u.val.(tree.CursorScrollOption) 1361 -} 1362 - 1363 -func (u *plpgsqlSymUnion) sqlStatement() tree.Statement { 1364 - return u.val.(tree.Statement) 1365 -} 1366 - 1367 -%} 1368 -/* 1369 - * Basic non-keyword token types. These are hard-wired into the core lexer. 1370 - * They must be listed first so that their numeric codes do not depend on 1371 - * the set of keywords. Keep this list in sync with backend/parser/gram.y! 1372 - * 1373 - * Some of these are not directly referenced in this file, but they must be 1374 - * here anyway. 1375 - */ 1376 -%token <str> IDENT UIDENT FCONST SCONST USCONST BCONST XCONST Op 1377 -%token <*tree.NumVal> ICONST PARAM 1378 -%token <str> TYPECAST DOT_DOT COLON_EQUALS EQUALS_GREATER 1379 -%token <str> LESS_EQUALS GREATER_EQUALS NOT_EQUALS 1380 - 1381 -/* 1382 - * Other tokens recognized by plpgsql's lexer interface layer (pl_scanner.c). 1383 - */ 1384 -%token <str> LESS_LESS GREATER_GREATER 1385 - 1386 -/* 1387 - * Keyword tokens. Some of these are reserved and some are not; 1388 - * see pl_scanner.c for info. Be sure unreserved keywords are listed 1389 - * in the "unreserved_keyword" production below. 1390 - */ 1391 -%token <str> ABSOLUTE 1392 -%token <str> ALIAS 1393 -%token <str> ALL 1394 -%token <str> AND 1395 -%token <str> ARRAY 1396 -%token <str> ASSERT 1397 -%token <str> BACKWARD 1398 -%token <str> BEGIN 1399 -%token <str> BY 1400 -%token <str> CALL 1401 -%token <str> CASE 1402 -%token <str> CHAIN 1403 -%token <str> CLOSE 1404 -%token <str> COLLATE 1405 -%token <str> COLUMN 1406 -%token <str> COLUMN_NAME 1407 -%token <str> COMMIT 1408 -%token <str> CONSTANT 1409 -%token <str> CONSTRAINT 1410 -%token <str> CONSTRAINT_NAME 1411 -%token <str> CONTINUE 1412 -%token <str> CURRENT 1413 -%token <str> CURSOR 1414 -%token <str> DATATYPE 1415 -%token <str> DEBUG 1416 -%token <str> DECLARE 1417 -%token <str> DEFAULT 1418 -%token <str> DETAIL 1419 -%token <str> DIAGNOSTICS 1420 -%token <str> DO 1421 -%token <str> DUMP 1422 -%token <str> ELSE 1423 -%token <str> ELSIF 1424 -%token <str> END 1425 -%token <str> END_CASE 1426 -%token <str> END_IF 1427 -%token <str> ERRCODE 1428 -%token <str> ERROR 1429 -%token <str> EXCEPTION 1430 -%token <str> EXECUTE 1431 -%token <str> EXIT 1432 -%token <str> FETCH 1433 -%token <str> FIRST 1434 -%token <str> FOR 1435 -%token <str> FOREACH 1436 -%token <str> FORWARD 1437 -%token <str> FROM 1438 -%token <str> GET 1439 -%token <str> HINT 1440 -%token <str> IF 1441 -%token <str> IMPORT 1442 -%token <str> IN 1443 -%token <str> INFO 1444 -%token <str> INSERT 1445 -%token <str> INTO 1446 -%token <str> IS 1447 -%token <str> LAST 1448 -%token <str> LOG 1449 -%token <str> LOOP 1450 -%token <str> MERGE 1451 -%token <str> MESSAGE 1452 -%token <str> MESSAGE_TEXT 1453 -%token <str> MOVE 1454 -%token <str> NEXT 1455 -%token <str> NO 1456 -%token <str> NO_SCROLL 1457 -%token <str> NOT 1458 -%token <str> NOTICE 1459 -%token <str> NULL 1460 -%token <str> OPEN 1461 -%token <str> OPTION 1462 -%token <str> OR 1463 -%token <str> PERFORM 1464 -%token <str> PG_CONTEXT 1465 -%token <str> PG_DATATYPE_NAME 1466 -%token <str> PG_EXCEPTION_CONTEXT 1467 -%token <str> PG_EXCEPTION_DETAIL 1468 -%token <str> PG_EXCEPTION_HINT 1469 -%token <str> PRINT_STRICT_PARAMS 1470 -%token <str> PRIOR 1471 -%token <str> QUERY 1472 -%token <str> RAISE 1473 -%token <str> RELATIVE 1474 -%token <str> RETURN 1475 -%token <str> RETURN_NEXT 1476 -%token <str> RETURN_QUERY 1477 -%token <str> RETURNED_SQLSTATE 1478 -%token <str> REVERSE 1479 -%token <str> ROLLBACK 1480 -%token <str> ROW_COUNT 1481 -%token <str> ROWTYPE 1482 -%token <str> SCHEMA 1483 -%token <str> SCHEMA_NAME 1484 -%token <str> SCROLL 1485 -%token <str> SLICE 1486 -%token <str> SQLSTATE 1487 -%token <str> STACKED 1488 -%token <str> STRICT 1489 -%token <str> TABLE 1490 -%token <str> TABLE_NAME 1491 -%token <str> THEN 1492 -%token <str> TO 1493 -%token <str> TYPE 1494 -%token <str> UPSERT 1495 -%token <str> USE_COLUMN 1496 -%token <str> USE_VARIABLE 1497 -%token <str> USING 1498 -%token <str> VARIABLE_CONFLICT 1499 -%token <str> WARNING 1500 -%token <str> WHEN 1501 -%token <str> WHILE 1502 - 1503 - 1504 -%union { 1505 - id int32 1506 - pos int32 1507 - str string 1508 - union plpgsqlSymUnion 1509 -} 1510 - 1511 -%type <str> decl_varname decl_defkey 1512 -%type <bool> decl_const decl_notnull 1513 -%type <plpgsqltree.Expr> decl_defval decl_cursor_query 1514 -%type <tree.ResolvableTypeReference> decl_datatype 1515 -%type <str> decl_collate 1516 - 1517 -%type <str> expr_until_semi expr_until_paren stmt_until_semi 1518 -%type <str> expr_until_then expr_until_loop opt_expr_until_when 1519 -%type <plpgsqltree.Expr> opt_exitcond 1520 - 1521 -%type <forvariable> for_variable 1522 -%type <plpgsqltree.Expr> return_variable 1523 -%type <*tree.NumVal> foreach_slice 1524 -%type <plpgsqltree.Statement> for_control 1525 - 1526 -%type <str> any_identifier opt_block_label opt_loop_label opt_label query_options 1527 -%type <str> opt_error_level option_type 1528 - 1529 -%type <[]plpgsqltree.Statement> proc_sect 1530 -%type <[]plpgsqltree.ElseIf> stmt_elsifs 1531 -%type <[]plpgsqltree.Statement> stmt_else loop_body // TODO is this a list of statement? 1532 -%type <plpgsqltree.Statement> pl_block 1533 -%type <plpgsqltree.Statement> proc_stmt 1534 -%type <plpgsqltree.Statement> stmt_assign stmt_if stmt_loop stmt_while stmt_exit stmt_continue 1535 -%type <plpgsqltree.Statement> stmt_return stmt_raise stmt_assert stmt_execsql 1536 -%type <plpgsqltree.Statement> stmt_dynexecute stmt_for stmt_perform stmt_call stmt_getdiag 1537 -%type <plpgsqltree.Statement> stmt_open stmt_fetch stmt_move stmt_close stmt_null 1538 -%type <plpgsqltree.Statement> stmt_commit stmt_rollback 1539 -%type <plpgsqltree.Statement> stmt_case stmt_foreach_a 1540 - 1541 -%type <plpgsqltree.Statement> decl_stmt decl_statement 1542 -%type <[]plpgsqltree.Statement> decl_sect opt_decl_stmts decl_stmts 1543 - 1544 -%type <[]plpgsqltree.Exception> exception_sect proc_exceptions 1545 -%type <*plpgsqltree.Exception> proc_exception 1546 -%type <[]plpgsqltree.Condition> proc_conditions 1547 -%type <*plpgsqltree.Condition> proc_condition 1548 - 1549 -%type <*plpgsqltree.CaseWhen> case_when 1550 -%type <[]*plpgsqltree.CaseWhen> case_when_list 1551 -%type <[]plpgsqltree.Statement> opt_case_else 1552 - 1553 -%type <bool> getdiag_area_opt 1554 -%type <plpgsqltree.GetDiagnosticsItemList> getdiag_list // TODO don't know what this is 1555 -%type <*plpgsqltree.GetDiagnosticsItem> getdiag_list_item // TODO don't know what this is 1556 -%type <int32> getdiag_item 1557 - 1558 -%type <*plpgsqltree.RaiseOption> option_expr 1559 -%type <[]plpgsqltree.RaiseOption> option_exprs opt_option_exprs 1560 -%type <plpgsqltree.Expr> format_expr 1561 -%type <[]plpgsqltree.Expr> opt_format_exprs format_exprs 1562 - 1563 -%type <tree.CursorScrollOption> opt_scrollable 1564 - 1565 -%type <*tree.NumVal> opt_transaction_chain 1566 - 1567 -%type <str> unreserved_keyword 1568 -%% 1569 - 1570 -pl_function: 1571 - pl_block opt_semi 1572 - { 1573 - plpgsqllex.(*lexer).SetStmt($1.statement()) 1574 - } 1575 - 1576 -opt_semi: 1577 -| ';' 1578 -; 1579 - 1580 -pl_block: opt_block_label decl_sect BEGIN proc_sect exception_sect END opt_label 1581 - { 1582 - $$.val = &plpgsqltree.Block{ 1583 - Label: $1, 1584 - Decls: $2.statements(), 1585 - Body: $4.statements(), 1586 - Exceptions: $5.exceptions(), 1587 - } 1588 - } 1589 -; 1590 - 1591 -decl_sect: DECLARE opt_decl_stmts 1592 - { 1593 - $$.val = $2.statements() 1594 - } 1595 -| /* EMPTY */ 1596 - { 1597 - // Use a nil slice to indicate DECLARE was not used. 1598 - $$.val = []plpgsqltree.Statement(nil) 1599 - } 1600 -; 1601 - 1602 -opt_decl_stmts: decl_stmts 1603 - { 1604 - $$.val = $1.statements() 1605 - } 1606 -| /* EMPTY */ 1607 - { 1608 - $$.val = []plpgsqltree.Statement{} 1609 - } 1610 -; 1611 - 1612 -decl_stmts: decl_stmts decl_stmt 1613 - { 1614 - decs := $1.statements() 1615 - dec := $2.statement() 1616 - $$.val = append(decs, dec) 1617 - } 1618 -| decl_stmt 1619 - { 1620 - dec := $1.statement() 1621 - $$.val = []plpgsqltree.Statement{dec} 1622 - } 1623 -; 1624 - 1625 -decl_stmt : decl_statement 1626 - { 1627 - $$.val = $1.statement() 1628 - } 1629 -| DECLARE 1630 - { 1631 - // This is to allow useless extra "DECLARE" keywords in the declare section. 1632 - $$.val = (plpgsqltree.Statement)(nil) 1633 - } 1634 -// TODO(chengxiong): turn this block on and throw useful error if user 1635 -// tries to put the block label just before BEGIN instead of before 1636 -// DECLARE. 1637 -//| LESS_LESS any_identifier GREATER_GREATER 1638 -// { 1639 -// } 1640 -; 1641 - 1642 -decl_statement: decl_varname decl_const decl_datatype decl_collate decl_notnull decl_defval 1643 - { 1644 - $$.val = &plpgsqltree.Declaration{ 1645 - Var: plpgsqltree.Variable($1), 1646 - Constant: $2.bool(), 1647 - Typ: $3.typ(), 1648 - Collate: $4, 1649 - NotNull: $5.bool(), 1650 - Expr: $6.expr(), 1651 - } 1652 - } 1653 -| decl_varname ALIAS FOR decl_aliasitem ';' 1654 - { 1655 - return unimplemented(plpgsqllex, "alias for") 1656 - } 1657 -| decl_varname opt_scrollable CURSOR decl_cursor_args decl_is_for decl_cursor_query 1658 - { 1659 - $$.val = &plpgsqltree.CursorDeclaration{ 1660 - Name: plpgsqltree.Variable($1), 1661 - Scroll: $2.cursorScrollOption(), 1662 - Query: $6.sqlStatement(), 1663 - } 1664 - } 1665 -; 1666 - 1667 -opt_scrollable: 1668 - { 1669 - $$.val = tree.UnspecifiedScroll 1670 - } 1671 -| NO_SCROLL SCROLL 1672 - { 1673 - $$.val = tree.NoScroll 1674 - } 1675 -| SCROLL 1676 - { 1677 - $$.val = tree.Scroll 1678 - } 1679 -; 1680 - 1681 -decl_cursor_query: stmt_until_semi ';' 1682 - { 1683 - stmts, err := parser.Parse($1) 1684 - if err != nil { 1685 - return setErr(plpgsqllex, err) 1686 - } 1687 - if len(stmts) != 1 { 1688 - return setErr(plpgsqllex, errors.New("expected exactly one SQL statement for cursor")) 1689 - } 1690 - $$.val = stmts[0].AST 1691 - } 1692 -; 1693 - 1694 -decl_cursor_args: '(' 1695 - { 1696 - return unimplemented(plpgsqllex, "cursor arguments") 1697 - } 1698 -| /* EMPTY */ 1699 - { 1700 - } 1701 -; 1702 - 1703 -decl_cursor_arglist: decl_cursor_arg 1704 - { 1705 - } 1706 -| decl_cursor_arglist ',' decl_cursor_arg 1707 - { 1708 - } 1709 -; 1710 - 1711 -decl_cursor_arg: decl_varname decl_datatype 1712 - { 1713 - } 1714 -; 1715 - 1716 -decl_is_for: 1717 - IS /* Oracle */ 1718 -| FOR /* SQL standard */ 1719 - 1720 -decl_aliasitem: IDENT 1721 - { 1722 - } 1723 -| unreserved_keyword 1724 - { 1725 - } 1726 -; 1727 - 1728 -decl_varname: IDENT 1729 -| unreserved_keyword 1730 -; 1731 - 1732 -decl_const: 1733 - { 1734 - $$.val = false 1735 - } 1736 -| CONSTANT 1737 - { 1738 - $$.val = true 1739 - } 1740 -; 1741 - 1742 -decl_datatype: 1743 - { 1744 - // Read until reaching one of the tokens that can follow a declaration 1745 - // data type. 1746 - sqlStr, _, err := plpgsqllex.(*lexer).ReadSqlExpr( 1747 - ';', COLLATE, NOT, '=', COLON_EQUALS, DECLARE, 1748 - ) 1749 - if err != nil { 1750 - return setErr(plpgsqllex, err) 1751 - } 1752 - typ, err := plpgsqllex.(*lexer).GetTypeFromValidSQLSyntax(sqlStr) 1753 - if err != nil { 1754 - return setErr(plpgsqllex, err) 1755 - } 1756 - $$.val = typ 1757 - } 1758 -; 1759 - 1760 -decl_collate: 1761 - { 1762 - $$ = "" 1763 - } 1764 -| COLLATE IDENT 1765 - { 1766 - $$ = $2 1767 - } 1768 -| COLLATE unreserved_keyword 1769 - { 1770 - $$ = $2 1771 - } 1772 -; 1773 - 1774 -decl_notnull: 1775 - { 1776 - $$.val = false 1777 - } 1778 -| NOT NULL 1779 - { 1780 - $$.val = true 1781 - } 1782 -; 1783 - 1784 -decl_defval: ';' 1785 - { 1786 - $$.val = (plpgsqltree.Expr)(nil) 1787 - } 1788 -| decl_defkey ';' 1789 - { 1790 - expr, err := plpgsqllex.(*lexer).ParseExpr($1) 1791 - if err != nil { 1792 - return setErr(plpgsqllex, err) 1793 - } 1794 - $$.val = expr 1795 - } 1796 -; 1797 - 1798 -decl_defkey: assign_operator 1799 - { 1800 - sqlStr, _, err := plpgsqllex.(*lexer).ReadSqlExpr(';') 1801 - if err != nil { 1802 - return setErr(plpgsqllex, err) 1803 - } 1804 - $$ = sqlStr 1805 - } 1806 -| DEFAULT 1807 - { 1808 - sqlStr, _, err := plpgsqllex.(*lexer).ReadSqlExpr(';') 1809 - if err != nil { 1810 - return setErr(plpgsqllex, err) 1811 - } 1812 - $$ = sqlStr 1813 - } 1814 -; 1815 - 1816 -/* 1817 - * Ada-based PL/SQL uses := for assignment and variable defaults, while 1818 - * the SQL standard uses equals for these cases and for GET 1819 - * DIAGNOSTICS, so we support both. FOR and OPEN only support :=. 1820 - */ 1821 -assign_operator: '=' 1822 -| COLON_EQUALS 1823 -; 1824 - 1825 -proc_sect: 1826 - { 1827 - $$.val = []plpgsqltree.Statement{} 1828 - } 1829 -| proc_sect proc_stmt 1830 - { 1831 - stmts := $1.statements() 1832 - stmts = append(stmts, $2.statement()) 1833 - $$.val = stmts 1834 - } 1835 -; 1836 - 1837 -proc_stmt:pl_block ';' 1838 - { 1839 - $$.val = $1.block() 1840 - } 1841 -| stmt_assign 1842 - { 1843 - $$.val = $1.statement() 1844 - } 1845 -| stmt_if 1846 - { 1847 - $$.val = $1.statement() 1848 - } 1849 -| stmt_case 1850 - { 1851 - $$.val = $1.statement() 1852 - } 1853 -| stmt_loop 1854 - { 1855 - $$.val = $1.statement() 1856 - } 1857 -| stmt_while 1858 - { } 1859 -| stmt_for 1860 - { } 1861 -| stmt_foreach_a 1862 - { } 1863 -| stmt_exit 1864 - { 1865 - $$.val = $1.statement() 1866 - } 1867 -| stmt_continue 1868 - { 1869 - $$.val = $1.statement() 1870 - } 1871 -| stmt_return 1872 - { 1873 - $$.val = $1.statement() 1874 - } 1875 -| stmt_raise 1876 - { 1877 - $$.val = $1.statement() 1878 - } 1879 -| stmt_assert 1880 - { 1881 - $$.val = $1.statement() 1882 - } 1883 -| stmt_execsql 1884 - { 1885 - $$.val = $1.statement() 1886 - } 1887 -| stmt_dynexecute 1888 - { 1889 - $$.val = $1.statement() 1890 - } 1891 -| stmt_perform 1892 - { } 1893 -| stmt_call 1894 - { 1895 - $$.val = $1.statement() 1896 - } 1897 -| stmt_getdiag 1898 - { } 1899 -| stmt_open 1900 - { 1901 - $$.val = $1.statement() 1902 - } 1903 -| stmt_fetch 1904 - { 1905 - $$.val = $1.statement() 1906 - } 1907 -| stmt_move 1908 - { 1909 - $$.val = $1.statement() 1910 - } 1911 -| stmt_close 1912 - { 1913 - $$.val = $1.statement() 1914 - } 1915 -| stmt_null 1916 - { } 1917 -| stmt_commit 1918 - { } 1919 -| stmt_rollback 1920 - { } 1921 -; 1922 - 1923 -stmt_perform: PERFORM stmt_until_semi ';' 1924 - { 1925 - return unimplemented(plpgsqllex, "perform") 1926 - } 1927 -; 1928 - 1929 -stmt_call: CALL call_cmd ';' 1930 - { 1931 - $$.val = &plpgsqltree.Call{IsCall: true} 1932 - } 1933 -| DO call_cmd ';' 1934 - { 1935 - $$.val = &plpgsqltree.Call{IsCall: false} 1936 - } 1937 -; 1938 - 1939 -call_cmd: 1940 - { 1941 - _, _, err := plpgsqllex.(*lexer).ReadSqlExpr(';') 1942 - if err != nil { 1943 - return setErr(plpgsqllex, err) 1944 - } 1945 - } 1946 -; 1947 - 1948 -stmt_assign: IDENT assign_operator expr_until_semi ';' 1949 - { 1950 - expr, err := plpgsqllex.(*lexer).ParseExpr($3) 1951 - if err != nil { 1952 - return setErr(plpgsqllex, err) 1953 - } 1954 - $$.val = &plpgsqltree.Assignment{ 1955 - Var: plpgsqltree.Variable($1), 1956 - Value: expr, 1957 - } 1958 - } 1959 -; 1960 - 1961 -stmt_getdiag: GET getdiag_area_opt DIAGNOSTICS getdiag_list ';' 1962 - { 1963 - $$.val = &plpgsqltree.GetDiagnostics{ 1964 - IsStacked: $2.bool(), 1965 - DiagItems: $4.getDiagnosticsItemList(), 1966 - } 1967 - // TODO(jane): Check information items are valid for area option. 1968 - } 1969 -; 1970 - 1971 -getdiag_area_opt: 1972 - { 1973 - $$.val = false 1974 - } 1975 -| CURRENT 1976 - { 1977 - $$.val = false 1978 - } 1979 -| STACKED 1980 - { 1981 - $$.val = true 1982 - } 1983 -; 1984 - 1985 -getdiag_list: getdiag_list ',' getdiag_list_item 1986 - { 1987 - $$.val = append($1.getDiagnosticsItemList(), $3.getDiagnosticsItem()) 1988 - } 1989 -| getdiag_list_item 1990 - { 1991 - $$.val = plpgsqltree.GetDiagnosticsItemList{$1.getDiagnosticsItem()} 1992 - } 1993 -; 1994 - 1995 -getdiag_list_item: IDENT assign_operator getdiag_item 1996 - { 1997 - $$.val = &plpgsqltree.GetDiagnosticsItem{ 1998 - Kind : $3.getDiagnosticsKind(), 1999 - TargetName: $1, 2000 - // TODO(jane): set the target from $1. 2001 - } 2002 - } 2003 -; 2004 - 2005 -getdiag_item: unreserved_keyword { 2006 - switch $1 { 2007 - case "row_count": 2008 - $$.val = plpgsqltree.GetDiagnosticsRowCount; 2009 - case "pg_context": 2010 - $$.val = plpgsqltree.GetDiagnosticsContext; 2011 - case "pg_exception_detail": 2012 - $$.val = plpgsqltree.GetDiagnosticsErrorDetail; 2013 - case "pg_exception_hint": 2014 - $$.val = plpgsqltree.GetDiagnosticsErrorHint; 2015 - case "pg_exception_context": 2016 - $$.val = plpgsqltree.GetDiagnosticsErrorContext; 2017 - case "column_name": 2018 - $$.val = plpgsqltree.GetDiagnosticsColumnName; 2019 - case "constraint_name": 2020 - $$.val = plpgsqltree.GetDiagnosticsConstraintName; 2021 - case "pg_datatype_name": 2022 - $$.val = plpgsqltree.GetDiagnosticsDatatypeName; 2023 - case "message_text": 2024 - $$.val = plpgsqltree.GetDiagnosticsMessageText; 2025 - case "table_name": 2026 - $$.val = plpgsqltree.GetDiagnosticsTableName; 2027 - case "schema_name": 2028 - $$.val = plpgsqltree.GetDiagnosticsSchemaName; 2029 - case "returned_sqlstate": 2030 - $$.val = plpgsqltree.GetDiagnosticsReturnedSQLState; 2031 - default: 2032 - // TODO(jane): Should this use an unimplemented error instead? 2033 - return setErr(plpgsqllex, errors.Newf("unrecognized GET DIAGNOSTICS item: %s", redact.Safe($1))) 2034 - } 2035 -} 2036 -; 2037 - 2038 -getdiag_target: 2039 -// TODO(jane): remove ident. 2040 -IDENT 2041 - { 2042 - } 2043 -; 2044 - 2045 -stmt_if: IF expr_until_then THEN proc_sect stmt_elsifs stmt_else END_IF IF ';' 2046 - { 2047 - cond, err := plpgsqllex.(*lexer).ParseExpr($2) 2048 - if err != nil { 2049 - return setErr(plpgsqllex, err) 2050 - } 2051 - $$.val = &plpgsqltree.If{ 2052 - Condition: cond, 2053 - ThenBody: $4.statements(), 2054 - ElseIfList: $5.elseIf(), 2055 - ElseBody: $6.statements(), 2056 - } 2057 - } 2058 -; 2059 - 2060 -stmt_elsifs: 2061 - { 2062 - $$.val = []plpgsqltree.ElseIf{}; 2063 - } 2064 -| stmt_elsifs ELSIF expr_until_then THEN proc_sect 2065 - { 2066 - cond, err := plpgsqllex.(*lexer).ParseExpr($3) 2067 - if err != nil { 2068 - return setErr(plpgsqllex, err) 2069 - } 2070 - newStmt := plpgsqltree.ElseIf{ 2071 - Condition: cond, 2072 - Stmts: $5.statements(), 2073 - } 2074 - $$.val = append($1.elseIf() , newStmt) 2075 - } 2076 -; 2077 - 2078 -stmt_else: 2079 - { 2080 - $$.val = []plpgsqltree.Statement{}; 2081 - } 2082 -| ELSE proc_sect 2083 - { 2084 - $$.val = $2.statements(); 2085 - } 2086 -; 2087 - 2088 -stmt_case: CASE opt_expr_until_when case_when_list opt_case_else END_CASE CASE ';' 2089 - { 2090 - expr := &plpgsqltree.Case { 2091 - TestExpr: $2, 2092 - CaseWhenList: $3.caseWhens(), 2093 - } 2094 - if $4.val != nil { 2095 - expr.HaveElse = true 2096 - expr.ElseStmts = $4.statements() 2097 - } 2098 - $$.val = expr 2099 - } 2100 -; 2101 - 2102 -opt_expr_until_when: 2103 - { 2104 - if plpgsqllex.(*lexer).Peek().id != WHEN { 2105 - sqlStr, _, err := plpgsqllex.(*lexer).ReadSqlExpr(WHEN) 2106 - if err != nil { 2107 - return setErr(plpgsqllex, err) 2108 - } 2109 - $$ = sqlStr 2110 - } else { 2111 - $$ = "" 2112 - } 2113 - } 2114 -; 2115 - 2116 -case_when_list: case_when_list case_when 2117 - { 2118 - stmts := $1.caseWhens() 2119 - stmts = append(stmts, $2.caseWhen()) 2120 - $$.val = stmts 2121 - } 2122 -| case_when 2123 - { 2124 - stmts := []*plpgsqltree.CaseWhen{} 2125 - stmts = append(stmts, $1.caseWhen()) 2126 - $$.val = stmts 2127 - } 2128 -; 2129 - 2130 -case_when: WHEN expr_until_then THEN proc_sect 2131 - { 2132 - expr := &plpgsqltree.CaseWhen{ 2133 - Expr: $2, 2134 - Stmts: $4.statements(), 2135 - } 2136 - $$.val = expr 2137 - } 2138 -; 2139 - 2140 -opt_case_else: 2141 - { 2142 - $$.val = nil 2143 - } 2144 -| ELSE proc_sect 2145 - { 2146 - $$.val = $2.statements() 2147 - } 2148 -; 2149 - 2150 -stmt_loop: opt_loop_label LOOP loop_body opt_label ';' 2151 - { 2152 - loopLabel, loopEndLabel := $1, $4 2153 - if err := checkLoopLabels(loopLabel, loopEndLabel); err != nil { 2154 - return setErr(plpgsqllex, err) 2155 - } 2156 - $$.val = &plpgsqltree.Loop{ 2157 - Label: $1, 2158 - Body: $3.statements(), 2159 - } 2160 - } 2161 -; 2162 - 2163 -stmt_while: opt_loop_label WHILE expr_until_loop LOOP loop_body opt_label ';' 2164 - { 2165 - loopLabel, loopEndLabel := $1, $6 2166 - if err := checkLoopLabels(loopLabel, loopEndLabel); err != nil { 2167 - return setErr(plpgsqllex, err) 2168 - } 2169 - cond, err := plpgsqllex.(*lexer).ParseExpr($3) 2170 - if err != nil { 2171 - return setErr(plpgsqllex, err) 2172 - } 2173 - $$.val = &plpgsqltree.While{ 2174 - Label: $1, 2175 - Condition: cond, 2176 - Body: $5.statements(), 2177 - } 2178 - } 2179 -; 2180 - 2181 -stmt_for: opt_loop_label FOR for_control loop_body 2182 - { 2183 - return unimplemented(plpgsqllex, "for loop") 2184 - } 2185 -; 2186 - 2187 -for_control: for_variable IN 2188 - // TODO need to parse the sql expression here. 2189 - { 2190 - return unimplemented(plpgsqllex, "for loop") 2191 - } 2192 -; 2193 - 2194 -/* 2195 - * Processing the for_variable is tricky because we don't yet know if the 2196 - * FOR is an integer FOR loop or a loop over query results. In the former 2197 - * case, the variable is just a name that we must instantiate as a loop 2198 - * local variable, regardless of any other definition it might have. 2199 - * Therefore, we always save the actual identifier into $$.name where it 2200 - * can be used for that case. We also save the outer-variable definition, 2201 - * if any, because that's what we need for the loop-over-query case. Note 2202 - * that we must NOT apply check_assignable() or any other semantic check 2203 - * until we know what's what. 2204 - * 2205 - * However, if we see a comma-separated list of names, we know that it 2206 - * can't be an integer FOR loop and so it's OK to check the variables 2207 - * immediately. In particular, for T_WORD followed by comma, we should 2208 - * complain that the name is not known rather than say it's a syntax error. 2209 - * Note that the non-error result of this case sets *both* $$.scalar and 2210 - * $$.row; see the for_control production. 2211 - */ 2212 -for_variable: any_identifier 2213 - { 2214 - return unimplemented(plpgsqllex, "for loop") 2215 - } 2216 -; 2217 - 2218 -stmt_foreach_a: opt_loop_label FOREACH for_variable foreach_slice IN ARRAY expr_until_loop loop_body 2219 - { 2220 - return unimplemented(plpgsqllex, "for each loop") 2221 - } 2222 -; 2223 - 2224 -foreach_slice: 2225 - { 2226 - } 2227 -| SLICE ICONST 2228 - { 2229 - } 2230 -; 2231 - 2232 -stmt_exit: EXIT opt_label opt_exitcond 2233 - { 2234 - $$.val = &plpgsqltree.Exit{ 2235 - Label: $2, 2236 - Condition: $3.expr(), 2237 - } 2238 - } 2239 -; 2240 - 2241 -stmt_continue: CONTINUE opt_label opt_exitcond 2242 - { 2243 - $$.val = &plpgsqltree.Continue{ 2244 - Label: $2, 2245 - Condition: $3.expr(), 2246 - } 2247 - } 2248 -; 2249 - 2250 - // TODO handle variable names 2251 - // 1. verify if the first token is a variable (this means that we need to track variable scope during parsing) 2252 - // 2. if yes, check next token is ';' 2253 - // 3. if no, expecting a sql expression "read_sql_expression" 2254 - // we can just read until a ';', then do the sql expression validation during compile time. 2255 - 2256 -stmt_return: RETURN return_variable ';' 2257 - { 2258 - $$.val = &plpgsqltree.Return{ 2259 - Expr: $2.expr(), 2260 - } 2261 - } 2262 -| RETURN_NEXT NEXT 2263 - { 2264 - return unimplemented(plpgsqllex, "return next") 2265 - } 2266 -| RETURN_QUERY QUERY 2267 - { 2268 - return unimplemented (plpgsqllex, "return query") 2269 - } 2270 -; 2271 - 2272 - 2273 -query_options: 2274 - { 2275 - _, terminator, err := plpgsqllex.(*lexer).ReadSqlExpr(EXECUTE, ';') 2276 - if err != nil { 2277 - return setErr(plpgsqllex, err) 2278 - } 2279 - if terminator == EXECUTE { 2280 - return unimplemented (plpgsqllex, "return dynamic sql query") 2281 - } 2282 - _, _, err = plpgsqllex.(*lexer).ReadSqlExpr(';') 2283 - if err != nil { 2284 - return setErr(plpgsqllex, err) 2285 - } 2286 - } 2287 -; 2288 - 2289 - 2290 -return_variable: expr_until_semi 2291 - { 2292 - expr, err := plpgsqllex.(*lexer).ParseExpr($1) 2293 - if err != nil { 2294 - return setErr(plpgsqllex, err) 2295 - } 2296 - $$.val = expr 2297 - } 2298 -; 2299 - 2300 -stmt_raise: 2301 - RAISE ';' 2302 - { 2303 - return unimplemented(plpgsqllex, "empty RAISE statement") 2304 - } 2305 -| RAISE opt_error_level SCONST opt_format_exprs opt_option_exprs ';' 2306 - { 2307 - $$.val = &plpgsqltree.Raise{ 2308 - LogLevel: $2, 2309 - Message: $3, 2310 - Params: $4.exprs(), 2311 - Options: $5.raiseOptions(), 2312 - } 2313 - } 2314 -| RAISE opt_error_level IDENT opt_option_exprs ';' 2315 - { 2316 - $$.val = &plpgsqltree.Raise{ 2317 - LogLevel: $2, 2318 - CodeName: $3, 2319 - Options: $4.raiseOptions(), 2320 - } 2321 - } 2322 -| RAISE opt_error_level SQLSTATE SCONST opt_option_exprs ';' 2323 - { 2324 - $$.val = &plpgsqltree.Raise{ 2325 - LogLevel: $2, 2326 - Code: $4, 2327 - Options: $5.raiseOptions(), 2328 - } 2329 - } 2330 -| RAISE opt_error_level USING option_exprs ';' 2331 - { 2332 - $$.val = &plpgsqltree.Raise{ 2333 - LogLevel: $2, 2334 - Options: $4.raiseOptions(), 2335 - } 2336 - } 2337 -; 2338 - 2339 -opt_error_level: 2340 - DEBUG 2341 -| LOG 2342 -| INFO 2343 -| NOTICE 2344 -| WARNING 2345 -| EXCEPTION 2346 -| /* EMPTY */ 2347 - { 2348 - $$ = "" 2349 - } 2350 -; 2351 - 2352 -opt_option_exprs: 2353 - USING option_exprs 2354 - { 2355 - $$.val = $2.raiseOptions() 2356 - } 2357 -| /* EMPTY */ 2358 - { 2359 - $$.val = []plpgsqltree.RaiseOption{} 2360 - } 2361 -; 2362 - 2363 -option_exprs: 2364 - option_exprs ',' option_expr 2365 - { 2366 - option := $3.raiseOption() 2367 - $$.val = append($1.raiseOptions(), *option) 2368 - } 2369 -| option_expr 2370 - { 2371 - option := $1.raiseOption() 2372 - $$.val = []plpgsqltree.RaiseOption{*option} 2373 - } 2374 -; 2375 - 2376 -option_expr: 2377 - option_type assign_operator 2378 - { 2379 - // Read until reaching one of the tokens that can follow a raise option. 2380 - sqlStr, _, err := plpgsqllex.(*lexer).ReadSqlExpr(',', ';') 2381 - if err != nil { 2382 - return setErr(plpgsqllex, err) 2383 - } 2384 - optionExpr, err := plpgsqllex.(*lexer).ParseExpr(sqlStr) 2385 - if err != nil { 2386 - return setErr(plpgsqllex, err) 2387 - } 2388 - $$.val = &plpgsqltree.RaiseOption{ 2389 - OptType: $1, 2390 - Expr: optionExpr, 2391 - } 2392 - } 2393 -; 2394 - 2395 -option_type: 2396 - MESSAGE 2397 -| DETAIL 2398 -| HINT 2399 -| ERRCODE 2400 -| COLUMN 2401 -| CONSTRAINT 2402 -| DATATYPE 2403 -| TABLE 2404 -| SCHEMA 2405 -; 2406 - 2407 -opt_format_exprs: 2408 - format_exprs 2409 - { 2410 - $$.val = $1.exprs() 2411 - } 2412 - | /* EMPTY */ 2413 - { 2414 - $$.val = []plpgsqltree.Expr{} 2415 - } 2416 -; 2417 - 2418 -format_exprs: 2419 - format_expr 2420 - { 2421 - $$.val = []plpgsqltree.Expr{$1.expr()} 2422 - } 2423 -| format_exprs format_expr 2424 - { 2425 - $$.val = append($1.exprs(), $2.expr()) 2426 - } 2427 -; 2428 - 2429 -format_expr: ',' 2430 - { 2431 - // Read until reaching a token that can follow a raise format parameter. 2432 - sqlStr, _, err := plpgsqllex.(*lexer).ReadSqlExpr(',', ';', USING) 2433 - if err != nil { 2434 - return setErr(plpgsqllex, err) 2435 - } 2436 - param, err := plpgsqllex.(*lexer).ParseExpr(sqlStr) 2437 - if err != nil { 2438 - return setErr(plpgsqllex, err) 2439 - } 2440 - $$.val = param 2441 - } 2442 -; 2443 - 2444 -stmt_assert: ASSERT assert_cond ';' 2445 - { 2446 - $$.val = &plpgsqltree.Assert{} 2447 - } 2448 -; 2449 - 2450 -assert_cond: 2451 - { 2452 - _, terminator, err := plpgsqllex.(*lexer).ReadSqlExpr(',', ';') 2453 - if err != nil { 2454 - return setErr(plpgsqllex, err) 2455 - } 2456 - if terminator == ',' { 2457 - _, _, err = plpgsqllex.(*lexer).ReadSqlExpr(';') 2458 - if err != nil { 2459 - return setErr(plpgsqllex, err) 2460 - } 2461 - } 2462 - } 2463 -; 2464 - 2465 -loop_body: proc_sect END LOOP 2466 - { 2467 - $$.val = $1.statements() 2468 - } 2469 -; 2470 - 2471 -stmt_execsql: stmt_execsql_start 2472 - { 2473 - stmt, err := plpgsqllex.(*lexer).MakeExecSqlStmt() 2474 - if err != nil { 2475 - return setErr(plpgsqllex, err) 2476 - } 2477 - $$.val = stmt 2478 - } 2479 -; 2480 - 2481 -stmt_execsql_start: 2482 - IMPORT 2483 -| INSERT 2484 -| UPSERT 2485 -| MERGE 2486 -| IDENT 2487 -; 2488 - 2489 -stmt_dynexecute: EXECUTE 2490 - { 2491 - stmt, err := plpgsqllex.(*lexer).MakeDynamicExecuteStmt() 2492 - if err != nil { 2493 - return setErr(plpgsqllex, err) 2494 - } 2495 - $$.val = stmt 2496 - } 2497 -; 2498 - 2499 -stmt_open: OPEN IDENT ';' 2500 - { 2501 - $$.val = &plpgsqltree.Open{CurVar: plpgsqltree.Variable($2)} 2502 - } 2503 -| OPEN IDENT opt_scrollable FOR EXECUTE 2504 - { 2505 - return unimplemented(plpgsqllex, "cursor for execute") 2506 - } 2507 -| OPEN IDENT opt_scrollable FOR stmt_until_semi ';' 2508 - { 2509 - stmts, err := parser.Parse($5) 2510 - if err != nil { 2511 - return setErr(plpgsqllex, err) 2512 - } 2513 - if len(stmts) != 1 { 2514 - return setErr(plpgsqllex, errors.New("expected exactly one SQL statement for cursor")) 2515 - } 2516 - $$.val = &plpgsqltree.Open{ 2517 - CurVar: plpgsqltree.Variable($2), 2518 - Scroll: $3.cursorScrollOption(), 2519 - Query: stmts[0].AST, 2520 - } 2521 - } 2522 -; 2523 - 2524 -stmt_fetch: FETCH 2525 - { 2526 - fetch, err := plpgsqllex.(*lexer).MakeFetchOrMoveStmt(false) 2527 - if err != nil { 2528 - return setErr(plpgsqllex, err) 2529 - } 2530 - $$.val = fetch 2531 - } 2532 -; 2533 - 2534 -stmt_move: MOVE 2535 - { 2536 - move, err := plpgsqllex.(*lexer).MakeFetchOrMoveStmt(true) 2537 - if err != nil { 2538 - return setErr(plpgsqllex, err) 2539 - } 2540 - $$.val = move 2541 - } 2542 -; 2543 - 2544 -stmt_close: CLOSE IDENT ';' 2545 - { 2546 - $$.val = &plpgsqltree.Close{CurVar: plpgsqltree.Variable($2)} 2547 - } 2548 -; 2549 - 2550 -stmt_null: NULL ';' 2551 - { 2552 - $$.val = &plpgsqltree.Null{}; 2553 - } 2554 -; 2555 - 2556 -stmt_commit: COMMIT opt_transaction_chain ';' 2557 - { 2558 - return unimplemented(plpgsqllex, "commit") 2559 - } 2560 -; 2561 - 2562 -stmt_rollback: ROLLBACK opt_transaction_chain ';' 2563 - { 2564 - return unimplemented(plpgsqllex, "rollback") 2565 - } 2566 -; 2567 - 2568 -opt_transaction_chain: 2569 -AND CHAIN 2570 - { } 2571 -| AND NO CHAIN 2572 - { } 2573 -| /* EMPTY */ 2574 - { } 2575 - 2576 -exception_sect: /* EMPTY */ 2577 - { 2578 - $$.val = []plpgsqltree.Exception(nil) 2579 - } 2580 -| EXCEPTION proc_exceptions 2581 - { 2582 - $$.val = $2.exceptions() 2583 - } 2584 -; 2585 - 2586 -proc_exceptions: proc_exceptions proc_exception 2587 - { 2588 - e := $2.exception() 2589 - $$.val = append($1.exceptions(), *e) 2590 - } 2591 -| proc_exception 2592 - { 2593 - e := $1.exception() 2594 - $$.val = []plpgsqltree.Exception{*e} 2595 - } 2596 -; 2597 - 2598 -proc_exception: WHEN proc_conditions THEN proc_sect 2599 - { 2600 - $$.val = &plpgsqltree.Exception{ 2601 - Conditions: $2.conditions(), 2602 - Action: $4.statements(), 2603 - } 2604 - } 2605 -; 2606 - 2607 -proc_conditions: proc_conditions OR proc_condition 2608 - { 2609 - c := $3.condition() 2610 - $$.val = append($1.conditions(), *c) 2611 - } 2612 -| proc_condition 2613 - { 2614 - c := $1.condition() 2615 - $$.val = []plpgsqltree.Condition{*c} 2616 - } 2617 -; 2618 - 2619 -proc_condition: any_identifier 2620 - { 2621 - $$.val = &plpgsqltree.Condition{SqlErrName: $1} 2622 - } 2623 -| SQLSTATE SCONST 2624 - { 2625 - $$.val = &plpgsqltree.Condition{SqlErrState: $2} 2626 - } 2627 -; 2628 - 2629 -expr_until_semi: 2630 - { 2631 - sqlStr, _, err := plpgsqllex.(*lexer).ReadSqlExpr(';') 2632 - if err != nil { 2633 - return setErr(plpgsqllex, err) 2634 - } 2635 - $$ = sqlStr 2636 - } 2637 -; 2638 - 2639 -stmt_until_semi: 2640 - { 2641 - sqlStr, _, err := plpgsqllex.(*lexer).ReadSqlStatement(';') 2642 - if err != nil { 2643 - return setErr(plpgsqllex, err) 2644 - } 2645 - $$ = sqlStr 2646 - } 2647 -; 2648 - 2649 -expr_until_then: 2650 - { 2651 - sqlStr, _, err := plpgsqllex.(*lexer).ReadSqlExpr(THEN) 2652 - if err != nil { 2653 - return setErr(plpgsqllex, err) 2654 - } 2655 - $$ = sqlStr 2656 - } 2657 -; 2658 - 2659 -expr_until_loop: 2660 - { 2661 - sqlStr, _, err := plpgsqllex.(*lexer).ReadSqlExpr(LOOP) 2662 - if err != nil { 2663 - return setErr(plpgsqllex, err) 2664 - } 2665 - $$ = sqlStr 2666 - } 2667 -; 2668 - 2669 -expr_until_paren : 2670 - { 2671 - sqlStr, _, err := plpgsqllex.(*lexer).ReadSqlExpr(')') 2672 - if err != nil { 2673 - return setErr(plpgsqllex, err) 2674 - } 2675 - $$ = sqlStr 2676 - } 2677 -; 2678 - 2679 -opt_block_label : 2680 - { 2681 - $$ = "" 2682 - } 2683 -| LESS_LESS any_identifier GREATER_GREATER 2684 - { 2685 - $$ = $2 2686 - } 2687 -; 2688 - 2689 -opt_loop_label: 2690 - { 2691 - $$ = "" 2692 - } 2693 -| LESS_LESS any_identifier GREATER_GREATER 2694 - { 2695 - $$ = $2 2696 - } 2697 -; 2698 - 2699 -opt_label: 2700 - { 2701 - $$ = "" 2702 - } 2703 -| any_identifier 2704 - { 2705 - $$ = $1 2706 - } 2707 -; 2708 - 2709 -opt_exitcond: ';' 2710 - { } 2711 -| WHEN expr_until_semi ';' 2712 - { 2713 - expr, err := plpgsqllex.(*lexer).ParseExpr($2) 2714 - if err != nil { 2715 - return setErr(plpgsqllex, err) 2716 - } 2717 - $$.val = expr 2718 - } 2719 -; 2720 - 2721 -/* 2722 - * need to allow DATUM because scanner will have tried to resolve as variable 2723 - */ 2724 -any_identifier: 2725 -IDENT 2726 -| unreserved_keyword 2727 -; 2728 - 2729 -unreserved_keyword: 2730 - ABSOLUTE 2731 -| ALIAS 2732 -| AND 2733 -| ARRAY 2734 -| ASSERT 2735 -| BACKWARD 2736 -| CALL 2737 -| CHAIN 2738 -| CLOSE 2739 -| COLLATE 2740 -| COLUMN 2741 -| COLUMN_NAME 2742 -| COMMIT 2743 -| CONSTANT 2744 -| CONSTRAINT 2745 -| CONSTRAINT_NAME 2746 -| CONTINUE 2747 -| CURRENT 2748 -| CURSOR 2749 -| DATATYPE 2750 -| DEBUG 2751 -| DEFAULT 2752 -| DETAIL 2753 -| DIAGNOSTICS 2754 -| DO 2755 -| DUMP 2756 -| ELSIF 2757 -| ERRCODE 2758 -| ERROR 2759 -| EXCEPTION 2760 -| EXIT 2761 -| FETCH 2762 -| FIRST 2763 -| FORWARD 2764 -| GET 2765 -| HINT 2766 -| IMPORT 2767 -| INFO 2768 -| INSERT 2769 -| IS 2770 -| LAST 2771 -| LOG 2772 -| MERGE 2773 -| MESSAGE 2774 -| MESSAGE_TEXT 2775 -| MOVE 2776 -| NEXT 2777 -| NO 2778 -| NO_SCROLL 2779 -| NOTICE 2780 -| OPEN 2781 -| OPTION 2782 -| PERFORM 2783 -| PG_CONTEXT 2784 -| PG_DATATYPE_NAME 2785 -| PG_EXCEPTION_CONTEXT 2786 -| PG_EXCEPTION_DETAIL 2787 -| PG_EXCEPTION_HINT 2788 -| PRINT_STRICT_PARAMS 2789 -| PRIOR 2790 -| QUERY 2791 -| RAISE 2792 -| RELATIVE 2793 -| RETURN 2794 -| RETURN_NEXT 2795 -| RETURN_QUERY 2796 -| RETURNED_SQLSTATE 2797 -| REVERSE 2798 -| ROLLBACK 2799 -| ROW_COUNT 2800 -| ROWTYPE 2801 -| SCHEMA 2802 -| SCHEMA_NAME 2803 -| SCROLL 2804 -| SLICE 2805 -| SQLSTATE 2806 -| STACKED 2807 -| TABLE 2808 -| TABLE_NAME 2809 -| TYPE 2810 -| UPSERT 2811 -| USE_COLUMN 2812 -| USE_VARIABLE 2813 -| VARIABLE_CONFLICT 2814 -| WARNING 2815 - 2816 -reserved_keyword: 2817 - ALL 2818 -| BEGIN 2819 -| BY 2820 -| CASE 2821 -| DECLARE 2822 -| ELSE 2823 -| END 2824 -| END_CASE 2825 -| END_IF 2826 -| EXECUTE 2827 -| FOR 2828 -| FOREACH 2829 -| FROM 2830 -| IF 2831 -| IN 2832 -| INTO 2833 -| LOOP 2834 -| NOT 2835 -| NULL 2836 -| OR 2837 -| STRICT 2838 -| THEN 2839 -| TO 2840 -| USING 2841 -| WHEN 2842 -| WHILE 2843 - 2844 -%% 2845 diff --git a/pkg/sql/scanner/plpgsql_scan.go b/pkg/sql/scanner/plpgsql_scan.go 2846 deleted file mode 100644 2847 index 3dc5500..0000000 2848 --- a/pkg/sql/scanner/plpgsql_scan.go 2849 +++ /dev/null 2850 @@ -1,246 +0,0 @@ 2851 -// Copyright 2023 The Cockroach Authors. 2852 -// 2853 -// Use of this software is governed by the Business Source License 2854 -// included in the file licenses/BSL.txt. 2855 -// 2856 -// As of the Change Date specified in that file, in accordance with 2857 -// the Business Source License, use of this software will be governed 2858 -// by the Apache License, Version 2.0, included in the file 2859 -// licenses/APL.txt. 2860 - 2861 -package scanner 2862 - 2863 -import ( 2864 - "fmt" 2865 - "go/constant" 2866 - "go/token" 2867 - 2868 - sqllex "github.com/cockroachdb/cockroachdb-parser/pkg/sql/lexbase" 2869 - "github.com/cockroachdb/cockroachdb-parser/pkg/sql/plpgsql/parser/lexbase" 2870 -) 2871 - 2872 -// PLpgSQLScanner is a scanner with a PLPGSQL specific scan function 2873 -type PLpgSQLScanner struct { 2874 - Scanner 2875 -} 2876 - 2877 -// Scan scans the next token and populates its information into lval. 2878 -// This scan function contains rules for plpgsql. 2879 -func (s *PLpgSQLScanner) Scan(lval ScanSymType) { 2880 - ch, skipWhiteSpace := s.scanSetup(lval) 2881 - 2882 - if skipWhiteSpace { 2883 - return 2884 - } 2885 - 2886 - switch ch { 2887 - case '$': 2888 - if s.scanDollarQuotedString(lval) { 2889 - lval.SetID(lexbase.SCONST) 2890 - return 2891 - } 2892 - return 2893 - 2894 - case identQuote: 2895 - // "[^"]" 2896 - if s.scanString(lval, identQuote, false /* allowEscapes */, true /* requireUTF8 */) { 2897 - lval.SetID(lexbase.IDENT) 2898 - } 2899 - return 2900 - 2901 - case singleQuote: 2902 - // '[^']' 2903 - if s.scanString(lval, ch, false /* allowEscapes */, true /* requireUTF8 */) { 2904 - lval.SetID(lexbase.SCONST) 2905 - } 2906 - return 2907 - 2908 - case 'b': 2909 - // Bytes? 2910 - if s.peek() == singleQuote { 2911 - // b'[^']' 2912 - s.pos++ 2913 - if s.scanString(lval, singleQuote, true /* allowEscapes */, false /* requireUTF8 */) { 2914 - lval.SetID(lexbase.BCONST) 2915 - } 2916 - return 2917 - } 2918 - s.scanIdent(lval) 2919 - return 2920 - 2921 - case '.': 2922 - switch t := s.peek(); { 2923 - case t == '.': // .. 2924 - s.pos++ 2925 - lval.SetID(lexbase.DOT_DOT) 2926 - return 2927 - case sqllex.IsDigit(t): 2928 - s.scanNumber(lval, ch) 2929 - return 2930 - } 2931 - return 2932 - 2933 - case '!': 2934 - switch s.peek() { 2935 - case '=': // != 2936 - s.pos++ 2937 - lval.SetID(lexbase.NOT_EQUALS) 2938 - return 2939 - } 2940 - return 2941 - 2942 - case '<': 2943 - switch s.peek() { 2944 - case '<': // << 2945 - s.pos++ 2946 - lval.SetID(lexbase.LESS_LESS) 2947 - return 2948 - case '=': // <= 2949 - s.pos++ 2950 - lval.SetID(lexbase.LESS_EQUALS) 2951 - return 2952 - } 2953 - return 2954 - 2955 - case '>': 2956 - switch s.peek() { 2957 - case '>': // >> 2958 - s.pos++ 2959 - lval.SetID(lexbase.GREATER_GREATER) 2960 - return 2961 - case '=': // >= 2962 - s.pos++ 2963 - lval.SetID(lexbase.GREATER_EQUALS) 2964 - return 2965 - } 2966 - return 2967 - 2968 - case ':': 2969 - switch s.peek() { 2970 - case ':': 2971 - s.pos++ 2972 - lval.SetID(lexbase.TYPECAST) 2973 - return 2974 - case '=': 2975 - s.pos++ 2976 - lval.SetID(lexbase.COLON_EQUALS) 2977 - return 2978 - } 2979 - return 2980 - 2981 - default: 2982 - if sqllex.IsDigit(ch) { 2983 - s.scanNumber(lval, ch) 2984 - return 2985 - } 2986 - if sqllex.IsIdentStart(ch) { 2987 - s.scanIdent(lval) 2988 - return 2989 - } 2990 - } 2991 - // Everything else is a single character token which we already initialized 2992 - // lval for above. 2993 -} 2994 - 2995 -func (s *PLpgSQLScanner) scanNumber(lval ScanSymType, ch int) { 2996 - start := s.pos - 1 2997 - isHex := false 2998 - hasDecimal := ch == '.' 2999 - hasExponent := false 3000 - 3001 - for { 3002 - ch := s.peek() 3003 - if (isHex && sqllex.IsHexDigit(ch)) || sqllex.IsDigit(ch) { 3004 - s.pos++ 3005 - continue 3006 - } 3007 - if ch == 'x' || ch == 'X' { 3008 - if isHex || s.in[start] != '0' || s.pos != start+1 { 3009 - lval.SetID(lexbase.ERROR) 3010 - lval.SetStr(errInvalidHexNumeric) 3011 - return 3012 - } 3013 - s.pos++ 3014 - isHex = true 3015 - continue 3016 - } 3017 - if isHex { 3018 - break 3019 - } 3020 - if ch == '.' { 3021 - if hasDecimal || hasExponent { 3022 - break 3023 - } 3024 - s.pos++ 3025 - if s.peek() == '.' { 3026 - // Found ".." while scanning a number: back up to the end of the 3027 - // integer. 3028 - s.pos-- 3029 - break 3030 - } 3031 - hasDecimal = true 3032 - continue 3033 - } 3034 - if ch == 'e' || ch == 'E' { 3035 - if hasExponent { 3036 - break 3037 - } 3038 - hasExponent = true 3039 - s.pos++ 3040 - ch = s.peek() 3041 - if ch == '-' || ch == '+' { 3042 - s.pos++ 3043 - } 3044 - ch = s.peek() 3045 - if !sqllex.IsDigit(ch) { 3046 - lval.SetID(lexbase.ERROR) 3047 - lval.SetStr("invalid floating point literal") 3048 - return 3049 - } 3050 - continue 3051 - } 3052 - break 3053 - } 3054 - 3055 - lval.SetStr(s.in[start:s.pos]) 3056 - if hasDecimal || hasExponent { 3057 - lval.SetID(lexbase.FCONST) 3058 - floatConst := constant.MakeFromLiteral(lval.Str(), token.FLOAT, 0) 3059 - if floatConst.Kind() == constant.Unknown { 3060 - lval.SetID(lexbase.ERROR) 3061 - lval.SetStr(fmt.Sprintf("could not make constant float from literal %q", lval.Str())) 3062 - return 3063 - } 3064 - lval.SetUnionVal(NewNumValFn(floatConst, lval.Str(), false /* negative */)) 3065 - } else { 3066 - if isHex && s.pos == start+2 { 3067 - lval.SetID(lexbase.ERROR) 3068 - lval.SetStr(errInvalidHexNumeric) 3069 - return 3070 - } 3071 - 3072 - // Strip off leading zeros from non-hex (decimal) literals so that 3073 - // constant.MakeFromLiteral doesn't inappropriately interpret the 3074 - // string as an octal literal. Note: we can't use strings.TrimLeft 3075 - // here, because it will truncate '0' to ''. 3076 - if !isHex { 3077 - for len(lval.Str()) > 1 && lval.Str()[0] == '0' { 3078 - lval.SetStr(lval.Str()[1:]) 3079 - } 3080 - } 3081 - 3082 - lval.SetID(lexbase.ICONST) 3083 - intConst := constant.MakeFromLiteral(lval.Str(), token.INT, 0) 3084 - if intConst.Kind() == constant.Unknown { 3085 - lval.SetID(lexbase.ERROR) 3086 - lval.SetStr(fmt.Sprintf("could not make constant int from literal %q", lval.Str())) 3087 - return 3088 - } 3089 - lval.SetUnionVal(NewNumValFn(intConst, lval.Str(), false /* negative */)) 3090 - } 3091 -} 3092 - 3093 -func (s *PLpgSQLScanner) scanIdent(lval ScanSymType) { 3094 - s.lowerCaseAndNormalizeIdent(lval) 3095 - lval.SetID(lexbase.GetKeywordID(lval.Str())) 3096 -} 3097 -- 3098 2.38.1 3099