diff --git a/Makefile b/Makefile index b5fa7858..3989ce29 100644 --- a/Makefile +++ b/Makefile @@ -230,7 +230,7 @@ examples/normalize_error: examples/normalize_error.c $(ARLIB) examples/simple_plpgsql: examples/simple_plpgsql.c $(ARLIB) $(CC) $(TEST_CFLAGS) -o $@ -g examples/simple_plpgsql.c $(ARLIB) $(TEST_LDFLAGS) -TESTS = test/complex test/concurrency test/deparse test/fingerprint test/fingerprint_opts test/normalize test/parse test/parse_opts test/parse_protobuf test/parse_protobuf_opts test/parse_plpgsql test/scan test/split +TESTS = test/complex test/concurrency test/deparse test/fingerprint test/fingerprint_opts test/normalize test/normalize_opts test/parse test/parse_opts test/parse_protobuf test/parse_protobuf_opts test/parse_plpgsql test/scan test/split test: $(TESTS) ifeq ($(VALGRIND),1) $(VALGRIND_MEMCHECK) test/complex || (cat test/valgrind.log && false) @@ -239,6 +239,7 @@ ifeq ($(VALGRIND),1) $(VALGRIND_MEMCHECK) test/fingerprint || (cat test/valgrind.log && false) $(VALGRIND_MEMCHECK) test/fingerprint_opts || (cat test/valgrind.log && false) $(VALGRIND_MEMCHECK) test/normalize || (cat test/valgrind.log && false) + $(VALGRIND_MEMCHECK) test/normalize_opts || (cat test/valgrind.log && false) $(VALGRIND_MEMCHECK) test/parse || (cat test/valgrind.log && false) $(VALGRIND_MEMCHECK) test/parse_opts || (cat test/valgrind.log && false) $(VALGRIND_MEMCHECK) test/parse_protobuf || (cat test/valgrind.log && false) @@ -255,6 +256,7 @@ else test/fingerprint test/fingerprint_opts test/normalize + test/normalize_opts test/parse test/parse_opts test/parse_protobuf @@ -287,6 +289,9 @@ test/fingerprint_opts: test/fingerprint_opts.c test/fingerprint_opts_tests.c $(A test/normalize: test/normalize.c test/normalize_tests.c $(ARLIB) $(CC) $(TEST_CFLAGS) -o $@ test/normalize.c $(ARLIB) $(TEST_LDFLAGS) +test/normalize_opts: test/normalize_opts.c test/normalize_opts_tests.c $(ARLIB) + $(CC) $(TEST_CFLAGS) -o $@ test/normalize_opts.c $(ARLIB) $(TEST_LDFLAGS) + test/parse: test/parse.c test/parse_tests.c $(ARLIB) $(CC) $(TEST_CFLAGS) -o $@ test/parse.c $(ARLIB) $(TEST_LDFLAGS) diff --git a/pg_query.h b/pg_query.h index e6879dd4..bc1e6e65 100644 --- a/pg_query.h +++ b/pg_query.h @@ -79,7 +79,8 @@ typedef enum PG_QUERY_PARSE_PLPGSQL_EXPR, PG_QUERY_PARSE_PLPGSQL_ASSIGN1, PG_QUERY_PARSE_PLPGSQL_ASSIGN2, - PG_QUERY_PARSE_PLPGSQL_ASSIGN3 + PG_QUERY_PARSE_PLPGSQL_ASSIGN3, + PG_QUERY_PARSE_ALL } PgQueryParseMode; // We technically only need 3 bits to store parse mode, but @@ -96,6 +97,7 @@ extern "C" { #endif PgQueryNormalizeResult pg_query_normalize(const char* input); +PgQueryNormalizeResult pg_query_normalize_opts(const char* input, int parser_options); PgQueryScanResult pg_query_scan(const char* input); PgQueryParseResult pg_query_parse(const char* input); PgQueryParseResult pg_query_parse_opts(const char* input, int parser_options); diff --git a/src/pg_query_fingerprint.c b/src/pg_query_fingerprint.c index a8fcd0cd..6b28ac59 100644 --- a/src/pg_query_fingerprint.c +++ b/src/pg_query_fingerprint.c @@ -391,7 +391,38 @@ PgQueryFingerprintResult pg_query_fingerprint(const char* input) PgQueryFingerprintResult pg_query_fingerprint_opts(const char* input, int parser_options) { - return pg_query_fingerprint_with_opts(input, parser_options, false); + if ((parser_options & PG_QUERY_PARSE_ALL) == PG_QUERY_PARSE_ALL) { + parser_options = (parser_options & ~PG_QUERY_PARSE_ALL) | PG_QUERY_PARSE_DEFAULT; + PgQueryFingerprintResult result = pg_query_fingerprint_with_opts(input, parser_options, false); + if (result.error) { + pg_query_free_fingerprint_result(result); + parser_options = (parser_options & ~PG_QUERY_PARSE_DEFAULT) | PG_QUERY_PARSE_TYPE_NAME; + result = pg_query_fingerprint_with_opts(input, parser_options, false); + } + if (result.error) { + pg_query_free_fingerprint_result(result); + parser_options = (parser_options & ~PG_QUERY_PARSE_TYPE_NAME) | PG_QUERY_PARSE_PLPGSQL_EXPR; + result = pg_query_fingerprint_with_opts(input, parser_options, false); + } + if (result.error) { + pg_query_free_fingerprint_result(result); + parser_options = (parser_options & ~PG_QUERY_PARSE_PLPGSQL_EXPR) | PG_QUERY_PARSE_PLPGSQL_ASSIGN1; + result = pg_query_fingerprint_with_opts(input, parser_options, false); + } + if (result.error) { + pg_query_free_fingerprint_result(result); + parser_options = (parser_options & ~PG_QUERY_PARSE_PLPGSQL_ASSIGN1) | PG_QUERY_PARSE_PLPGSQL_ASSIGN2; + result = pg_query_fingerprint_with_opts(input, parser_options, false); + } + if (result.error) { + pg_query_free_fingerprint_result(result); + parser_options = (parser_options & ~PG_QUERY_PARSE_PLPGSQL_ASSIGN2) | PG_QUERY_PARSE_PLPGSQL_ASSIGN3; + result = pg_query_fingerprint_with_opts(input, parser_options, false); + } + return result; + } else { + return pg_query_fingerprint_with_opts(input, parser_options, false); + } } void pg_query_free_fingerprint_result(PgQueryFingerprintResult result) diff --git a/src/pg_query_normalize.c b/src/pg_query_normalize.c index bc15b01e..b046d400 100644 --- a/src/pg_query_normalize.c +++ b/src/pg_query_normalize.c @@ -558,7 +558,7 @@ static bool const_record_walker(Node *node, pgssConstLocations *jstate) return false; } -PgQueryNormalizeResult pg_query_normalize(const char* input) +PgQueryNormalizeResult pg_query_normalize_opts_internal(const char* input, int parser_options) { MemoryContext ctx = NULL; PgQueryNormalizeResult result = {0}; @@ -571,8 +571,40 @@ PgQueryNormalizeResult pg_query_normalize(const char* input) pgssConstLocations jstate; int query_len; + RawParseMode rawParseMode = RAW_PARSE_DEFAULT; + switch (parser_options & PG_QUERY_PARSE_MODE_BITMASK) + { + case PG_QUERY_PARSE_TYPE_NAME: + rawParseMode = RAW_PARSE_TYPE_NAME; + break; + case PG_QUERY_PARSE_PLPGSQL_EXPR: + rawParseMode = RAW_PARSE_PLPGSQL_EXPR; + break; + case PG_QUERY_PARSE_PLPGSQL_ASSIGN1: + rawParseMode = RAW_PARSE_PLPGSQL_ASSIGN1; + break; + case PG_QUERY_PARSE_PLPGSQL_ASSIGN2: + rawParseMode = RAW_PARSE_PLPGSQL_ASSIGN2; + break; + case PG_QUERY_PARSE_PLPGSQL_ASSIGN3: + rawParseMode = RAW_PARSE_PLPGSQL_ASSIGN3; + break; + } + + if ((parser_options & PG_QUERY_DISABLE_BACKSLASH_QUOTE) == PG_QUERY_DISABLE_BACKSLASH_QUOTE) { + backslash_quote = BACKSLASH_QUOTE_OFF; + } else { + backslash_quote = BACKSLASH_QUOTE_SAFE_ENCODING; + } + standard_conforming_strings = !((parser_options & PG_QUERY_DISABLE_STANDARD_CONFORMING_STRINGS) == PG_QUERY_DISABLE_STANDARD_CONFORMING_STRINGS); + escape_string_warning = !((parser_options & PG_QUERY_DISABLE_ESCAPE_STRING_WARNING) == PG_QUERY_DISABLE_ESCAPE_STRING_WARNING); + /* Parse query */ - tree = raw_parser(input, RAW_PARSE_DEFAULT); + tree = raw_parser(input, rawParseMode); + + backslash_quote = BACKSLASH_QUOTE_SAFE_ENCODING; + standard_conforming_strings = true; + escape_string_warning = true; query_len = (int) strlen(input); @@ -621,6 +653,47 @@ PgQueryNormalizeResult pg_query_normalize(const char* input) return result; } +PgQueryNormalizeResult pg_query_normalize_opts(const char* input, int parser_options) +{ + if ((parser_options & PG_QUERY_PARSE_ALL) == PG_QUERY_PARSE_ALL) { + parser_options = (parser_options & ~PG_QUERY_PARSE_ALL) | PG_QUERY_PARSE_DEFAULT; + PgQueryNormalizeResult result = pg_query_normalize_opts_internal(input, parser_options); + if (result.error) { + pg_query_free_normalize_result(result); + parser_options = (parser_options & ~PG_QUERY_PARSE_DEFAULT) | PG_QUERY_PARSE_TYPE_NAME; + result = pg_query_normalize_opts_internal(input, parser_options); + } + if (result.error) { + pg_query_free_normalize_result(result); + parser_options = (parser_options & ~PG_QUERY_PARSE_TYPE_NAME) | PG_QUERY_PARSE_PLPGSQL_EXPR; + result = pg_query_normalize_opts_internal(input, parser_options); + } + if (result.error) { + pg_query_free_normalize_result(result); + parser_options = (parser_options & ~PG_QUERY_PARSE_PLPGSQL_EXPR) | PG_QUERY_PARSE_PLPGSQL_ASSIGN1; + result = pg_query_normalize_opts_internal(input, parser_options); + } + if (result.error) { + pg_query_free_normalize_result(result); + parser_options = (parser_options & ~PG_QUERY_PARSE_PLPGSQL_ASSIGN1) | PG_QUERY_PARSE_PLPGSQL_ASSIGN2; + result = pg_query_normalize_opts_internal(input, parser_options); + } + if (result.error) { + pg_query_free_normalize_result(result); + parser_options = (parser_options & ~PG_QUERY_PARSE_PLPGSQL_ASSIGN2) | PG_QUERY_PARSE_PLPGSQL_ASSIGN3; + result = pg_query_normalize_opts_internal(input, parser_options); + } + return result; + } else { + return pg_query_normalize_opts_internal(input, parser_options); + } +} + +PgQueryNormalizeResult pg_query_normalize(const char* input) +{ + return pg_query_normalize_opts(input, PG_QUERY_PARSE_DEFAULT); +} + void pg_query_free_normalize_result(PgQueryNormalizeResult result) { if (result.error) { diff --git a/src/pg_query_parse.c b/src/pg_query_parse.c index 5307c0c0..359e136d 100644 --- a/src/pg_query_parse.c +++ b/src/pg_query_parse.c @@ -120,7 +120,7 @@ PgQueryParseResult pg_query_parse(const char* input) return pg_query_parse_opts(input, PG_QUERY_PARSE_DEFAULT); } -PgQueryParseResult pg_query_parse_opts(const char* input, int parser_options) +PgQueryParseResult pg_query_parse_opts_internal(const char* input, int parser_options) { MemoryContext ctx = NULL; PgQueryInternalParsetreeAndError parsetree_and_error; @@ -144,12 +144,48 @@ PgQueryParseResult pg_query_parse_opts(const char* input, int parser_options) return result; } +PgQueryParseResult pg_query_parse_opts(const char* input, int parser_options) +{ + if ((parser_options & PG_QUERY_PARSE_ALL) == PG_QUERY_PARSE_ALL) { + parser_options = (parser_options & ~PG_QUERY_PARSE_ALL) | PG_QUERY_PARSE_DEFAULT; + PgQueryParseResult result = pg_query_parse_opts_internal(input, parser_options); + if (result.error) { + pg_query_free_parse_result(result); + parser_options = (parser_options & ~PG_QUERY_PARSE_DEFAULT) | PG_QUERY_PARSE_TYPE_NAME; + result = pg_query_parse_opts_internal(input, parser_options); + } + if (result.error) { + pg_query_free_parse_result(result); + parser_options = (parser_options & ~PG_QUERY_PARSE_TYPE_NAME) | PG_QUERY_PARSE_PLPGSQL_EXPR; + result = pg_query_parse_opts_internal(input, parser_options); + } + if (result.error) { + pg_query_free_parse_result(result); + parser_options = (parser_options & ~PG_QUERY_PARSE_PLPGSQL_EXPR) | PG_QUERY_PARSE_PLPGSQL_ASSIGN1; + result = pg_query_parse_opts_internal(input, parser_options); + } + if (result.error) { + pg_query_free_parse_result(result); + parser_options = (parser_options & ~PG_QUERY_PARSE_PLPGSQL_ASSIGN1) | PG_QUERY_PARSE_PLPGSQL_ASSIGN2; + result = pg_query_parse_opts_internal(input, parser_options); + } + if (result.error) { + pg_query_free_parse_result(result); + parser_options = (parser_options & ~PG_QUERY_PARSE_PLPGSQL_ASSIGN2) | PG_QUERY_PARSE_PLPGSQL_ASSIGN3; + result = pg_query_parse_opts_internal(input, parser_options); + } + return result; + } else { + return pg_query_parse_opts_internal(input, parser_options); + } +} + PgQueryProtobufParseResult pg_query_parse_protobuf(const char* input) { return pg_query_parse_protobuf_opts(input, PG_QUERY_PARSE_DEFAULT); } -PgQueryProtobufParseResult pg_query_parse_protobuf_opts(const char* input, int parser_options) +PgQueryProtobufParseResult pg_query_parse_protobuf_opts_internal(const char* input, int parser_options) { MemoryContext ctx = NULL; PgQueryInternalParsetreeAndError parsetree_and_error; @@ -169,6 +205,42 @@ PgQueryProtobufParseResult pg_query_parse_protobuf_opts(const char* input, int p return result; } +PgQueryProtobufParseResult pg_query_parse_protobuf_opts(const char* input, int parser_options) +{ + if ((parser_options & PG_QUERY_PARSE_ALL) == PG_QUERY_PARSE_ALL) { + parser_options = (parser_options & ~PG_QUERY_PARSE_ALL) | PG_QUERY_PARSE_DEFAULT; + PgQueryProtobufParseResult result = pg_query_parse_protobuf_opts_internal(input, parser_options); + if (result.error) { + pg_query_free_protobuf_parse_result(result); + parser_options = (parser_options & ~PG_QUERY_PARSE_DEFAULT) | PG_QUERY_PARSE_TYPE_NAME; + result = pg_query_parse_protobuf_opts_internal(input, parser_options); + } + if (result.error) { + pg_query_free_protobuf_parse_result(result); + parser_options = (parser_options & ~PG_QUERY_PARSE_TYPE_NAME) | PG_QUERY_PARSE_PLPGSQL_EXPR; + result = pg_query_parse_protobuf_opts_internal(input, parser_options); + } + if (result.error) { + pg_query_free_protobuf_parse_result(result); + parser_options = (parser_options & ~PG_QUERY_PARSE_PLPGSQL_EXPR) | PG_QUERY_PARSE_PLPGSQL_ASSIGN1; + result = pg_query_parse_protobuf_opts_internal(input, parser_options); + } + if (result.error) { + pg_query_free_protobuf_parse_result(result); + parser_options = (parser_options & ~PG_QUERY_PARSE_PLPGSQL_ASSIGN1) | PG_QUERY_PARSE_PLPGSQL_ASSIGN2; + result = pg_query_parse_protobuf_opts_internal(input, parser_options); + } + if (result.error) { + pg_query_free_protobuf_parse_result(result); + parser_options = (parser_options & ~PG_QUERY_PARSE_PLPGSQL_ASSIGN2) | PG_QUERY_PARSE_PLPGSQL_ASSIGN3; + result = pg_query_parse_protobuf_opts_internal(input, parser_options); + } + return result; + } else { + return pg_query_parse_protobuf_opts_internal(input, parser_options); + } +} + void pg_query_free_parse_result(PgQueryParseResult result) { if (result.error) { diff --git a/test/fingerprint_opts_tests.c b/test/fingerprint_opts_tests.c index 1a998bc5..564afcb6 100644 --- a/test/fingerprint_opts_tests.c +++ b/test/fingerprint_opts_tests.c @@ -29,6 +29,37 @@ const char* tests[] = { "NEW.author.first_name = upper(cleanString(NEW.author.first_name))", "5", "a148e3f78b53c252", + // PG_QUERY_PARSE_ALL + "SELECT 1", + "6", + "50fde20626009aba", + "integer", + "6", + "c71927729d707de5", + "character varying(32)", + "6", + "453ab4df8fd3eea9", + "EXISTS(SELECT 1)", + "6", + "976a797c8ca2985b", + "v_version IS NULL", + "6", + "6b292a26fcb78b1c", + "pos:= instr($1, $2, 1)", + "6", + "786552659cc61f6f", + "temp_str := substring(string FROM beg_index)", + "6", + "d6671d73f1654866", + "v3.c1 := 4", + "6", + "7f65202632663ba0", + "NEW.name = upper(cleanString(NEW.name))", + "6", + "184cff1a84037010", + "NEW.author.first_name = upper(cleanString(NEW.author.first_name))", + "6", + "b7de0b0d4f636a16", }; -size_t testsLength = __LINE__ - 4; +size_t testsLength = __LINE__ - 5; diff --git a/test/normalize_opts.c b/test/normalize_opts.c new file mode 100644 index 00000000..de032689 --- /dev/null +++ b/test/normalize_opts.c @@ -0,0 +1,36 @@ +#include + +#include +#include +#include +#include + +#include "normalize_opts_tests.c" + +int main() { + size_t i; + bool ret_code = 0; + + for (i = 0; i < testsLength; i += 3) { + PgQueryParseMode mode = atoi(tests[i + 1]); + PgQueryNormalizeResult result = pg_query_normalize_opts(tests[i], mode); + + if (result.error) { + ret_code = -1; + printf("%s\n", result.error->message); + } else if (strcmp(result.normalized_query, tests[i + 2]) == 0) { + printf("."); + } else { + ret_code = -1; + printf("INVALID result for \"%s\" with %d mode\nexpected: %s\nactual: %s\n", tests[i], mode, tests[i + 2], result.normalized_query); + } + + pg_query_free_normalize_result(result); + } + + printf("\n"); + + pg_query_exit(); + + return ret_code; +} diff --git a/test/normalize_opts_tests.c b/test/normalize_opts_tests.c new file mode 100644 index 00000000..a0638c5d --- /dev/null +++ b/test/normalize_opts_tests.c @@ -0,0 +1,62 @@ +const char* tests[] = { + "integer", + "1", + "integer", + "character varying(32)", + "1", + "character varying(32)", + "EXISTS(SELECT 1)", + "2", + "EXISTS(SELECT $1)", + "v_version IS NULL", + "2", + "v_version IS NULL", + "pos:= instr($1, $2, 1)", + "3", + "pos:= instr($1, $2, $3)", + "temp_str := substring(string FROM beg_index)", + "3", + "temp_str := substring(string FROM beg_index)", + "v3.c1 := 4", + "4", + "v3.c1 := $1", + "NEW.name = upper(cleanString(NEW.name))", + "4", + "NEW.name = upper(cleanString(NEW.name))", + "NEW.author.first_name = upper(cleanString(NEW.author.first_name))", + "5", + "NEW.author.first_name = upper(cleanString(NEW.author.first_name))", + // PG_QUERY_PARSE_ALL + "SELECT 1", + "6", + "SELECT $1", + "integer", + "6", + "integer", + "character varying(32)", + "6", + "character varying(32)", + "EXISTS(SELECT 1)", + "6", + "EXISTS(SELECT $1)", + "v_version IS NULL", + "6", + "v_version IS NULL", + "pos:= instr($1, $2, 1)", + "6", + "pos:= instr($1, $2, $3)", + "temp_str := substring(string FROM beg_index)", + "6", + "temp_str := substring(string FROM beg_index)", + "v3.c1 := 4", + "6", + "v3.c1 := $1", + "NEW.name = upper(cleanString(NEW.name))", + "6", + "NEW.name = upper(cleanString(NEW.name))", + "NEW.author.first_name = upper(cleanString(NEW.author.first_name))", + "6", + "NEW.author.first_name = upper(cleanString(NEW.author.first_name))", +}; + +size_t testsLength = __LINE__ - 5; diff --git a/test/parse_opts_tests.c b/test/parse_opts_tests.c index 07a1302a..38f690df 100644 --- a/test/parse_opts_tests.c +++ b/test/parse_opts_tests.c @@ -35,6 +35,37 @@ const char* tests[] = { "v3.c1 := '\\''", "100", "{\"version\":150001,\"stmts\":[{\"stmt\":{\"PLAssignStmt\":{\"name\":\"v3\",\"indirection\":[{\"String\":{\"sval\":\"c1\"}}],\"nnames\":2,\"val\":{\"targetList\":[{\"ResTarget\":{\"val\":{\"A_Const\":{\"sval\":{\"sval\":\"'\"},\"location\":9}},\"location\":9}}],\"limitOption\":\"LIMIT_OPTION_DEFAULT\",\"op\":\"SETOP_NONE\"}}}}]}", + // PG_QUERY_PARSE_ALL + "SELECT 1", + "6", + "{\"version\":150001,\"stmts\":[{\"stmt\":{\"SelectStmt\":{\"targetList\":[{\"ResTarget\":{\"val\":{\"A_Const\":{\"ival\":{\"ival\":1},\"location\":7}},\"location\":7}}],\"limitOption\":\"LIMIT_OPTION_DEFAULT\",\"op\":\"SETOP_NONE\"}}}]}", + "integer", + "6", + "{\"version\":150001,\"stmts\":[{\"stmt\":{\"List\":{\"items\":[{\"String\":{\"sval\":\"pg_catalog\"}},{\"String\":{\"sval\":\"int4\"}}]}}}]}", + "character varying(32)", + "6", + "{\"version\":150001,\"stmts\":[{\"stmt\":{\"List\":{\"items\":[{\"String\":{\"sval\":\"pg_catalog\"}},{\"String\":{\"sval\":\"varchar\"}}]}}}]}", + "EXISTS(SELECT 1)", + "6", + "{\"version\":150001,\"stmts\":[{\"stmt\":{\"SelectStmt\":{\"targetList\":[{\"ResTarget\":{\"val\":{\"SubLink\":{\"subLinkType\":\"EXISTS_SUBLINK\",\"subselect\":{\"SelectStmt\":{\"targetList\":[{\"ResTarget\":{\"val\":{\"A_Const\":{\"ival\":{\"ival\":1},\"location\":14}},\"location\":14}}],\"limitOption\":\"LIMIT_OPTION_DEFAULT\",\"op\":\"SETOP_NONE\"}}}}}}],\"limitOption\":\"LIMIT_OPTION_DEFAULT\",\"op\":\"SETOP_NONE\"}}}]}", + "v_version IS NULL", + "6", + "{\"version\":150001,\"stmts\":[{\"stmt\":{\"SelectStmt\":{\"targetList\":[{\"ResTarget\":{\"val\":{\"NullTest\":{\"arg\":{\"ColumnRef\":{\"fields\":[{\"String\":{\"sval\":\"v_version\"}}]}},\"nulltesttype\":\"IS_NULL\",\"location\":10}}}}],\"limitOption\":\"LIMIT_OPTION_DEFAULT\",\"op\":\"SETOP_NONE\"}}}]}", + "pos:= instr($1, $2, 1)", + "6", + "{\"version\":150001,\"stmts\":[{\"stmt\":{\"PLAssignStmt\":{\"name\":\"pos\",\"nnames\":1,\"val\":{\"targetList\":[{\"ResTarget\":{\"val\":{\"FuncCall\":{\"funcname\":[{\"String\":{\"sval\":\"instr\"}}],\"args\":[{\"ParamRef\":{\"number\":1,\"location\":12}},{\"ParamRef\":{\"number\":2,\"location\":16}},{\"A_Const\":{\"ival\":{\"ival\":1},\"location\":20}}],\"funcformat\":\"COERCE_EXPLICIT_CALL\",\"location\":6}},\"location\":6}}],\"limitOption\":\"LIMIT_OPTION_DEFAULT\",\"op\":\"SETOP_NONE\"}}}}]}", + "temp_str := substring(string FROM beg_index)", + "6", + "{\"version\":150001,\"stmts\":[{\"stmt\":{\"PLAssignStmt\":{\"name\":\"temp_str\",\"nnames\":1,\"val\":{\"targetList\":[{\"ResTarget\":{\"val\":{\"FuncCall\":{\"funcname\":[{\"String\":{\"sval\":\"pg_catalog\"}},{\"String\":{\"sval\":\"substring\"}}],\"args\":[{\"ColumnRef\":{\"fields\":[{\"String\":{\"sval\":\"string\"}}],\"location\":22}},{\"ColumnRef\":{\"fields\":[{\"String\":{\"sval\":\"beg_index\"}}],\"location\":34}}],\"funcformat\":\"COERCE_SQL_SYNTAX\",\"location\":12}},\"location\":12}}],\"limitOption\":\"LIMIT_OPTION_DEFAULT\",\"op\":\"SETOP_NONE\"}}}}]}", + "v3.c1 := 4", + "6", + "{\"version\":150001,\"stmts\":[{\"stmt\":{\"PLAssignStmt\":{\"name\":\"v3\",\"indirection\":[{\"String\":{\"sval\":\"c1\"}}],\"nnames\":1,\"val\":{\"targetList\":[{\"ResTarget\":{\"val\":{\"A_Const\":{\"ival\":{\"ival\":4},\"location\":9}},\"location\":9}}],\"limitOption\":\"LIMIT_OPTION_DEFAULT\",\"op\":\"SETOP_NONE\"}}}}]}", + "NEW.name = upper(cleanString(NEW.name))", + "6", + "{\"version\":150001,\"stmts\":[{\"stmt\":{\"SelectStmt\":{\"targetList\":[{\"ResTarget\":{\"val\":{\"A_Expr\":{\"kind\":\"AEXPR_OP\",\"name\":[{\"String\":{\"sval\":\"=\"}}],\"lexpr\":{\"ColumnRef\":{\"fields\":[{\"String\":{\"sval\":\"new\"}},{\"String\":{\"sval\":\"name\"}}]}},\"rexpr\":{\"FuncCall\":{\"funcname\":[{\"String\":{\"sval\":\"upper\"}}],\"args\":[{\"FuncCall\":{\"funcname\":[{\"String\":{\"sval\":\"cleanstring\"}}],\"args\":[{\"ColumnRef\":{\"fields\":[{\"String\":{\"sval\":\"new\"}},{\"String\":{\"sval\":\"name\"}}],\"location\":29}}],\"funcformat\":\"COERCE_EXPLICIT_CALL\",\"location\":17}}],\"funcformat\":\"COERCE_EXPLICIT_CALL\",\"location\":11}},\"location\":9}}}}],\"limitOption\":\"LIMIT_OPTION_DEFAULT\",\"op\":\"SETOP_NONE\"}}}]}", + "NEW.author.first_name = upper(cleanString(NEW.author.first_name))", + "6", + "{\"version\":150001,\"stmts\":[{\"stmt\":{\"SelectStmt\":{\"targetList\":[{\"ResTarget\":{\"val\":{\"A_Expr\":{\"kind\":\"AEXPR_OP\",\"name\":[{\"String\":{\"sval\":\"=\"}}],\"lexpr\":{\"ColumnRef\":{\"fields\":[{\"String\":{\"sval\":\"new\"}},{\"String\":{\"sval\":\"author\"}},{\"String\":{\"sval\":\"first_name\"}}]}},\"rexpr\":{\"FuncCall\":{\"funcname\":[{\"String\":{\"sval\":\"upper\"}}],\"args\":[{\"FuncCall\":{\"funcname\":[{\"String\":{\"sval\":\"cleanstring\"}}],\"args\":[{\"ColumnRef\":{\"fields\":[{\"String\":{\"sval\":\"new\"}},{\"String\":{\"sval\":\"author\"}},{\"String\":{\"sval\":\"first_name\"}}],\"location\":42}}],\"funcformat\":\"COERCE_EXPLICIT_CALL\",\"location\":30}}],\"funcformat\":\"COERCE_EXPLICIT_CALL\",\"location\":24}},\"location\":22}}}}],\"limitOption\":\"LIMIT_OPTION_DEFAULT\",\"op\":\"SETOP_NONE\"}}}]}", }; -size_t testsLength = __LINE__ - 4; +size_t testsLength = __LINE__ - 5;