├── .gitignore ├── README.md ├── TODO.md ├── plpgsql-ast-demo ├── pom.xml └── src │ ├── main │ ├── java │ │ └── de │ │ │ └── zalando │ │ │ └── plpgsql │ │ │ └── ast │ │ │ └── demo │ │ │ └── CodeFormatter.java │ └── resources │ │ └── log4j.xml │ └── test │ ├── java │ └── de │ │ └── zalando │ │ └── plpgsql │ │ └── ast │ │ └── demo │ │ └── CodeFormatterTest.java │ └── resources │ └── sprocs │ └── unformatted_query.sql └── plpgsql-ast ├── Makefile ├── pom.xml └── src ├── main ├── grammar │ ├── de │ │ └── zalando │ │ │ └── plpgsql │ │ │ └── ast │ │ │ ├── PgSqlLexer.g4 │ │ │ ├── PlPgSql.g4 │ │ │ ├── PlPgSqlKeyWords.g4 │ │ │ ├── Sql.g4 │ │ │ └── SqlKeyWords.g4 │ ├── postgres_grammar │ │ ├── kwlist.h │ │ ├── pl_scanner.c │ │ ├── plpgsql_gram.y │ │ ├── scan.l │ │ └── sql_gram.y │ └── scripts │ │ ├── lexer_grammar_converter.py │ │ ├── parser_grammar_converter.py │ │ ├── plpgsql_lexer_grammar_converter.py │ │ ├── plpgsql_parser_grammar_converter.py │ │ ├── rule_rewrite_config.py │ │ ├── sql_lexer_grammar_converter.py │ │ ├── sql_parser_grammar_converter.py │ │ └── yacc_rule_sort_by_precedence_for_antlr.py ├── java │ └── de │ │ └── zalando │ │ └── plpgsql │ │ └── ast │ │ ├── ParseUtil.java │ │ └── SyntaxErrorListener.java └── resources │ └── log4j.xml └── test ├── java └── de │ └── zalando │ └── plpgsql │ └── ast │ └── ParseTest.java └── resources ├── function_parse_test ├── function_insert.sql ├── function_with_assign_stmts.sql ├── function_with_declarations.sql ├── function_with_exception_handling.sql ├── function_with_query.sql ├── function_with_select_into.sql ├── function_with_simple_query.sql ├── function_with_var_declarations.sql ├── simple_empty_function.sql ├── simple_empty_function_with_IN_OUT_arguments.sql ├── simple_empty_function_with_many_arguments.sql ├── simple_empty_function_with_no_arguments.sql ├── simple_empty_function_with_qualified_types.sql ├── simple_empty_functions.sql └── unformatted_query.sql ├── operator_parse_test └── operators.sql └── sql_parse_test ├── abstime.sql ├── advisory_lock.sql ├── aggregates.sql ├── alter_table.sql ├── arrays.sql ├── bit.sql ├── bitmapops.sql ├── boolean.sql ├── box.sql ├── btree_index.sql ├── case.sql ├── char.sql ├── circle.sql ├── cluster.sql ├── collate.linux.utf8.sql ├── collate.sql ├── combocid.sql ├── comments.sql ├── conversion.sql ├── copy2.sql ├── copyselect.sql ├── create_aggregate.sql ├── create_cast.sql ├── create_function_3.sql ├── create_index.sql ├── create_misc.sql ├── create_operator.sql ├── create_table.sql ├── create_table_like.sql ├── create_type.sql ├── create_view.sql ├── date.sql ├── delete.sql ├── dependency.sql ├── domain.sql ├── drop.sql ├── drop_if_exists.sql ├── enum.sql ├── errors.sql ├── euc_cn.sql ├── euc_jp.sql ├── euc_kr.sql ├── euc_tw.sql ├── float4.sql ├── float8.sql ├── foreign_data.sql ├── foreign_key.sql ├── functional_deps.sql ├── geometry.sql ├── guc.sql ├── hash_index.sql ├── horology.sql ├── hs_primary_extremes.sql ├── hs_primary_setup.sql ├── hs_standby_allowed.sql ├── hs_standby_check.sql ├── hs_standby_disallowed.sql ├── hs_standby_functions.sql ├── inet.sql ├── inherit.sql ├── insert.sql ├── int2.sql ├── int4.sql ├── int8.sql ├── interval.sql ├── join.sql ├── json.sql ├── limit.sql ├── lseg.sql ├── macaddr.sql ├── money.sql ├── mule_internal.sql ├── name.sql ├── namespace.sql ├── numeric.sql ├── numeric_big.sql ├── numerology.sql ├── oid.sql ├── oidjoins.sql ├── opr_sanity.sql ├── path.sql ├── plancache.sql ├── plpgsql.sql ├── point.sql ├── polygon.sql ├── polymorphism.sql ├── portals.sql ├── portals_p2.sql ├── prepare.sql ├── prepared_xacts.sql ├── privileges.sql ├── query_with_complex_where_clause.sql ├── query_with_join.sql ├── query_with_left_join.sql ├── query_with_many_joins.sql ├── random.sql ├── rangefuncs.sql ├── rangetypes.sql ├── regex.sql ├── reltime.sql ├── returning.sql ├── rowtypes.sql ├── rules.sql ├── sanity_check.sql ├── select.sql ├── select_distinct.sql ├── select_distinct_on.sql ├── select_having.sql ├── select_implicit.sql ├── select_into.sql ├── select_views.sql ├── sequence.sql ├── simple_sql.sql ├── sql_ascii.sql ├── stats.sql ├── strings.sql ├── subselect.sql ├── temp.sql ├── text.sql ├── time.sql ├── timestamp.sql ├── timestamptz.sql ├── timetz.sql ├── tinterval.sql ├── transactions.sql ├── triggers.sql ├── truncate.sql ├── tsdicts.sql ├── tsearch.sql ├── tstypes.sql ├── txid.sql ├── type_sanity.sql ├── typed_table.sql ├── union.sql ├── update.sql ├── uuid.sql ├── vacuum.sql ├── varchar.sql ├── window.sql ├── with.sql ├── with_query.sql ├── without_oid.sql ├── xml.sql └── xmlmap.sql /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | pom.xml.tag 3 | pom.xml.releaseBackup 4 | pom.xml.next 5 | release.properties 6 | .classpath 7 | .project 8 | .settings 9 | .idea/** 10 | .idea 11 | **/src/generated/ 12 | gen/ 13 | *.swp 14 | *.swo 15 | *.pyc 16 | .DS_Store 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | pg_sql_parser 2 | ============= 3 | 4 | The aim of this project is to provide a PostgreSQL SQL and PL/pgSQL grammars (ANTLR4) to enable code analysis of Postgres stored procedures in Java and Python. 5 | 6 | This is work in progress or even an experiment for now. 7 | 8 | METHOD 9 | ====== 10 | We create grammar files for a lexer and a parser. ANTLR4 can turn these into java classes for us. We can then use these classes to parse the source code. 11 | Having a basic grasp of parsing and ANTLR4 is very valuable in getting started. 12 | 13 | GOALS 14 | ===== 15 | For this project we have a few different goals, they are here listed in order 16 | of ease of expected implementation: 17 | 18 | - Identify relations that are being mentioned (and therefore probably used) in the stored procedures. 19 | - Reformat source code 20 | 21 | REFERENCES 22 | ========== 23 | We are not the only one having this idea. There are multiple projects dead and alive which are attempting the same thing. We will list a few as reference, to learn from other's mistakes and ideas. 24 | 25 | **An ANTLR 4 lexer for PostgreSQL** 26 | https://github.com/tunnelvisionlabs/antlr4-grammar-postgresql 27 | Last activity: 4 days ago (September 2014) 28 | 29 | **pg-parser** 30 | https://github.com/claesjac/pg-parser 31 | Last activity: 3 years ago (2011) 32 | 33 | Discussion: **exporting raw parser** 34 | http://postgresql.1045698.n5.nabble.com/exporting-raw-parser-td2018442.html 35 | Last activity: 4 years ago (2010) 36 | 37 | **pgFormatter** 38 | https://github.com/darold/pgFormatter 39 | Last activity: 14 days ago (September 2014) 40 | 41 | BUGS 42 | ==== 43 | Issue 670 44 | ----------- 45 | - ANTLR 4.2.2 Can parse our .g4 files, but cannot generate Python code. 46 | - ANTLR 4.4 Cannot parse our .g4 files, but can generate Pyton code. 47 | https://github.com/antlr/antlr4/issues/670 48 | 49 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | Grammar 2 | ======= 3 | - document grammar 4 | - do something about the complex dollar delimited strings, currently we "catch" only the following: 5 | $$ 6 | $function$ 7 | $BODY$ 8 | 9 | Parsing function body 10 | ===================== 11 | Currently a function body is read as a string (s_const). The reason for this is that we cannot know during the first 12 | parse what language a function is written in. (The LANGUAGE option may come *after* the function body). 13 | 14 | One option is to do a second parse after the first parse, a solution could be: 15 | 16 | PARSE SQL 17 | WALK THROUGH parse tree (using a Listener or a Visitor) 18 | IF enterFunc_as is called 19 | IF function language is PLPGSQL 20 | THEN parse function boday with PlPgSql lexer/parser 21 | 22 | Discussion points 23 | ================= 24 | - very clear split up in lexer/parser 25 | - design a parser and use an already finished lexer 26 | - provide the tool to convert grammar in the PostgreSQL source code into g4 files for this project 27 | -------------------------------------------------------------------------------- /plpgsql-ast-demo/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | de.zalando 4 | plpgsql-ast-demo 5 | 0.0.1-SNAPSHOT 6 | PLPGSQL AST Demo 7 | Demo to show first possibilities with current PLPGSQL AST version 8 | 9 | 10 | de.zalando.plgpqsql.ast 11 | plpgsql-ast 12 | 1.0-SNAPSHOT 13 | 14 | 15 | junit 16 | junit 17 | 4.13.1 18 | test 19 | 20 | 21 | org.slf4j 22 | slf4j-api 23 | 1.7.5 24 | 25 | 26 | 27 | org.slf4j 28 | slf4j-log4j12 29 | 1.7.5 30 | 31 | 32 | 33 | 34 | 35 | 36 | org.apache.maven.plugins 37 | maven-compiler-plugin 38 | 39 | 1.7 40 | 1.7 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /plpgsql-ast-demo/src/main/resources/log4j.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /plpgsql-ast-demo/src/test/java/de/zalando/plpgsql/ast/demo/CodeFormatterTest.java: -------------------------------------------------------------------------------- 1 | package de.zalando.plpgsql.ast.demo; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | 6 | import org.antlr.v4.runtime.tree.ParseTree; 7 | import org.antlr.v4.runtime.tree.ParseTreeWalker; 8 | 9 | import org.junit.Test; 10 | 11 | import de.zalando.plpgsql.ast.ParseUtil; 12 | 13 | public final class CodeFormatterTest { 14 | 15 | @Test 16 | public void test() throws Exception { 17 | 18 | final File file = new File("src/test/resources/sprocs/unformatted_query.sql"); 19 | final ParseTree tree = ParseUtil.parse(new FileInputStream(file)); 20 | 21 | final CodeFormatter formatter = new CodeFormatter(); 22 | 23 | final ParseTreeWalker walker = new ParseTreeWalker(); 24 | walker.walk(formatter, tree); 25 | 26 | System.out.println(formatter.toString()); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /plpgsql-ast-demo/src/test/resources/sprocs/unformatted_query.sql: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE FUNCTION increment(i integer) 2 | RETURNS integer AS 3 | $$ 4 | DECLARE 5 | a INTEGER; 6 | BEGIN 7 | SELECT ft_id, ft_text, ft_another_file into a1, a2, a3 8 | FROM t.my_fancy_table JOIN t.other_table ON ot_id = mft_my_fancy_table_id 9 | LEFT JOIN z.might_be_there_table 10 | ON mbtt_id = mft_id 11 | WHERE ft_id = 0 and ft_id2 < 10 12 | AND ft_id3 >= 0 oR ft_id4 <= ft_id3 OR ft_id5 = 'TEXT' anD ft_id5 = '"text with double quotes"' 13 | OR ft_id6 like '%t' AND ft_id7 like '%small' 14 | AND ft_id8 = (1 + 3 ) AND ft_id9 = myArr[0] 15 | LIMIT 16 | 1 ; 17 | 18 | END; 19 | $$ 20 | LANGUAGE plpgsql; 21 | -------------------------------------------------------------------------------- /plpgsql-ast/Makefile: -------------------------------------------------------------------------------- 1 | 2 | GRAMMAR_DIR = src/main/grammar 3 | 4 | SQL_PARSER = $(GRAMMAR_DIR)/de/zalando/plpgsql/ast/Sql.g4 5 | SQL_KEYWORDS = $(GRAMMAR_DIR)/de/zalando/plpgsql/ast/SqlKeyWords.g4 6 | SQL_LEXER = $(GRAMMAR_DIR)/de/zalando/plpgsql/ast/PgSqlLexer.g4 7 | 8 | PLPGSQL_PARSER = $(GRAMMAR_DIR)/de/zalando/plpgsql/ast/PlPgSql.g4.tmp 9 | PLPGSQL_KEYWORDS = $(GRAMMAR_DIR)/de/zalando/plpgsql/ast/PlPgSqlKeyWords.g4.tmp 10 | 11 | ORIGINAL_SQL_PARSER_GRAMMAR = $(GRAMMAR_DIR)/postgres_grammar/sql_gram.y 12 | ORIGINAL_SQL_KEYWORDS = $(GRAMMAR_DIR)/postgres_grammar/kwlist.h 13 | 14 | ORIGINAL_PLPGSQL_PARSER_GRAMMAR = $(GRAMMAR_DIR)/postgres_grammar/plpgsql_gram.y 15 | ORIGINAL_PLPGSQL_KEYWORDS = $(GRAMMAR_DIR)/postgres_grammar/pl_scanner.c 16 | 17 | 18 | ifeq ($(shell uname -s),Darwin) 19 | ANTLR_JAR = /usr/local/Cellar/antlr/4.5/antlr-4.5-complete.jar 20 | else # Linux 21 | ANTLR_JAR = /usr/local/lib/antlr-4.2.2-complete.jar 22 | endif 23 | 24 | PYTHON_CMD = python 25 | MVN_CMD = mvn 26 | ANTLR_CMD := java -jar $(ANTLR_JAR) 27 | GRUN_CMD := java -cp $(ANTLR_JAR) org.antlr.v4.runtime.misc.TestRig 28 | 29 | generate: $(SQL_PARSER) $(SQL_KEYWORDS) $(SQL_LEXER) $(PLPGSQL_PARSER) $(PLPGSQL_KEYWORDS) 30 | $(MVN_CMD) install -DskipTests=true 31 | 32 | clean: 33 | rm -f $(SQL_PARSER) 34 | rm -f $(SQL_KEYWORDS) 35 | rm -f $(PLPGSQL_PARSER) 36 | rm -f $(PLPGSQL_KEYWORDS) 37 | $(MVN_CMD) -o -q clean 38 | 39 | $(SQL_PARSER): 40 | $(PYTHON_CMD) $(GRAMMAR_DIR)/scripts/sql_parser_grammar_converter.py $(ORIGINAL_SQL_PARSER_GRAMMAR) > $(SQL_PARSER) 41 | 42 | $(SQL_KEYWORDS): 43 | $(PYTHON_CMD) $(GRAMMAR_DIR)/scripts/sql_lexer_grammar_converter.py $(ORIGINAL_SQL_KEYWORDS) > $(SQL_KEYWORDS) 44 | 45 | $(PLPGSQL_PARSER): 46 | $(PYTHON_CMD) $(GRAMMAR_DIR)/scripts/plpgsql_parser_grammar_converter.py $(ORIGINAL_PLPGSQL_PARSER_GRAMMAR) > $(PLPGSQL_PARSER) 47 | 48 | $(PLPGSQL_KEYWORDS): 49 | $(PYTHON_CMD) $(GRAMMAR_DIR)/scripts/plpgsql_lexer_grammar_converter.py $(ORIGINAL_PLPGSQL_KEYWORDS) > $(PLPGSQL_KEYWORDS) 50 | 51 | 52 | test: generate 53 | $(MVN_CMD) -o install 54 | -------------------------------------------------------------------------------- /plpgsql-ast/src/main/grammar/scripts/lexer_grammar_converter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | from __future__ import print_function 5 | import re 6 | import sys 7 | import cStringIO 8 | 9 | 10 | def to_rule(val): 11 | # ok for now but we could generate an alphabet later on. 12 | # see http://stackoverflow.com/questions/228730/how-do-i-iterate-through-the-alphabet-in-python 13 | v = '' 14 | for c in val: 15 | v = v + '[' + c.lower() + c.upper() + ']' 16 | return v 17 | 18 | 19 | def convert_postgres_keywords(input_file_content): 20 | p = re.compile('.*PG_KEYWORD.*\\"([a-zA-Z\\_]+)\\"\\s*,\\s*([a-zA-Z\\_]+).*') 21 | 22 | output = '' 23 | rule_to_def_map = dict() 24 | 25 | # collect all rules first to handle rule collisions 26 | # -> such a case is resolved with one rule consisting of multiple alternatives 27 | buffer = cStringIO.StringIO(input_file_content) 28 | for line in buffer: 29 | m = p.match(line) 30 | if m: 31 | # also print out the original data (we might need it later on) 32 | output = output + '//' + line 33 | 34 | rule = m.group(2) 35 | if rule in rule_to_def_map: 36 | value_list = rule_to_def_map[rule] 37 | value_list.append(to_rule(m.group(1))) 38 | else: 39 | value_list = list() 40 | value_list.append(to_rule(m.group(1))) 41 | rule_to_def_map[rule] = value_list 42 | 43 | # put out collected rule data 44 | keys = rule_to_def_map.keys() 45 | 46 | for key in keys: 47 | output = output + key + ' : ' + ' | '.join(rule_to_def_map[key]) + ';\n' 48 | 49 | return output 50 | 51 | 52 | def convert(input_file): 53 | f = open(input_file, 'r') 54 | input_file_content = f.read() 55 | converted_content = convert_postgres_keywords(input_file_content) 56 | 57 | print(converted_content) 58 | 59 | return 0 60 | 61 | 62 | -------------------------------------------------------------------------------- /plpgsql-ast/src/main/grammar/scripts/plpgsql_lexer_grammar_converter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | from __future__ import print_function 5 | from lexer_grammar_converter import convert 6 | import sys 7 | 8 | 9 | def main(input_file): 10 | 11 | # header = \ 12 | # """ 13 | # lexer grammar SqlKeyWords; 14 | # 15 | # import PgSqlLexer; 16 | # 17 | # NULLS_FIRST : NULLS_P T_whitespace+ FIRST_P ; 18 | # NULLS_LAST : NULLS_P T_whitespace+ LAST_P ; 19 | # WITH_TIME : WITH T_whitespace+ TIME; 20 | # """ 21 | # 22 | # print(header) 23 | 24 | print('lexer grammar PlPgSqlKeyWords;\n') 25 | convert(input_file) 26 | 27 | return 0 28 | 29 | 30 | if __name__ == '__main__': 31 | sys.exit(main(sys.argv[1])) 32 | 33 | -------------------------------------------------------------------------------- /plpgsql-ast/src/main/grammar/scripts/plpgsql_parser_grammar_converter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | from __future__ import print_function 5 | from parser_grammar_converter import convert 6 | import sys 7 | 8 | 9 | def main(input_file): 10 | print('grammar PlPgSql;') 11 | print('import PlPgSqlKeyWords, Sql;\n') 12 | convert(input_file) 13 | 14 | 15 | if __name__ == '__main__': 16 | sys.exit(main(sys.argv[1])) 17 | 18 | -------------------------------------------------------------------------------- /plpgsql-ast/src/main/grammar/scripts/rule_rewrite_config.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # mapping: rule_name => replacement 5 | 6 | ''' 7 | Rule rewrite definitions to resolve problems regarding Mutual Left Recursion. 8 | TODO: automate these resolutions. 9 | ''' 10 | 11 | rule_replacement_map = dict() 12 | 13 | # ============= table_ref ============= 14 | 15 | rule_replacement_map['table_ref'] = \ 16 | """table_ref : joined_table 17 | \ 18 | | table_ref2 19 | \ 20 | ; 21 | 22 | \ 23 | table_ref2: relation_expr 24 | \ 25 | | relation_expr alias_clause 26 | \ 27 | | func_table 28 | \ 29 | | func_table alias_clause 30 | \ 31 | | func_table AS '(' tableFuncElementList ')' 32 | \ 33 | | func_table AS colId '(' tableFuncElementList ')' 34 | \ 35 | | func_table colId '(' tableFuncElementList ')' 36 | \ 37 | | select_with_parens 38 | \ 39 | | select_with_parens alias_clause 40 | \ 41 | ; 42 | 43 | """ 44 | 45 | # ============= joined_table ============= 46 | 47 | rule_replacement_map['joined_table'] = \ 48 | """joined_table: 49 | \ 50 | '(' joined_table ')' alias_clause? 51 | \ 52 | | table_ref2 CROSS JOIN table_ref 53 | \ 54 | | table_ref2 join_type JOIN table_ref join_qual 55 | \ 56 | | table_ref2 JOIN table_ref join_qual 57 | \ 58 | | table_ref2 NATURAL join_type JOIN table_ref 59 | \ 60 | | table_ref2 NATURAL JOIN table_ref 61 | \ 62 | | joined_table CROSS JOIN table_ref 63 | \ 64 | | joined_table join_type JOIN table_ref join_qual 65 | \ 66 | | joined_table JOIN table_ref join_qual 67 | \ 68 | | joined_table NATURAL join_type JOIN table_ref 69 | \ 70 | | joined_table NATURAL JOIN table_ref 71 | \ 72 | ; 73 | 74 | """ 75 | 76 | # ============ simple_select ================ 77 | 78 | rule_replacement_map['simple_select'] = \ 79 | """simple_select: 80 | \ 81 | SELECT opt_distinct target_list 82 | \ 83 | into_clause from_clause where_clause 84 | \ 85 | group_clause having_clause window_clause 86 | \ 87 | | values_clause 88 | \ 89 | | TABLE relation_expr 90 | \ 91 | | simple_select UNION opt_all select_clause 92 | \ 93 | | simple_select INTERSECT opt_all select_clause 94 | \ 95 | | simple_select EXCEPT opt_all select_clause 96 | \ 97 | ; 98 | 99 | """ 100 | 101 | # ============= select_with_parens ========== 102 | rule_replacement_map['select_with_parens'] = \ 103 | """select_with_parens: 104 | \ 105 | '(' select_no_parens ')' 106 | \ 107 | | '(' select_with_parens ')' 108 | \ 109 | | select_with_parens UNION opt_all select_clause 110 | \ 111 | | select_with_parens INTERSECT opt_all select_clause 112 | \ 113 | | select_with_parens EXCEPT opt_all select_clause 114 | \ 115 | ; 116 | 117 | """ 118 | -------------------------------------------------------------------------------- /plpgsql-ast/src/main/grammar/scripts/sql_lexer_grammar_converter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | from __future__ import print_function 5 | from lexer_grammar_converter import convert 6 | import sys 7 | 8 | 9 | def main(input_file): 10 | 11 | header = \ 12 | """ 13 | lexer grammar SqlKeyWords; 14 | 15 | import PgSqlLexer; 16 | 17 | NULLS_FIRST : NULLS_P T_whitespace+ FIRST_P ; 18 | NULLS_LAST : NULLS_P T_whitespace+ LAST_P ; 19 | WITH_TIME : WITH T_whitespace+ TIME; 20 | """ 21 | 22 | print(header) 23 | convert(input_file) 24 | 25 | return 0 26 | 27 | 28 | if __name__ == '__main__': 29 | sys.exit(main(sys.argv[1])) 30 | 31 | -------------------------------------------------------------------------------- /plpgsql-ast/src/main/grammar/scripts/sql_parser_grammar_converter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | from __future__ import print_function 5 | from parser_grammar_converter import convert 6 | import sys 7 | 8 | 9 | def main(input_file): 10 | print('grammar Sql;') 11 | print('import SqlKeyWords;\n') 12 | convert(input_file) 13 | 14 | 15 | if __name__ == '__main__': 16 | sys.exit(main(sys.argv[1])) 17 | 18 | -------------------------------------------------------------------------------- /plpgsql-ast/src/main/java/de/zalando/plpgsql/ast/ParseUtil.java: -------------------------------------------------------------------------------- 1 | package de.zalando.plpgsql.ast; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | 6 | import org.antlr.v4.runtime.ANTLRInputStream; 7 | import org.antlr.v4.runtime.CommonTokenStream; 8 | import org.antlr.v4.runtime.DiagnosticErrorListener; 9 | import org.antlr.v4.runtime.tree.ParseTree; 10 | 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | 14 | public final class ParseUtil { 15 | private ParseUtil() { } 16 | 17 | private static final Logger LOGGER = LoggerFactory.getLogger(ParseUtil.class); 18 | 19 | public static ParseTree parse(final InputStream in) throws IOException { 20 | final ANTLRInputStream input = new ANTLRInputStream(in); 21 | 22 | // create a lexer that feeds off of input CharStream 23 | SqlLexer lexer = new SqlLexer(input); 24 | 25 | // create a buffer of tokens pulled from the lexer 26 | final CommonTokenStream tokens = new CommonTokenStream(lexer); 27 | 28 | // create a parser that feeds off the tokens buffer 29 | final SqlParser parser = new SqlParser(tokens); 30 | 31 | // parser.setErrorHandler(new BailErrorStrategy()); 32 | parser.addErrorListener(new SyntaxErrorListener()); 33 | parser.addErrorListener(new DiagnosticErrorListener()); 34 | // parser.setTrace(true); 35 | 36 | final ParseTree tree = parser.stmt(); 37 | LOGGER.debug(tree.toStringTree(parser)); 38 | 39 | // LOGGER.debug(parser.getCurrentToken() + ""); 40 | // LOGGER.debug(tokens.getTokens().toString()); 41 | 42 | return tree; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /plpgsql-ast/src/main/java/de/zalando/plpgsql/ast/SyntaxErrorListener.java: -------------------------------------------------------------------------------- 1 | package de.zalando.plpgsql.ast; 2 | 3 | import java.util.Collections; 4 | import java.util.List; 5 | 6 | import org.antlr.v4.runtime.BaseErrorListener; 7 | import org.antlr.v4.runtime.Parser; 8 | import org.antlr.v4.runtime.RecognitionException; 9 | import org.antlr.v4.runtime.Recognizer; 10 | 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | 14 | public class SyntaxErrorListener extends BaseErrorListener { 15 | private static final Logger LOGGER = LoggerFactory.getLogger(SyntaxErrorListener.class); 16 | 17 | @Override 18 | public void syntaxError(final Recognizer recognizer, final Object offendingSymbol, final int line, 19 | final int charPositionInLine, final String msg, final RecognitionException e) { 20 | 21 | super.syntaxError(recognizer, offendingSymbol, line, charPositionInLine, msg, e); 22 | 23 | if (e != null) { 24 | final Parser parser = (Parser) recognizer; 25 | final List stack = parser.getRuleInvocationStack(); 26 | Collections.reverse(stack); 27 | 28 | LOGGER.error("rule stack: {}", stack); 29 | LOGGER.error("line {} position {} : {} at {}", 30 | new Object[] {line, charPositionInLine, msg, offendingSymbol, e}); 31 | } 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /plpgsql-ast/src/main/resources/log4j.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/function_parse_test/function_insert.sql: -------------------------------------------------------------------------------- 1 | -- test cases are taken from 2 | -- http://www.postgresql.org/docs/9.1/static/sql-insert.html 3 | CREATE OR REPLACE FUNCTION insert_test(i integer) 4 | RETURNS integer AS 5 | $$ 6 | DECLARE 7 | a INTEGER; 8 | BEGIN 9 | 10 | 11 | INSERT INTO distributors (did, dname) VALUES (DEFAULT, 'XYZ Widgets') 12 | RETURNING did as lala into a; 13 | 14 | INSERT INTO films VALUES 15 | ('UA502', 'Bananas', 105, '1971-07-13', 'Comedy', '82 minutes'); 16 | 17 | INSERT INTO films (code, title, did, date_prod, kind) 18 | VALUES ('T_601', 'Yojimbo', 106, '1961-06-16', 'Drama'); 19 | 20 | 21 | INSERT INTO films (code, title, did, date_prod, kind) VALUES 22 | ('B6717', 'Tampopo', 110, '1985-02-10', 'Comedy'), 23 | ('HG120', 'The Dinner Game', 140, DEFAULT, 'Comedy'); 24 | 25 | INSERT INTO films SELECT * FROM tmp_films WHERE date_prod < '2004-05-07'; 26 | 27 | INSERT INTO films DEFAULT VALUES; 28 | 29 | 30 | INSERT INTO films (code, title, did, date_prod, kind) 31 | SELECT a,b,c,d,e 32 | FROM test; 33 | 34 | INSERT INTO films (code, title, did, date_prod, kind) 35 | SELECT a,b,c,d,e 36 | FROM z.test; 37 | 38 | INSERT INTO distributors (did, dname) VALUES (DEFAULT, 'XYZ Widgets') 39 | RETURNING did; 40 | 41 | INSERT INTO distributors (did, dname) VALUES (DEFAULT, 'XYZ Widgets') 42 | RETURNING did as lala into strict a; 43 | 44 | END; 45 | $$ 46 | LANGUAGE plpgsql; 47 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/function_parse_test/function_with_assign_stmts.sql: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE FUNCTION increment() 2 | RETURNS integer AS 3 | $$ 4 | DECLARE 5 | 6 | BEGIN 7 | a = i; 8 | a = 0; 9 | i = i + 1; 10 | i = i - 1; 11 | i = i * 1; 12 | i = i % 1; 13 | 14 | t = 'hello world'; -- String Test 15 | b = t like 'hello'; 16 | b = t Ilike 'hello'; 17 | b = t similar to 'my fancy test'; 18 | 19 | a = a + 1 + (1 * 2); 20 | 21 | a = 2^1; 22 | a = a^b^i^2; 23 | 24 | arr = arr[1]; 25 | arr = arr[i]; 26 | 27 | 28 | arr[i] = i; 29 | arr[2] = i; 30 | arr[ funcCall(a) ] = 12334; 31 | 32 | END; 33 | $$ 34 | LANGUAGE plpgsql; 35 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/function_parse_test/function_with_declarations.sql: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE FUNCTION function_with_declarations( 2 | p_limit integer, 3 | p_shipment_number TEXT[], 4 | OUT result_status_id SMALLINT, 5 | OUT result_status_msg text 6 | ) RETURNS RECORD AS 7 | $$ 8 | DECLARE 9 | header_ids bigint[]; 10 | commissions commission[]; 11 | l_commission commission; 12 | l_commission_write_result RECORD; 13 | l_loop_index SMALLINT; 14 | l_exported_order_ids TEXT[]; 15 | l_error_message TEXT; 16 | l_commission_ids bigint[]; 17 | l_commission_id bigint; 18 | l_outbound_tour_required_old BOOLEAN; 19 | l_number_commission_item integer; 20 | l_num_count_items_for_big_multi integer; 21 | l_warehouse_number TEXT; 22 | BEGIN 23 | 24 | 25 | END 26 | $$ 27 | LANGUAGE 'plpgsql' VOLATILE SECURITY DEFINER COST 100; 28 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/function_parse_test/function_with_exception_handling.sql: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE FUNCTION increment(i integer) 2 | RETURNS integer AS 3 | $$ 4 | DECLARE 5 | a INTEGER; 6 | BEGIN 7 | DECLARE 8 | b INTEGER; 9 | BEGIN 10 | 11 | EXCEPTION WHEN OTHERS THEN 12 | b = b + 1; 13 | END; 14 | EXCEPTION WHEN OTHERS THEN 15 | a = a + 1; 16 | END; 17 | $$ 18 | LANGUAGE plpgsql; 19 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/function_parse_test/function_with_query.sql: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE FUNCTION increment(i integer) 2 | RETURNS integer AS 3 | $$ 4 | DECLARE 5 | a INTEGER; 6 | BEGIN 7 | SELECT ft_id 8 | INTO a 9 | FROM t.my_fancy_table 10 | JOIN t.other_table ON ot_id = mft_my_fancy_table_id 11 | LEFT JOIN z.might_be_there_table ON mbtt_id = mft_id 12 | WHERE ft_id = 0 13 | AND ft_id2 < 10 14 | AND ft_id3 >= 0 15 | OR ft_id4 <= ft_id3 16 | OR ft_id5 = 'TEXT' 17 | AND ft_id5 = '"text with double quotes"' 18 | OR ft_id6 LIKE '%t' 19 | AND ft_id7 ILIKE '%small' 20 | AND ft_id8 = (1 + 3) 21 | AND ft_id9 = myArr[0] 22 | LIMIT 1 ; 23 | 24 | END; 25 | $$ 26 | LANGUAGE plpgsql; 27 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/function_parse_test/function_with_select_into.sql: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE FUNCTION function_with_select_into( 2 | p_limit integer, 3 | p_shipment_number TEXT[], 4 | OUT result_status_id SMALLINT, 5 | OUT result_status_msg text 6 | ) RETURNS RECORD AS 7 | $$ 8 | DECLARE 9 | BEGIN 10 | SELECT cc_outbound_tour_required 11 | FROM zal_data.commission 12 | JOIN zal_data.commission_config on cc_id = c_commission_config_id 13 | INTO l_outbound_tour_required_old 14 | where c_id = l_commission_id; 15 | 16 | select count(1) 17 | from zal_data.commission_item 18 | into l_number_commission_item 19 | where ci_commission_id = l_commission_id; 20 | 21 | END 22 | $$ 23 | LANGUAGE 'plpgsql' VOLATILE SECURITY DEFINER COST 100; 24 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/function_parse_test/function_with_simple_query.sql: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE FUNCTION increment(i integer) 2 | RETURNS integer AS 3 | $$ 4 | DECLARE 5 | a INTEGER; 6 | BEGIN 7 | SELECT t 8 | INTO a 9 | FROM t.my_fancy_table; 10 | END; 11 | $$ 12 | LANGUAGE plpgsql; 13 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/function_parse_test/function_with_var_declarations.sql: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE FUNCTION increment(i integer) 2 | RETURNS integer AS 3 | $$ 4 | DECLARE 5 | l_var INTEGER; 6 | l_var2 z.custom; 7 | l_var3 BIGINT = 1234; 8 | l_var4 TEXT = 'my fancy test'; 9 | l_var5 INTEGER = 123456789; 10 | 11 | l_var6 ALIAS FOR l_var; 12 | user_id z.my_table.user_id%TYPE; 13 | my_row z.my_table%ROWTYPE; 14 | my_arr INTEGER[]; 15 | my_arr_with_init INTEGER[] = '{1,2,3,4,5}'::INTEGER[]; 16 | BEGIN 17 | END; 18 | $$ LANGUAGE plpgsql; 19 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/function_parse_test/simple_empty_function.sql: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE FUNCTION increment(i integer) RETURNS integer AS 2 | $$ BEGIN END; $$ LANGUAGE plpgsql; 3 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/function_parse_test/simple_empty_function_with_IN_OUT_arguments.sql: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE FUNCTION increment( 2 | IN a integer, 3 | IN b integer, 4 | OUT c integer 5 | ) 6 | RETURNS integer AS 7 | $$ 8 | BEGIN 9 | END; 10 | $$ LANGUAGE plpgsql; 11 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/function_parse_test/simple_empty_function_with_many_arguments.sql: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE FUNCTION increment(i integer, t TEXT) 2 | RETURNS integer AS 3 | $$ 4 | BEGIN 5 | END; 6 | $$ LANGUAGE plpgsql; 7 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/function_parse_test/simple_empty_function_with_no_arguments.sql: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE FUNCTION increment() 2 | RETURNS integer AS 3 | $$ 4 | BEGIN 5 | END; 6 | $$ LANGUAGE plpgsql; 7 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/function_parse_test/simple_empty_function_with_qualified_types.sql: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE FUNCTION increment(i z.custom, OUT o z.custom) RETURNS integer 2 | AS $$ BEGIN 3 | END; $$ LANGUAGE plpgsql; 4 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/function_parse_test/simple_empty_functions.sql: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE FUNCTION increment(i integer) 2 | RETURNS integer AS 3 | $$ 4 | BEGIN 5 | END; 6 | $$ 7 | LANGUAGE plpgsql; 8 | 9 | -- CREATE OR REPLACE FUNCTION increment(i integer) RETURNS integer AS 10 | -- ' BEGIN END; ' 11 | -- LANGUAGE plpgsql; 12 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/function_parse_test/unformatted_query.sql: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE FUNCTION increment(i integer) 2 | RETURNS integer AS 3 | $$ 4 | DECLARE 5 | BEGIN 6 | 7 | 8 | select ft_id , ft_description INTO a , b FROM t.my_fancy_table; 9 | 10 | END; 11 | $$ 12 | LANGUAGE plpgsql; 13 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/operator_parse_test/operators.sql: -------------------------------------------------------------------------------- 1 | SELECT 1 <+->> 1; 2 | 3 | SELECT 1 +-- this is a comment 4 | 2; 5 | 6 | SELECT 1 &/*this is a coment*/ 2; 7 | 8 | SELECT 1 <-> 2; 9 | 10 | SELECT 1 >> 3; 11 | 12 | SELECT 1 >>? 2; 13 | 14 | SELECT 1 >>- 4; -- should be processed as 1 >> -4 15 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/abstime.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- ABSTIME 3 | -- testing built-in time type abstime 4 | -- uses reltime and tinterval 5 | -- 6 | 7 | -- 8 | -- timezones may vary based not only on location but the operating 9 | -- system. the main correctness issue is that the OS may not get 10 | -- daylight savings time right for times prior to Unix epoch (jan 1 1970). 11 | -- 12 | 13 | CREATE TABLE ABSTIME_TBL (f1 abstime); 14 | 15 | BEGIN; 16 | INSERT INTO ABSTIME_TBL (f1) VALUES (abstime 'now'); 17 | INSERT INTO ABSTIME_TBL (f1) VALUES (abstime 'now'); 18 | SELECT count(*) AS two FROM ABSTIME_TBL WHERE f1 = 'now' ; 19 | END; 20 | 21 | DELETE FROM ABSTIME_TBL; 22 | 23 | INSERT INTO ABSTIME_TBL (f1) VALUES ('Jan 14, 1973 03:14:21'); 24 | INSERT INTO ABSTIME_TBL (f1) VALUES (abstime 'Mon May 1 00:30:30 1995'); 25 | INSERT INTO ABSTIME_TBL (f1) VALUES (abstime 'epoch'); 26 | INSERT INTO ABSTIME_TBL (f1) VALUES (abstime 'infinity'); 27 | INSERT INTO ABSTIME_TBL (f1) VALUES (abstime '-infinity'); 28 | INSERT INTO ABSTIME_TBL (f1) VALUES (abstime 'May 10, 1947 23:59:12'); 29 | 30 | -- what happens if we specify slightly misformatted abstime? 31 | INSERT INTO ABSTIME_TBL (f1) VALUES ('Feb 35, 1946 10:00:00'); 32 | INSERT INTO ABSTIME_TBL (f1) VALUES ('Feb 28, 1984 25:08:10'); 33 | 34 | -- badly formatted abstimes: these should result in invalid abstimes 35 | INSERT INTO ABSTIME_TBL (f1) VALUES ('bad date format'); 36 | INSERT INTO ABSTIME_TBL (f1) VALUES ('Jun 10, 1843'); 37 | 38 | -- test abstime operators 39 | 40 | SELECT '' AS eight, * FROM ABSTIME_TBL; 41 | 42 | SELECT '' AS six, * FROM ABSTIME_TBL 43 | WHERE ABSTIME_TBL.f1 < abstime 'Jun 30, 2001'; 44 | 45 | SELECT '' AS six, * FROM ABSTIME_TBL 46 | WHERE ABSTIME_TBL.f1 > abstime '-infinity'; 47 | 48 | SELECT '' AS six, * FROM ABSTIME_TBL 49 | WHERE abstime 'May 10, 1947 23:59:12' <> ABSTIME_TBL.f1; 50 | 51 | SELECT '' AS three, * FROM ABSTIME_TBL 52 | WHERE abstime 'epoch' >= ABSTIME_TBL.f1; 53 | 54 | SELECT '' AS four, * FROM ABSTIME_TBL 55 | WHERE ABSTIME_TBL.f1 <= abstime 'Jan 14, 1973 03:14:21'; 56 | 57 | SELECT '' AS four, * FROM ABSTIME_TBL 58 | WHERE ABSTIME_TBL.f1 59 | tinterval '["Apr 1 1950 00:00:00" "Dec 30 1999 23:00:00"]'; 60 | 61 | SELECT '' AS four, f1 AS abstime, 62 | date_part('year', f1) AS year, date_part('month', f1) AS month, 63 | date_part('day',f1) AS day, date_part('hour', f1) AS hour, 64 | date_part('minute', f1) AS minute, date_part('second', f1) AS second 65 | FROM ABSTIME_TBL 66 | WHERE isfinite(f1) 67 | ORDER BY abstime; 68 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/advisory_lock.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- ADVISORY LOCKS 3 | -- 4 | 5 | BEGIN; 6 | 7 | SELECT 8 | pg_advisory_xact_lock(1), pg_advisory_xact_lock_shared(2), 9 | pg_advisory_xact_lock(1, 1), pg_advisory_xact_lock_shared(2, 2); 10 | 11 | SELECT locktype, classid, objid, objsubid, mode, granted 12 | FROM pg_locks WHERE locktype = 'advisory' 13 | ORDER BY classid, objid, objsubid; 14 | 15 | 16 | -- pg_advisory_unlock_all() shouldn't release xact locks 17 | SELECT pg_advisory_unlock_all(); 18 | 19 | SELECT count(*) FROM pg_locks WHERE locktype = 'advisory'; 20 | 21 | 22 | -- can't unlock xact locks 23 | SELECT 24 | pg_advisory_unlock(1), pg_advisory_unlock_shared(2), 25 | pg_advisory_unlock(1, 1), pg_advisory_unlock_shared(2, 2); 26 | 27 | 28 | -- automatically release xact locks at commit 29 | COMMIT; 30 | 31 | SELECT count(*) FROM pg_locks WHERE locktype = 'advisory'; 32 | 33 | 34 | BEGIN; 35 | 36 | -- holding both session and xact locks on the same objects, xact first 37 | SELECT 38 | pg_advisory_xact_lock(1), pg_advisory_xact_lock_shared(2), 39 | pg_advisory_xact_lock(1, 1), pg_advisory_xact_lock_shared(2, 2); 40 | 41 | SELECT locktype, classid, objid, objsubid, mode, granted 42 | FROM pg_locks WHERE locktype = 'advisory' 43 | ORDER BY classid, objid, objsubid; 44 | 45 | SELECT 46 | pg_advisory_lock(1), pg_advisory_lock_shared(2), 47 | pg_advisory_lock(1, 1), pg_advisory_lock_shared(2, 2); 48 | 49 | ROLLBACK; 50 | 51 | SELECT locktype, classid, objid, objsubid, mode, granted 52 | FROM pg_locks WHERE locktype = 'advisory' 53 | ORDER BY classid, objid, objsubid; 54 | 55 | 56 | -- unlocking session locks 57 | SELECT 58 | pg_advisory_unlock(1), pg_advisory_unlock(1), 59 | pg_advisory_unlock_shared(2), pg_advisory_unlock_shared(2), 60 | pg_advisory_unlock(1, 1), pg_advisory_unlock(1, 1), 61 | pg_advisory_unlock_shared(2, 2), pg_advisory_unlock_shared(2, 2); 62 | 63 | SELECT count(*) FROM pg_locks WHERE locktype = 'advisory'; 64 | 65 | 66 | BEGIN; 67 | 68 | -- holding both session and xact locks on the same objects, session first 69 | SELECT 70 | pg_advisory_lock(1), pg_advisory_lock_shared(2), 71 | pg_advisory_lock(1, 1), pg_advisory_lock_shared(2, 2); 72 | 73 | SELECT locktype, classid, objid, objsubid, mode, granted 74 | FROM pg_locks WHERE locktype = 'advisory' 75 | ORDER BY classid, objid, objsubid; 76 | 77 | SELECT 78 | pg_advisory_xact_lock(1), pg_advisory_xact_lock_shared(2), 79 | pg_advisory_xact_lock(1, 1), pg_advisory_xact_lock_shared(2, 2); 80 | 81 | ROLLBACK; 82 | 83 | SELECT locktype, classid, objid, objsubid, mode, granted 84 | FROM pg_locks WHERE locktype = 'advisory' 85 | ORDER BY classid, objid, objsubid; 86 | 87 | 88 | -- releasing all session locks 89 | SELECT pg_advisory_unlock_all(); 90 | 91 | SELECT count(*) FROM pg_locks WHERE locktype = 'advisory'; 92 | 93 | 94 | BEGIN; 95 | 96 | -- grabbing txn locks multiple times 97 | 98 | SELECT 99 | pg_advisory_xact_lock(1), pg_advisory_xact_lock(1), 100 | pg_advisory_xact_lock_shared(2), pg_advisory_xact_lock_shared(2), 101 | pg_advisory_xact_lock(1, 1), pg_advisory_xact_lock(1, 1), 102 | pg_advisory_xact_lock_shared(2, 2), pg_advisory_xact_lock_shared(2, 2); 103 | 104 | SELECT locktype, classid, objid, objsubid, mode, granted 105 | FROM pg_locks WHERE locktype = 'advisory' 106 | ORDER BY classid, objid, objsubid; 107 | 108 | COMMIT; 109 | 110 | SELECT count(*) FROM pg_locks WHERE locktype = 'advisory'; 111 | 112 | -- grabbing session locks multiple times 113 | 114 | SELECT 115 | pg_advisory_lock(1), pg_advisory_lock(1), 116 | pg_advisory_lock_shared(2), pg_advisory_lock_shared(2), 117 | pg_advisory_lock(1, 1), pg_advisory_lock(1, 1), 118 | pg_advisory_lock_shared(2, 2), pg_advisory_lock_shared(2, 2); 119 | 120 | SELECT locktype, classid, objid, objsubid, mode, granted 121 | FROM pg_locks WHERE locktype = 'advisory' 122 | ORDER BY classid, objid, objsubid; 123 | 124 | SELECT 125 | pg_advisory_unlock(1), pg_advisory_unlock(1), 126 | pg_advisory_unlock_shared(2), pg_advisory_unlock_shared(2), 127 | pg_advisory_unlock(1, 1), pg_advisory_unlock(1, 1), 128 | pg_advisory_unlock_shared(2, 2), pg_advisory_unlock_shared(2, 2); 129 | 130 | SELECT count(*) FROM pg_locks WHERE locktype = 'advisory'; 131 | 132 | -- .. and releasing them all at once 133 | 134 | SELECT 135 | pg_advisory_lock(1), pg_advisory_lock(1), 136 | pg_advisory_lock_shared(2), pg_advisory_lock_shared(2), 137 | pg_advisory_lock(1, 1), pg_advisory_lock(1, 1), 138 | pg_advisory_lock_shared(2, 2), pg_advisory_lock_shared(2, 2); 139 | 140 | SELECT locktype, classid, objid, objsubid, mode, granted 141 | FROM pg_locks WHERE locktype = 'advisory' 142 | ORDER BY classid, objid, objsubid; 143 | 144 | SELECT pg_advisory_unlock_all(); 145 | 146 | SELECT count(*) FROM pg_locks WHERE locktype = 'advisory'; 147 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/bitmapops.sql: -------------------------------------------------------------------------------- 1 | -- Test bitmap AND and OR 2 | 3 | 4 | -- Generate enough data that we can test the lossy bitmaps. 5 | 6 | -- There's 55 tuples per page in the table. 53 is just 7 | -- below 55, so that an index scan with qual a = constant 8 | -- will return at least one hit per page. 59 is just above 9 | -- 55, so that an index scan with qual b = constant will return 10 | -- hits on most but not all pages. 53 and 59 are prime, so that 11 | -- there's a maximum number of a,b combinations in the table. 12 | -- That allows us to test all the different combinations of 13 | -- lossy and non-lossy pages with the minimum amount of data 14 | 15 | CREATE TABLE bmscantest (a int, b int, t text); 16 | 17 | INSERT INTO bmscantest 18 | SELECT (r%53), (r%59), 'foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo' 19 | FROM generate_series(1,70000) r; 20 | 21 | CREATE INDEX i_bmtest_a ON bmscantest(a); 22 | CREATE INDEX i_bmtest_b ON bmscantest(b); 23 | 24 | -- We want to use bitmapscans. With default settings, the planner currently 25 | -- chooses a bitmap scan for the queries below anyway, but let's make sure. 26 | set enable_indexscan=false; 27 | set enable_seqscan=false; 28 | 29 | -- Lower work_mem to trigger use of lossy bitmaps 30 | set work_mem = 64; 31 | 32 | 33 | -- Test bitmap-and. 34 | SELECT count(*) FROM bmscantest WHERE a = 1 AND b = 1; 35 | 36 | -- Test bitmap-or. 37 | SELECT count(*) FROM bmscantest WHERE a = 1 OR b = 1; 38 | 39 | 40 | -- clean up 41 | DROP TABLE bmscantest; 42 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/box.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- BOX 3 | -- 4 | 5 | -- 6 | -- box logic 7 | -- o 8 | -- 3 o--|X 9 | -- | o| 10 | -- 2 +-+-+ | 11 | -- | | | | 12 | -- 1 | o-+-o 13 | -- | | 14 | -- 0 +---+ 15 | -- 16 | -- 0 1 2 3 17 | -- 18 | 19 | -- boxes are specified by two points, given by four floats x1,y1,x2,y2 20 | 21 | 22 | CREATE TABLE BOX_TBL (f1 box); 23 | 24 | INSERT INTO BOX_TBL (f1) VALUES ('(2.0,2.0,0.0,0.0)'); 25 | 26 | INSERT INTO BOX_TBL (f1) VALUES ('(1.0,1.0,3.0,3.0)'); 27 | 28 | -- degenerate cases where the box is a line or a point 29 | -- note that lines and points boxes all have zero area 30 | INSERT INTO BOX_TBL (f1) VALUES ('(2.5, 2.5, 2.5,3.5)'); 31 | 32 | INSERT INTO BOX_TBL (f1) VALUES ('(3.0, 3.0,3.0,3.0)'); 33 | 34 | -- badly formatted box inputs 35 | INSERT INTO BOX_TBL (f1) VALUES ('(2.3, 4.5)'); 36 | 37 | INSERT INTO BOX_TBL (f1) VALUES ('asdfasdf(ad'); 38 | 39 | 40 | SELECT '' AS four, * FROM BOX_TBL; 41 | 42 | SELECT '' AS four, b.*, area(b.f1) as barea 43 | FROM BOX_TBL b; 44 | 45 | -- overlap 46 | SELECT '' AS three, b.f1 47 | FROM BOX_TBL b 48 | WHERE b.f1 && box '(2.5,2.5,1.0,1.0)'; 49 | 50 | -- left-or-overlap (x only) 51 | SELECT '' AS two, b1.* 52 | FROM BOX_TBL b1 53 | WHERE b1.f1 &< box '(2.0,2.0,2.5,2.5)'; 54 | 55 | -- right-or-overlap (x only) 56 | SELECT '' AS two, b1.* 57 | FROM BOX_TBL b1 58 | WHERE b1.f1 &> box '(2.0,2.0,2.5,2.5)'; 59 | 60 | -- left of 61 | SELECT '' AS two, b.f1 62 | FROM BOX_TBL b 63 | WHERE b.f1 << box '(3.0,3.0,5.0,5.0)'; 64 | 65 | -- area <= 66 | SELECT '' AS four, b.f1 67 | FROM BOX_TBL b 68 | WHERE b.f1 <= box '(3.0,3.0,5.0,5.0)'; 69 | 70 | -- area < 71 | SELECT '' AS two, b.f1 72 | FROM BOX_TBL b 73 | WHERE b.f1 < box '(3.0,3.0,5.0,5.0)'; 74 | 75 | -- area = 76 | SELECT '' AS two, b.f1 77 | FROM BOX_TBL b 78 | WHERE b.f1 = box '(3.0,3.0,5.0,5.0)'; 79 | 80 | -- area > 81 | SELECT '' AS two, b.f1 82 | FROM BOX_TBL b -- zero area 83 | WHERE b.f1 > box '(3.5,3.0,4.5,3.0)'; 84 | 85 | -- area >= 86 | SELECT '' AS four, b.f1 87 | FROM BOX_TBL b -- zero area 88 | WHERE b.f1 >= box '(3.5,3.0,4.5,3.0)'; 89 | 90 | -- right of 91 | SELECT '' AS two, b.f1 92 | FROM BOX_TBL b 93 | WHERE box '(3.0,3.0,5.0,5.0)' >> b.f1; 94 | 95 | -- contained in 96 | SELECT '' AS three, b.f1 97 | FROM BOX_TBL b 98 | WHERE b.f1 <@ box '(0,0,3,3)'; 99 | 100 | -- contains 101 | SELECT '' AS three, b.f1 102 | FROM BOX_TBL b 103 | WHERE box '(0,0,3,3)' @> b.f1; 104 | 105 | -- box equality 106 | SELECT '' AS one, b.f1 107 | FROM BOX_TBL b 108 | WHERE box '(1,1,3,3)' ~= b.f1; 109 | 110 | -- center of box, left unary operator 111 | SELECT '' AS four, @@(b1.f1) AS p 112 | FROM BOX_TBL b1; 113 | 114 | -- wholly-contained 115 | SELECT '' AS one, b1.*, b2.* 116 | FROM BOX_TBL b1, BOX_TBL b2 117 | WHERE b1.f1 @> b2.f1 and not b1.f1 ~= b2.f1; 118 | 119 | SELECT '' AS four, height(f1), width(f1) FROM BOX_TBL; 120 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/btree_index.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- BTREE_INDEX 3 | -- test retrieval of min/max keys for each index 4 | -- 5 | 6 | SELECT b.* 7 | FROM bt_i4_heap b 8 | WHERE b.seqno < 1; 9 | 10 | SELECT b.* 11 | FROM bt_i4_heap b 12 | WHERE b.seqno >= 9999; 13 | 14 | SELECT b.* 15 | FROM bt_i4_heap b 16 | WHERE b.seqno = 4500; 17 | 18 | SELECT b.* 19 | FROM bt_name_heap b 20 | WHERE b.seqno < '1'::name; 21 | 22 | SELECT b.* 23 | FROM bt_name_heap b 24 | WHERE b.seqno >= '9999'::name; 25 | 26 | SELECT b.* 27 | FROM bt_name_heap b 28 | WHERE b.seqno = '4500'::name; 29 | 30 | SELECT b.* 31 | FROM bt_txt_heap b 32 | WHERE b.seqno < '1'::text; 33 | 34 | SELECT b.* 35 | FROM bt_txt_heap b 36 | WHERE b.seqno >= '9999'::text; 37 | 38 | SELECT b.* 39 | FROM bt_txt_heap b 40 | WHERE b.seqno = '4500'::text; 41 | 42 | SELECT b.* 43 | FROM bt_f8_heap b 44 | WHERE b.seqno < '1'::float8; 45 | 46 | SELECT b.* 47 | FROM bt_f8_heap b 48 | WHERE b.seqno >= '9999'::float8; 49 | 50 | SELECT b.* 51 | FROM bt_f8_heap b 52 | WHERE b.seqno = '4500'::float8; 53 | 54 | -- 55 | -- Check correct optimization of LIKE (special index operator support) 56 | -- for both indexscan and bitmapscan cases 57 | -- 58 | 59 | set enable_seqscan to false; 60 | set enable_indexscan to true; 61 | set enable_bitmapscan to false; 62 | select proname from pg_proc where proname like E'RI\\_FKey%del' order by 1; 63 | 64 | set enable_indexscan to false; 65 | set enable_bitmapscan to true; 66 | select proname from pg_proc where proname like E'RI\\_FKey%del' order by 1; 67 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/case.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- CASE 3 | -- Test the case statement 4 | -- 5 | 6 | CREATE TABLE CASE_TBL ( 7 | i integer, 8 | f double precision 9 | ); 10 | 11 | CREATE TABLE CASE2_TBL ( 12 | i integer, 13 | j integer 14 | ); 15 | 16 | INSERT INTO CASE_TBL VALUES (1, 10.1); 17 | INSERT INTO CASE_TBL VALUES (2, 20.2); 18 | INSERT INTO CASE_TBL VALUES (3, -30.3); 19 | INSERT INTO CASE_TBL VALUES (4, NULL); 20 | 21 | INSERT INTO CASE2_TBL VALUES (1, -1); 22 | INSERT INTO CASE2_TBL VALUES (2, -2); 23 | INSERT INTO CASE2_TBL VALUES (3, -3); 24 | INSERT INTO CASE2_TBL VALUES (2, -4); 25 | INSERT INTO CASE2_TBL VALUES (1, NULL); 26 | INSERT INTO CASE2_TBL VALUES (NULL, -6); 27 | 28 | -- 29 | -- Simplest examples without tables 30 | -- 31 | 32 | SELECT '3' AS "One", 33 | CASE 34 | WHEN 1 < 2 THEN 3 35 | END AS "Simple WHEN"; 36 | 37 | SELECT '' AS "One", 38 | CASE 39 | WHEN 1 > 2 THEN 3 40 | END AS "Simple default"; 41 | 42 | SELECT '3' AS "One", 43 | CASE 44 | WHEN 1 < 2 THEN 3 45 | ELSE 4 46 | END AS "Simple ELSE"; 47 | 48 | SELECT '4' AS "One", 49 | CASE 50 | WHEN 1 > 2 THEN 3 51 | ELSE 4 52 | END AS "ELSE default"; 53 | 54 | SELECT '6' AS "One", 55 | CASE 56 | WHEN 1 > 2 THEN 3 57 | WHEN 4 < 5 THEN 6 58 | ELSE 7 59 | END AS "Two WHEN with default"; 60 | 61 | -- Constant-expression folding shouldn't evaluate unreachable subexpressions 62 | SELECT CASE WHEN 1=0 THEN 1/0 WHEN 1=1 THEN 1 ELSE 2/0 END; 63 | SELECT CASE 1 WHEN 0 THEN 1/0 WHEN 1 THEN 1 ELSE 2/0 END; 64 | 65 | -- However we do not currently suppress folding of potentially 66 | -- reachable subexpressions 67 | SELECT CASE WHEN i > 100 THEN 1/0 ELSE 0 END FROM case_tbl; 68 | 69 | -- Test for cases involving untyped literals in test expression 70 | SELECT CASE 'a' WHEN 'a' THEN 1 ELSE 2 END; 71 | 72 | -- 73 | -- Examples of targets involving tables 74 | -- 75 | 76 | SELECT '' AS "Five", 77 | CASE 78 | WHEN i >= 3 THEN i 79 | END AS ">= 3 or Null" 80 | FROM CASE_TBL; 81 | 82 | SELECT '' AS "Five", 83 | CASE WHEN i >= 3 THEN (i + i) 84 | ELSE i 85 | END AS "Simplest Math" 86 | FROM CASE_TBL; 87 | 88 | SELECT '' AS "Five", i AS "Value", 89 | CASE WHEN (i < 0) THEN 'small' 90 | WHEN (i = 0) THEN 'zero' 91 | WHEN (i = 1) THEN 'one' 92 | WHEN (i = 2) THEN 'two' 93 | ELSE 'big' 94 | END AS "Category" 95 | FROM CASE_TBL; 96 | 97 | SELECT '' AS "Five", 98 | CASE WHEN ((i < 0) or (i < 0)) THEN 'small' 99 | WHEN ((i = 0) or (i = 0)) THEN 'zero' 100 | WHEN ((i = 1) or (i = 1)) THEN 'one' 101 | WHEN ((i = 2) or (i = 2)) THEN 'two' 102 | ELSE 'big' 103 | END AS "Category" 104 | FROM CASE_TBL; 105 | 106 | -- 107 | -- Examples of qualifications involving tables 108 | -- 109 | 110 | -- 111 | -- NULLIF() and COALESCE() 112 | -- Shorthand forms for typical CASE constructs 113 | -- defined in the SQL92 standard. 114 | -- 115 | 116 | SELECT * FROM CASE_TBL WHERE COALESCE(f,i) = 4; 117 | 118 | SELECT * FROM CASE_TBL WHERE NULLIF(f,i) = 2; 119 | 120 | SELECT COALESCE(a.f, b.i, b.j) 121 | FROM CASE_TBL a, CASE2_TBL b; 122 | 123 | SELECT * 124 | FROM CASE_TBL a, CASE2_TBL b 125 | WHERE COALESCE(a.f, b.i, b.j) = 2; 126 | 127 | SELECT '' AS Five, NULLIF(a.i,b.i) AS "NULLIF(a.i,b.i)", 128 | NULLIF(b.i, 4) AS "NULLIF(b.i,4)" 129 | FROM CASE_TBL a, CASE2_TBL b; 130 | 131 | SELECT '' AS "Two", * 132 | FROM CASE_TBL a, CASE2_TBL b 133 | WHERE COALESCE(f,b.i) = 2; 134 | 135 | -- 136 | -- Examples of updates involving tables 137 | -- 138 | 139 | UPDATE CASE_TBL 140 | SET i = CASE WHEN i >= 3 THEN (- i) 141 | ELSE (2 * i) END; 142 | 143 | SELECT * FROM CASE_TBL; 144 | 145 | UPDATE CASE_TBL 146 | SET i = CASE WHEN i >= 2 THEN (2 * i) 147 | ELSE (3 * i) END; 148 | 149 | SELECT * FROM CASE_TBL; 150 | 151 | UPDATE CASE_TBL 152 | SET i = CASE WHEN b.i >= 2 THEN (2 * j) 153 | ELSE (3 * j) END 154 | FROM CASE2_TBL b 155 | WHERE j = -CASE_TBL.i; 156 | 157 | SELECT * FROM CASE_TBL; 158 | 159 | -- 160 | -- Clean up 161 | -- 162 | 163 | DROP TABLE CASE_TBL; 164 | DROP TABLE CASE2_TBL; 165 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/char.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- CHAR 3 | -- 4 | 5 | -- fixed-length by value 6 | -- internally passed by value if <= 4 bytes in storage 7 | 8 | SELECT char 'c' = char 'c' AS true; 9 | 10 | -- 11 | -- Build a table for testing 12 | -- 13 | 14 | CREATE TABLE CHAR_TBL(f1 char); 15 | 16 | INSERT INTO CHAR_TBL (f1) VALUES ('a'); 17 | 18 | INSERT INTO CHAR_TBL (f1) VALUES ('A'); 19 | 20 | -- any of the following three input formats are acceptable 21 | INSERT INTO CHAR_TBL (f1) VALUES ('1'); 22 | 23 | INSERT INTO CHAR_TBL (f1) VALUES (2); 24 | 25 | INSERT INTO CHAR_TBL (f1) VALUES ('3'); 26 | 27 | -- zero-length char 28 | INSERT INTO CHAR_TBL (f1) VALUES (''); 29 | 30 | -- try char's of greater than 1 length 31 | INSERT INTO CHAR_TBL (f1) VALUES ('cd'); 32 | INSERT INTO CHAR_TBL (f1) VALUES ('c '); 33 | 34 | 35 | SELECT '' AS seven, * FROM CHAR_TBL; 36 | 37 | SELECT '' AS six, c.* 38 | FROM CHAR_TBL c 39 | WHERE c.f1 <> 'a'; 40 | 41 | SELECT '' AS one, c.* 42 | FROM CHAR_TBL c 43 | WHERE c.f1 = 'a'; 44 | 45 | SELECT '' AS five, c.* 46 | FROM CHAR_TBL c 47 | WHERE c.f1 < 'a'; 48 | 49 | SELECT '' AS six, c.* 50 | FROM CHAR_TBL c 51 | WHERE c.f1 <= 'a'; 52 | 53 | SELECT '' AS one, c.* 54 | FROM CHAR_TBL c 55 | WHERE c.f1 > 'a'; 56 | 57 | SELECT '' AS two, c.* 58 | FROM CHAR_TBL c 59 | WHERE c.f1 >= 'a'; 60 | 61 | DROP TABLE CHAR_TBL; 62 | 63 | -- 64 | -- Now test longer arrays of char 65 | -- 66 | 67 | CREATE TABLE CHAR_TBL(f1 char(4)); 68 | 69 | INSERT INTO CHAR_TBL (f1) VALUES ('a'); 70 | INSERT INTO CHAR_TBL (f1) VALUES ('ab'); 71 | INSERT INTO CHAR_TBL (f1) VALUES ('abcd'); 72 | INSERT INTO CHAR_TBL (f1) VALUES ('abcde'); 73 | INSERT INTO CHAR_TBL (f1) VALUES ('abcd '); 74 | 75 | SELECT '' AS four, * FROM CHAR_TBL; 76 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/circle.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- CIRCLE 3 | -- 4 | 5 | CREATE TABLE CIRCLE_TBL (f1 circle); 6 | 7 | INSERT INTO CIRCLE_TBL VALUES ('<(5,1),3>'); 8 | 9 | INSERT INTO CIRCLE_TBL VALUES ('<(1,2),100>'); 10 | 11 | INSERT INTO CIRCLE_TBL VALUES ('1,3,5'); 12 | 13 | INSERT INTO CIRCLE_TBL VALUES ('((1,2),3)'); 14 | 15 | INSERT INTO CIRCLE_TBL VALUES ('<(100,200),10>'); 16 | 17 | INSERT INTO CIRCLE_TBL VALUES ('<(100,1),115>'); 18 | 19 | -- bad values 20 | 21 | INSERT INTO CIRCLE_TBL VALUES ('<(-100,0),-100>'); 22 | 23 | INSERT INTO CIRCLE_TBL VALUES ('1abc,3,5'); 24 | 25 | INSERT INTO CIRCLE_TBL VALUES ('(3,(1,2),3)'); 26 | 27 | SELECT * FROM CIRCLE_TBL; 28 | 29 | SELECT '' AS six, center(f1) AS center 30 | FROM CIRCLE_TBL; 31 | 32 | SELECT '' AS six, radius(f1) AS radius 33 | FROM CIRCLE_TBL; 34 | 35 | SELECT '' AS six, diameter(f1) AS diameter 36 | FROM CIRCLE_TBL; 37 | 38 | SELECT '' AS two, f1 FROM CIRCLE_TBL WHERE radius(f1) < 5; 39 | 40 | SELECT '' AS four, f1 FROM CIRCLE_TBL WHERE diameter(f1) >= 10; 41 | 42 | SELECT '' as five, c1.f1 AS one, c2.f1 AS two, (c1.f1 <-> c2.f1) AS distance 43 | FROM CIRCLE_TBL c1, CIRCLE_TBL c2 44 | WHERE (c1.f1 < c2.f1) AND ((c1.f1 <-> c2.f1) > 0) 45 | ORDER BY distance, area(c1.f1), area(c2.f1); 46 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/combocid.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- Tests for some likely failure cases with combo cmin/cmax mechanism 3 | -- 4 | CREATE TEMP TABLE combocidtest (foobar int); 5 | 6 | BEGIN; 7 | 8 | -- a few dummy ops to push up the CommandId counter 9 | INSERT INTO combocidtest SELECT 1 LIMIT 0; 10 | INSERT INTO combocidtest SELECT 1 LIMIT 0; 11 | INSERT INTO combocidtest SELECT 1 LIMIT 0; 12 | INSERT INTO combocidtest SELECT 1 LIMIT 0; 13 | INSERT INTO combocidtest SELECT 1 LIMIT 0; 14 | INSERT INTO combocidtest SELECT 1 LIMIT 0; 15 | INSERT INTO combocidtest SELECT 1 LIMIT 0; 16 | INSERT INTO combocidtest SELECT 1 LIMIT 0; 17 | INSERT INTO combocidtest SELECT 1 LIMIT 0; 18 | INSERT INTO combocidtest SELECT 1 LIMIT 0; 19 | 20 | INSERT INTO combocidtest VALUES (1); 21 | INSERT INTO combocidtest VALUES (2); 22 | 23 | SELECT ctid,cmin,* FROM combocidtest; 24 | 25 | SAVEPOINT s1; 26 | 27 | UPDATE combocidtest SET foobar = foobar + 10; 28 | 29 | -- here we should see only updated tuples 30 | SELECT ctid,cmin,* FROM combocidtest; 31 | 32 | ROLLBACK TO s1; 33 | 34 | -- now we should see old tuples, but with combo CIDs starting at 0 35 | SELECT ctid,cmin,* FROM combocidtest; 36 | 37 | COMMIT; 38 | 39 | -- combo data is not there anymore, but should still see tuples 40 | SELECT ctid,cmin,* FROM combocidtest; 41 | 42 | -- Test combo cids with portals 43 | BEGIN; 44 | 45 | INSERT INTO combocidtest VALUES (333); 46 | 47 | DECLARE c CURSOR FOR SELECT ctid,cmin,* FROM combocidtest; 48 | 49 | DELETE FROM combocidtest; 50 | 51 | FETCH ALL FROM c; 52 | 53 | ROLLBACK; 54 | 55 | SELECT ctid,cmin,* FROM combocidtest; 56 | 57 | -- check behavior with locked tuples 58 | BEGIN; 59 | 60 | -- a few dummy ops to push up the CommandId counter 61 | INSERT INTO combocidtest SELECT 1 LIMIT 0; 62 | INSERT INTO combocidtest SELECT 1 LIMIT 0; 63 | INSERT INTO combocidtest SELECT 1 LIMIT 0; 64 | INSERT INTO combocidtest SELECT 1 LIMIT 0; 65 | INSERT INTO combocidtest SELECT 1 LIMIT 0; 66 | INSERT INTO combocidtest SELECT 1 LIMIT 0; 67 | INSERT INTO combocidtest SELECT 1 LIMIT 0; 68 | INSERT INTO combocidtest SELECT 1 LIMIT 0; 69 | INSERT INTO combocidtest SELECT 1 LIMIT 0; 70 | INSERT INTO combocidtest SELECT 1 LIMIT 0; 71 | 72 | INSERT INTO combocidtest VALUES (444); 73 | 74 | SELECT ctid,cmin,* FROM combocidtest; 75 | 76 | SAVEPOINT s1; 77 | 78 | -- this doesn't affect cmin 79 | SELECT ctid,cmin,* FROM combocidtest FOR UPDATE; 80 | SELECT ctid,cmin,* FROM combocidtest; 81 | 82 | -- but this does 83 | UPDATE combocidtest SET foobar = foobar + 10; 84 | 85 | SELECT ctid,cmin,* FROM combocidtest; 86 | 87 | ROLLBACK TO s1; 88 | 89 | SELECT ctid,cmin,* FROM combocidtest; 90 | 91 | COMMIT; 92 | 93 | SELECT ctid,cmin,* FROM combocidtest; 94 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/comments.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- COMMENTS 3 | -- 4 | 5 | SELECT 'trailing' AS first; -- trailing single line 6 | SELECT /* embedded single line */ 'embedded' AS second; 7 | SELECT /* both embedded and trailing single line */ 'both' AS third; -- trailing single line 8 | 9 | SELECT 'before multi-line' AS fourth; 10 | /* This is an example of SQL which should not execute: 11 | * select 'multi-line'; 12 | */ 13 | SELECT 'after multi-line' AS fifth; 14 | 15 | -- 16 | -- Nested comments 17 | -- 18 | 19 | /* 20 | SELECT 'trailing' as x1; -- inside block comment 21 | */ 22 | 23 | /* This block comment surrounds a query which itself has a block comment... 24 | SELECT /* embedded single line */ 'embedded' AS x2; 25 | */ 26 | 27 | SELECT -- continued after the following block comments... 28 | /* Deeply nested comment. 29 | This includes a single apostrophe to make sure we aren't decoding this part as a string. 30 | SELECT 'deep nest' AS n1; 31 | /* Second level of nesting... 32 | SELECT 'deeper nest' as n2; 33 | /* Third level of nesting... 34 | SELECT 'deepest nest' as n3; 35 | */ 36 | Hoo boy. Still two deep... 37 | */ 38 | Now just one deep... 39 | */ 40 | 'deeply nested example' AS sixth; 41 | 42 | /* and this is the end of the file */ 43 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/copy2.sql: -------------------------------------------------------------------------------- 1 | CREATE TEMP TABLE x ( 2 | a serial, 3 | b int, 4 | c text not null default 'stuff', 5 | d text, 6 | e text 7 | ) WITH OIDS; 8 | 9 | CREATE FUNCTION fn_x_before () RETURNS TRIGGER AS ' 10 | BEGIN 11 | NEW.e := ''before trigger fired''::text; 12 | return NEW; 13 | END; 14 | ' LANGUAGE plpgsql; 15 | 16 | CREATE FUNCTION fn_x_after () RETURNS TRIGGER AS ' 17 | BEGIN 18 | UPDATE x set e=''after trigger fired'' where c=''stuff''; 19 | return NULL; 20 | END; 21 | ' LANGUAGE plpgsql; 22 | 23 | CREATE TRIGGER trg_x_after AFTER INSERT ON x 24 | FOR EACH ROW EXECUTE PROCEDURE fn_x_after(); 25 | 26 | CREATE TRIGGER trg_x_before BEFORE INSERT ON x 27 | FOR EACH ROW EXECUTE PROCEDURE fn_x_before(); 28 | 29 | COPY x (a, b, c, d, e) from stdin; 30 | 9999 \N \\N \NN \N 31 | 10000 21 31 41 51 32 | \. 33 | 34 | COPY x (b, d) from stdin; 35 | 1 test_1 36 | \. 37 | 38 | COPY x (b, d) from stdin; 39 | 2 test_2 40 | 3 test_3 41 | 4 test_4 42 | 5 test_5 43 | \. 44 | 45 | COPY x (a, b, c, d, e) from stdin; 46 | 10001 22 32 42 52 47 | 10002 23 33 43 53 48 | 10003 24 34 44 54 49 | 10004 25 35 45 55 50 | 10005 26 36 46 56 51 | \. 52 | 53 | -- non-existent column in column list: should fail 54 | COPY x (xyz) from stdin; 55 | 56 | -- too many columns in column list: should fail 57 | COPY x (a, b, c, d, e, d, c) from stdin; 58 | 59 | -- missing data: should fail 60 | COPY x from stdin; 61 | 62 | \. 63 | COPY x from stdin; 64 | 2000 230 23 23 65 | \. 66 | COPY x from stdin; 67 | 2001 231 \N \N 68 | \. 69 | 70 | -- extra data: should fail 71 | COPY x from stdin; 72 | 2002 232 40 50 60 70 80 73 | \. 74 | 75 | -- various COPY options: delimiters, oids, NULL string, encoding 76 | COPY x (b, c, d, e) from stdin with oids delimiter ',' null 'x'; 77 | 500000,x,45,80,90 78 | 500001,x,\x,\\x,\\\x 79 | 500002,x,\,,\\\,,\\ 80 | \. 81 | 82 | COPY x from stdin WITH DELIMITER AS ';' NULL AS ''; 83 | 3000;;c;; 84 | \. 85 | 86 | COPY x from stdin WITH DELIMITER AS ':' NULL AS E'\\X' ENCODING 'sql_ascii'; 87 | 4000:\X:C:\X:\X 88 | 4001:1:empty:: 89 | 4002:2:null:\X:\X 90 | 4003:3:Backslash:\\:\\ 91 | 4004:4:BackslashX:\\X:\\X 92 | 4005:5:N:\N:\N 93 | 4006:6:BackslashN:\\N:\\N 94 | 4007:7:XX:\XX:\XX 95 | 4008:8:Delimiter:\::\: 96 | \. 97 | 98 | -- check results of copy in 99 | SELECT * FROM x; 100 | 101 | -- COPY w/ oids on a table w/o oids should fail 102 | CREATE TABLE no_oids ( 103 | a int, 104 | b int 105 | ) WITHOUT OIDS; 106 | 107 | INSERT INTO no_oids (a, b) VALUES (5, 10); 108 | INSERT INTO no_oids (a, b) VALUES (20, 30); 109 | 110 | -- should fail 111 | COPY no_oids FROM stdin WITH OIDS; 112 | COPY no_oids TO stdout WITH OIDS; 113 | 114 | -- check copy out 115 | COPY x TO stdout; 116 | COPY x (c, e) TO stdout; 117 | COPY x (b, e) TO stdout WITH NULL 'I''m null'; 118 | 119 | CREATE TEMP TABLE y ( 120 | col1 text, 121 | col2 text 122 | ); 123 | 124 | INSERT INTO y VALUES ('Jackson, Sam', E'\\h'); 125 | INSERT INTO y VALUES ('It is "perfect".',E'\t'); 126 | INSERT INTO y VALUES ('', NULL); 127 | 128 | COPY y TO stdout WITH CSV; 129 | COPY y TO stdout WITH CSV QUOTE '''' DELIMITER '|'; 130 | COPY y TO stdout WITH CSV FORCE QUOTE col2 ESCAPE E'\\' ENCODING 'sql_ascii'; 131 | COPY y TO stdout WITH CSV FORCE QUOTE *; 132 | 133 | -- Repeat above tests with new 9.0 option syntax 134 | 135 | COPY y TO stdout (FORMAT CSV); 136 | COPY y TO stdout (FORMAT CSV, QUOTE '''', DELIMITER '|'); 137 | COPY y TO stdout (FORMAT CSV, FORCE_QUOTE (col2), ESCAPE E'\\'); 138 | COPY y TO stdout (FORMAT CSV, FORCE_QUOTE *); 139 | 140 | \copy y TO stdout (FORMAT CSV) 141 | \copy y TO stdout (FORMAT CSV, QUOTE '''', DELIMITER '|') 142 | \copy y TO stdout (FORMAT CSV, FORCE_QUOTE (col2), ESCAPE E'\\') 143 | \copy y TO stdout (FORMAT CSV, FORCE_QUOTE *) 144 | 145 | --test that we read consecutive LFs properly 146 | 147 | CREATE TEMP TABLE testnl (a int, b text, c int); 148 | 149 | COPY testnl FROM stdin CSV; 150 | 1,"a field with two LFs 151 | 152 | inside",2 153 | \. 154 | 155 | -- test end of copy marker 156 | CREATE TEMP TABLE testeoc (a text); 157 | 158 | COPY testeoc FROM stdin CSV; 159 | a\. 160 | \.b 161 | c\.d 162 | "\." 163 | \. 164 | 165 | COPY testeoc TO stdout CSV; 166 | 167 | -- test handling of nonstandard null marker that violates escaping rules 168 | 169 | CREATE TEMP TABLE testnull(a int, b text); 170 | INSERT INTO testnull VALUES (1, E'\\0'), (NULL, NULL); 171 | 172 | COPY testnull TO stdout WITH NULL AS E'\\0'; 173 | 174 | COPY testnull FROM stdin WITH NULL AS E'\\0'; 175 | 42 \\0 176 | \0 \0 177 | \. 178 | 179 | SELECT * FROM testnull; 180 | 181 | 182 | DROP TABLE x, y; 183 | DROP FUNCTION fn_x_before(); 184 | DROP FUNCTION fn_x_after(); 185 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/copyselect.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- Test cases for COPY (select) TO 3 | -- 4 | create table test1 (id serial, t text); 5 | insert into test1 (t) values ('a'); 6 | insert into test1 (t) values ('b'); 7 | insert into test1 (t) values ('c'); 8 | insert into test1 (t) values ('d'); 9 | insert into test1 (t) values ('e'); 10 | 11 | create table test2 (id serial, t text); 12 | insert into test2 (t) values ('A'); 13 | insert into test2 (t) values ('B'); 14 | insert into test2 (t) values ('C'); 15 | insert into test2 (t) values ('D'); 16 | insert into test2 (t) values ('E'); 17 | 18 | create view v_test1 19 | as select 'v_'||t from test1; 20 | 21 | -- 22 | -- Test COPY table TO 23 | -- 24 | copy test1 to stdout; 25 | -- 26 | -- This should fail 27 | -- 28 | copy v_test1 to stdout; 29 | -- 30 | -- Test COPY (select) TO 31 | -- 32 | copy (select t from test1 where id=1) to stdout; 33 | -- 34 | -- Test COPY (select for update) TO 35 | -- 36 | copy (select t from test1 where id=3 for update) to stdout; 37 | -- 38 | -- This should fail 39 | -- 40 | copy (select t into temp test3 from test1 where id=3) to stdout; 41 | -- 42 | -- This should fail 43 | -- 44 | copy (select * from test1) from stdin; 45 | -- 46 | -- This should fail 47 | -- 48 | copy (select * from test1) (t,id) to stdout; 49 | -- 50 | -- Test JOIN 51 | -- 52 | copy (select * from test1 join test2 using (id)) to stdout; 53 | -- 54 | -- Test UNION SELECT 55 | -- 56 | copy (select t from test1 where id = 1 UNION select * from v_test1 ORDER BY 1) to stdout; 57 | -- 58 | -- Test subselect 59 | -- 60 | copy (select * from (select t from test1 where id = 1 UNION select * from v_test1 ORDER BY 1) t1) to stdout; 61 | -- 62 | -- Test headers, CSV and quotes 63 | -- 64 | copy (select t from test1 where id = 1) to stdout csv header force quote t; 65 | -- 66 | -- Test psql builtins, plain table 67 | -- 68 | \copy test1 to stdout 69 | -- 70 | -- This should fail 71 | -- 72 | \copy v_test1 to stdout 73 | -- 74 | -- Test \copy (select ...) 75 | -- 76 | \copy (select "id",'id','id""'||t,(id + 1)*id,t,"test1"."t" from test1 where id=3) to stdout 77 | -- 78 | -- Drop everything 79 | -- 80 | drop table test2; 81 | drop view v_test1; 82 | drop table test1; 83 | 84 | -- psql handling of COPY in multi-command strings 85 | copy (select 1) to stdout\; select 1/0; -- row, then error 86 | select 1/0\; copy (select 1) to stdout; -- error only 87 | copy (select 1) to stdout\; copy (select 2) to stdout\; select 0\; select 3; -- 1 2 3 88 | 89 | create table test3 (c int); 90 | select 0\; copy test3 from stdin\; copy test3 from stdin\; select 1; -- 1 91 | 1 92 | \. 93 | 2 94 | \. 95 | select * from test3; 96 | drop table test3; 97 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/create_aggregate.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- CREATE_AGGREGATE 3 | -- 4 | 5 | -- all functions CREATEd 6 | CREATE AGGREGATE newavg ( 7 | sfunc = int4_avg_accum, basetype = int4, stype = _int8, 8 | finalfunc = int8_avg, 9 | initcond1 = '{0,0}' 10 | ); 11 | 12 | -- test comments 13 | COMMENT ON AGGREGATE newavg_wrong (int4) IS 'an agg comment'; 14 | COMMENT ON AGGREGATE newavg (int4) IS 'an agg comment'; 15 | COMMENT ON AGGREGATE newavg (int4) IS NULL; 16 | 17 | -- without finalfunc; test obsolete spellings 'sfunc1' etc 18 | CREATE AGGREGATE newsum ( 19 | sfunc1 = int4pl, basetype = int4, stype1 = int4, 20 | initcond1 = '0' 21 | ); 22 | 23 | -- zero-argument aggregate 24 | CREATE AGGREGATE newcnt (*) ( 25 | sfunc = int8inc, stype = int8, 26 | initcond = '0' 27 | ); 28 | 29 | -- old-style spelling of same 30 | CREATE AGGREGATE oldcnt ( 31 | sfunc = int8inc, basetype = 'ANY', stype = int8, 32 | initcond = '0' 33 | ); 34 | 35 | -- aggregate that only cares about null/nonnull input 36 | CREATE AGGREGATE newcnt ("any") ( 37 | sfunc = int8inc_any, stype = int8, 38 | initcond = '0' 39 | ); 40 | 41 | COMMENT ON AGGREGATE nosuchagg (*) IS 'should fail'; 42 | COMMENT ON AGGREGATE newcnt (*) IS 'an agg(*) comment'; 43 | COMMENT ON AGGREGATE newcnt ("any") IS 'an agg(any) comment'; 44 | 45 | -- multi-argument aggregate 46 | create function sum3(int8,int8,int8) returns int8 as 47 | 'select $1 + $2 + $3' language sql strict immutable; 48 | 49 | create aggregate sum2(int8,int8) ( 50 | sfunc = sum3, stype = int8, 51 | initcond = '0' 52 | ); 53 | 54 | -- multi-argument aggregates sensitive to distinct/order, strict/nonstrict 55 | create type aggtype as (a integer, b integer, c text); 56 | 57 | create function aggf_trans(aggtype[],integer,integer,text) returns aggtype[] 58 | as 'select array_append($1,ROW($2,$3,$4)::aggtype)' 59 | language sql strict immutable; 60 | 61 | create function aggfns_trans(aggtype[],integer,integer,text) returns aggtype[] 62 | as 'select array_append($1,ROW($2,$3,$4)::aggtype)' 63 | language sql immutable; 64 | 65 | create aggregate aggfstr(integer,integer,text) ( 66 | sfunc = aggf_trans, stype = aggtype[], 67 | initcond = '{}' 68 | ); 69 | 70 | create aggregate aggfns(integer,integer,text) ( 71 | sfunc = aggfns_trans, stype = aggtype[], 72 | initcond = '{}' 73 | ); 74 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/create_cast.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- CREATE_CAST 3 | -- 4 | 5 | -- Create some types to test with 6 | CREATE TYPE casttesttype; 7 | 8 | CREATE FUNCTION casttesttype_in(cstring) 9 | RETURNS casttesttype 10 | AS 'textin' 11 | LANGUAGE internal STRICT; 12 | CREATE FUNCTION casttesttype_out(casttesttype) 13 | RETURNS cstring 14 | AS 'textout' 15 | LANGUAGE internal STRICT; 16 | 17 | CREATE TYPE casttesttype ( 18 | internallength = variable, 19 | input = casttesttype_in, 20 | output = casttesttype_out, 21 | alignment = int4 22 | ); 23 | 24 | -- a dummy function to test with 25 | CREATE FUNCTION casttestfunc(casttesttype) RETURNS int4 LANGUAGE SQL AS 26 | $$ SELECT 1; $$; 27 | 28 | SELECT casttestfunc('foo'::text); -- fails, as there's no cast 29 | 30 | -- Try binary coercion cast 31 | CREATE CAST (text AS casttesttype) WITHOUT FUNCTION; 32 | SELECT casttestfunc('foo'::text); -- doesn't work, as the cast is explicit 33 | SELECT casttestfunc('foo'::text::casttesttype); -- should work 34 | DROP CAST (text AS casttesttype); -- cleanup 35 | 36 | -- Try IMPLICIT binary coercion cast 37 | CREATE CAST (text AS casttesttype) WITHOUT FUNCTION AS IMPLICIT; 38 | SELECT casttestfunc('foo'::text); -- Should work now 39 | 40 | -- Try I/O conversion cast. 41 | SELECT 1234::int4::casttesttype; -- No cast yet, should fail 42 | 43 | CREATE CAST (int4 AS casttesttype) WITH INOUT; 44 | SELECT 1234::int4::casttesttype; -- Should work now 45 | 46 | DROP CAST (int4 AS casttesttype); 47 | 48 | -- Try cast with a function 49 | 50 | CREATE FUNCTION int4_casttesttype(int4) RETURNS casttesttype LANGUAGE SQL AS 51 | $$ SELECT ('foo'::text || $1::text)::casttesttype; $$; 52 | 53 | CREATE CAST (int4 AS casttesttype) WITH FUNCTION int4_casttesttype(int4) AS IMPLICIT; 54 | SELECT 1234::int4::casttesttype; -- Should work now 55 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/create_operator.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- CREATE_OPERATOR 3 | -- 4 | 5 | CREATE OPERATOR ## ( 6 | leftarg = path, 7 | rightarg = path, 8 | procedure = path_inter, 9 | commutator = ## 10 | ); 11 | 12 | CREATE OPERATOR <% ( 13 | leftarg = point, 14 | rightarg = widget, 15 | procedure = pt_in_widget, 16 | commutator = >% , 17 | negator = >=% 18 | ); 19 | 20 | CREATE OPERATOR @#@ ( 21 | rightarg = int8, -- left unary 22 | procedure = numeric_fac 23 | ); 24 | 25 | CREATE OPERATOR #@# ( 26 | leftarg = int8, -- right unary 27 | procedure = numeric_fac 28 | ); 29 | 30 | CREATE OPERATOR #%# ( 31 | leftarg = int8, -- right unary 32 | procedure = numeric_fac 33 | ); 34 | 35 | -- Test comments 36 | COMMENT ON OPERATOR ###### (int4, NONE) IS 'bad right unary'; 37 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/create_type.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- CREATE_TYPE 3 | -- 4 | 5 | -- 6 | -- Note: widget_in/out were created in create_function_1, without any 7 | -- prior shell-type creation. These commands therefore complete a test 8 | -- of the "old style" approach of making the functions first. 9 | -- 10 | CREATE TYPE widget ( 11 | internallength = 24, 12 | input = widget_in, 13 | output = widget_out, 14 | typmod_in = numerictypmodin, 15 | typmod_out = numerictypmodout, 16 | alignment = double 17 | ); 18 | 19 | CREATE TYPE city_budget ( 20 | internallength = 16, 21 | input = int44in, 22 | output = int44out, 23 | element = int4, 24 | category = 'x', -- just to verify the system will take it 25 | preferred = true -- ditto 26 | ); 27 | 28 | -- Test creation and destruction of shell types 29 | CREATE TYPE shell; 30 | CREATE TYPE shell; -- fail, type already present 31 | DROP TYPE shell; 32 | DROP TYPE shell; -- fail, type not exist 33 | 34 | -- 35 | -- Test type-related default values (broken in releases before PG 7.2) 36 | -- 37 | -- This part of the test also exercises the "new style" approach of making 38 | -- a shell type and then filling it in. 39 | -- 40 | CREATE TYPE int42; 41 | CREATE TYPE text_w_default; 42 | 43 | -- Make dummy I/O routines using the existing internal support for int4, text 44 | CREATE FUNCTION int42_in(cstring) 45 | RETURNS int42 46 | AS 'int4in' 47 | LANGUAGE internal STRICT; 48 | CREATE FUNCTION int42_out(int42) 49 | RETURNS cstring 50 | AS 'int4out' 51 | LANGUAGE internal STRICT; 52 | CREATE FUNCTION text_w_default_in(cstring) 53 | RETURNS text_w_default 54 | AS 'textin' 55 | LANGUAGE internal STRICT; 56 | CREATE FUNCTION text_w_default_out(text_w_default) 57 | RETURNS cstring 58 | AS 'textout' 59 | LANGUAGE internal STRICT; 60 | 61 | CREATE TYPE int42 ( 62 | internallength = 4, 63 | input = int42_in, 64 | output = int42_out, 65 | alignment = int4, 66 | default = 42, 67 | passedbyvalue 68 | ); 69 | 70 | CREATE TYPE text_w_default ( 71 | internallength = variable, 72 | input = text_w_default_in, 73 | output = text_w_default_out, 74 | alignment = int4, 75 | default = 'zippo' 76 | ); 77 | 78 | CREATE TABLE default_test (f1 text_w_default, f2 int42); 79 | 80 | INSERT INTO default_test DEFAULT VALUES; 81 | 82 | SELECT * FROM default_test; 83 | 84 | -- Test stand-alone composite type 85 | 86 | CREATE TYPE default_test_row AS (f1 text_w_default, f2 int42); 87 | 88 | CREATE FUNCTION get_default_test() RETURNS SETOF default_test_row AS ' 89 | SELECT * FROM default_test; 90 | ' LANGUAGE SQL; 91 | 92 | SELECT * FROM get_default_test(); 93 | 94 | -- Test comments 95 | COMMENT ON TYPE bad IS 'bad comment'; 96 | COMMENT ON TYPE default_test_row IS 'good comment'; 97 | COMMENT ON TYPE default_test_row IS NULL; 98 | COMMENT ON COLUMN default_test_row.nope IS 'bad comment'; 99 | COMMENT ON COLUMN default_test_row.f1 IS 'good comment'; 100 | COMMENT ON COLUMN default_test_row.f1 IS NULL; 101 | 102 | -- Check shell type create for existing types 103 | CREATE TYPE text_w_default; -- should fail 104 | 105 | DROP TYPE default_test_row CASCADE; 106 | 107 | DROP TABLE default_test; 108 | 109 | -- Check usage of typmod with a user-defined type 110 | -- (we have borrowed numeric's typmod functions) 111 | 112 | CREATE TEMP TABLE mytab (foo widget(42,13,7)); -- should fail 113 | CREATE TEMP TABLE mytab (foo widget(42,13)); 114 | 115 | SELECT format_type(atttypid,atttypmod) FROM pg_attribute 116 | WHERE attrelid = 'mytab'::regclass AND attnum > 0; 117 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/delete.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE delete_test ( 2 | id SERIAL PRIMARY KEY, 3 | a INT, 4 | b text 5 | ); 6 | 7 | INSERT INTO delete_test (a) VALUES (10); 8 | INSERT INTO delete_test (a, b) VALUES (50, repeat('x', 10000)); 9 | INSERT INTO delete_test (a) VALUES (100); 10 | 11 | -- allow an alias to be specified for DELETE's target table 12 | DELETE FROM delete_test AS dt WHERE dt.a > 75; 13 | 14 | -- if an alias is specified, don't allow the original table name 15 | -- to be referenced 16 | DELETE FROM delete_test dt WHERE delete_test.a > 25; 17 | 18 | SELECT id, a, char_length(b) FROM delete_test; 19 | 20 | -- delete a row with a TOASTed value 21 | DELETE FROM delete_test WHERE a > 25; 22 | 23 | SELECT id, a, char_length(b) FROM delete_test; 24 | 25 | DROP TABLE delete_test; 26 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/dependency.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- DEPENDENCIES 3 | -- 4 | 5 | CREATE USER regression_user; 6 | CREATE USER regression_user2; 7 | CREATE USER regression_user3; 8 | CREATE GROUP regression_group; 9 | 10 | CREATE TABLE deptest (f1 serial primary key, f2 text); 11 | 12 | GRANT SELECT ON TABLE deptest TO GROUP regression_group; 13 | GRANT ALL ON TABLE deptest TO regression_user, regression_user2; 14 | 15 | -- can't drop neither because they have privileges somewhere 16 | DROP USER regression_user; 17 | DROP GROUP regression_group; 18 | 19 | -- if we revoke the privileges we can drop the group 20 | REVOKE SELECT ON deptest FROM GROUP regression_group; 21 | DROP GROUP regression_group; 22 | 23 | -- can't drop the user if we revoke the privileges partially 24 | REVOKE SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES ON deptest FROM regression_user; 25 | DROP USER regression_user; 26 | 27 | -- now we are OK to drop him 28 | REVOKE TRIGGER ON deptest FROM regression_user; 29 | DROP USER regression_user; 30 | 31 | -- we are OK too if we drop the privileges all at once 32 | REVOKE ALL ON deptest FROM regression_user2; 33 | DROP USER regression_user2; 34 | 35 | -- can't drop the owner of an object 36 | -- the error message detail here would include a pg_toast_nnn name that 37 | -- is not constant, so suppress it 38 | \set VERBOSITY terse 39 | ALTER TABLE deptest OWNER TO regression_user3; 40 | DROP USER regression_user3; 41 | 42 | \set VERBOSITY default 43 | -- if we drop the object, we can drop the user too 44 | DROP TABLE deptest; 45 | DROP USER regression_user3; 46 | 47 | -- Test DROP OWNED 48 | CREATE USER regression_user0; 49 | CREATE USER regression_user1; 50 | CREATE USER regression_user2; 51 | SET SESSION AUTHORIZATION regression_user0; 52 | -- permission denied 53 | DROP OWNED BY regression_user1; 54 | DROP OWNED BY regression_user0, regression_user2; 55 | REASSIGN OWNED BY regression_user0 TO regression_user1; 56 | REASSIGN OWNED BY regression_user1 TO regression_user0; 57 | -- this one is allowed 58 | DROP OWNED BY regression_user0; 59 | 60 | CREATE TABLE deptest1 (f1 int unique); 61 | GRANT ALL ON deptest1 TO regression_user1 WITH GRANT OPTION; 62 | 63 | SET SESSION AUTHORIZATION regression_user1; 64 | CREATE TABLE deptest (a serial primary key, b text); 65 | GRANT ALL ON deptest1 TO regression_user2; 66 | RESET SESSION AUTHORIZATION; 67 | \z deptest1 68 | 69 | DROP OWNED BY regression_user1; 70 | -- all grants revoked 71 | \z deptest1 72 | -- table was dropped 73 | \d deptest 74 | 75 | -- Test REASSIGN OWNED 76 | GRANT ALL ON deptest1 TO regression_user1; 77 | 78 | SET SESSION AUTHORIZATION regression_user1; 79 | CREATE TABLE deptest (a serial primary key, b text); 80 | 81 | CREATE TABLE deptest2 (f1 int); 82 | -- make a serial column the hard way 83 | CREATE SEQUENCE ss1; 84 | ALTER TABLE deptest2 ALTER f1 SET DEFAULT nextval('ss1'); 85 | ALTER SEQUENCE ss1 OWNED BY deptest2.f1; 86 | RESET SESSION AUTHORIZATION; 87 | 88 | REASSIGN OWNED BY regression_user1 TO regression_user2; 89 | \dt deptest 90 | 91 | -- doesn't work: grant still exists 92 | DROP USER regression_user1; 93 | DROP OWNED BY regression_user1; 94 | DROP USER regression_user1; 95 | 96 | \set VERBOSITY terse 97 | DROP USER regression_user2; 98 | DROP OWNED BY regression_user2, regression_user0; 99 | DROP USER regression_user2; 100 | DROP USER regression_user0; 101 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/drop.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- drop.source 3 | -- 4 | 5 | -- 6 | -- this will fail if the user is not the postgres superuser. 7 | -- if it does, don't worry about it (you can turn usersuper 8 | -- back on as "postgres"). too many people don't follow 9 | -- directions and run this as "postgres", though... 10 | -- 11 | UPDATE pg_user 12 | SET usesuper = 't'::bool 13 | WHERE usename = 'postgres'; 14 | 15 | 16 | -- 17 | -- FUNCTION REMOVAL 18 | -- 19 | DROP FUNCTION hobbies(person); 20 | 21 | DROP FUNCTION hobby_construct(text,text); 22 | 23 | DROP FUNCTION equipment(hobbies_r); 24 | 25 | DROP FUNCTION user_relns(); 26 | 27 | DROP FUNCTION widget_in(cstring); 28 | 29 | DROP FUNCTION widget_out(widget); 30 | 31 | DROP FUNCTION pt_in_widget(point,widget); 32 | 33 | DROP FUNCTION overpaid(emp); 34 | 35 | DROP FUNCTION boxarea(box); 36 | 37 | DROP FUNCTION interpt_pp(path,path); 38 | 39 | DROP FUNCTION reverse_name(name); 40 | 41 | DROP FUNCTION oldstyle_length(int4, text); 42 | 43 | -- 44 | -- OPERATOR REMOVAL 45 | -- 46 | DROP OPERATOR ## (path, path); 47 | 48 | DROP OPERATOR <% (point, widget); 49 | 50 | -- left unary 51 | DROP OPERATOR @#@ (none, int4); 52 | 53 | -- right unary 54 | DROP OPERATOR #@# (int4, none); 55 | 56 | -- right unary 57 | DROP OPERATOR #%# (int4, none); 58 | 59 | 60 | -- 61 | -- ABSTRACT DATA TYPE REMOVAL 62 | -- 63 | DROP TYPE city_budget; 64 | 65 | DROP TYPE widget; 66 | 67 | 68 | -- 69 | -- RULE REMOVAL 70 | -- (is also tested in queries.source) 71 | -- 72 | 73 | -- 74 | -- AGGREGATE REMOVAL 75 | -- 76 | DROP AGGREGATE newavg (int4); 77 | 78 | DROP AGGREGATE newsum (int4); 79 | 80 | DROP AGGREGATE newcnt (int4); 81 | 82 | 83 | -- 84 | -- CLASS REMOVAL 85 | -- (inheritance hierarchies are deleted in reverse order) 86 | -- 87 | 88 | -- 89 | -- DROP ancillary data structures (i.e. indices) 90 | -- 91 | DROP INDEX onek_unique1; 92 | 93 | DROP INDEX onek_unique2; 94 | 95 | DROP INDEX onek_hundred; 96 | 97 | DROP INDEX onek_stringu1; 98 | 99 | DROP INDEX tenk1_unique1; 100 | 101 | DROP INDEX tenk1_unique2; 102 | 103 | DROP INDEX tenk1_hundred; 104 | 105 | DROP INDEX tenk2_unique1; 106 | 107 | DROP INDEX tenk2_unique2; 108 | 109 | DROP INDEX tenk2_hundred; 110 | 111 | -- DROP INDEX onek2_u1_prtl; 112 | 113 | -- DROP INDEX onek2_u2_prtl; 114 | 115 | -- DROP INDEX onek2_stu1_prtl; 116 | 117 | DROP INDEX rect2ind; 118 | 119 | DROP INDEX rix; 120 | 121 | DROP INDEX iix; 122 | 123 | DROP INDEX six; 124 | 125 | DROP INDEX hash_i4_index; 126 | 127 | DROP INDEX hash_name_index; 128 | 129 | DROP INDEX hash_txt_index; 130 | 131 | DROP INDEX hash_f8_index; 132 | 133 | -- DROP INDEX hash_ovfl_index; 134 | 135 | DROP INDEX bt_i4_index; 136 | 137 | DROP INDEX bt_name_index; 138 | 139 | DROP INDEX bt_txt_index; 140 | 141 | DROP INDEX bt_f8_index; 142 | 143 | 144 | DROP TABLE onek; 145 | 146 | DROP TABLE onek2; 147 | 148 | DROP TABLE tenk1; 149 | 150 | DROP TABLE tenk2; 151 | 152 | DROP TABLE Bprime; 153 | 154 | 155 | DROP TABLE hobbies_r; 156 | 157 | DROP TABLE equipment_r; 158 | 159 | 160 | DROP TABLE aggtest; 161 | 162 | DROP TABLE xacttest; 163 | 164 | DROP TABLE arrtest; 165 | 166 | DROP TABLE iportaltest; 167 | 168 | 169 | DROP TABLE f_star; 170 | 171 | DROP TABLE e_star; 172 | 173 | DROP TABLE d_star; 174 | 175 | DROP TABLE c_star; 176 | 177 | DROP TABLE b_star; 178 | 179 | DROP TABLE a_star; 180 | 181 | 182 | -- 183 | -- must be in reverse inheritance order 184 | -- 185 | DROP TABLE stud_emp; 186 | 187 | DROP TABLE student; 188 | 189 | DROP TABLE slow_emp4000; 190 | 191 | DROP TABLE fast_emp4000; 192 | 193 | DROP TABLE emp; 194 | 195 | DROP TABLE person; 196 | 197 | 198 | DROP TABLE ramp; 199 | 200 | DROP TABLE real_city; 201 | 202 | DROP TABLE dept; 203 | 204 | DROP TABLE ihighway; 205 | 206 | DROP TABLE shighway; 207 | 208 | DROP TABLE road; 209 | 210 | DROP TABLE city; 211 | 212 | 213 | DROP TABLE hash_i4_heap; 214 | 215 | DROP TABLE hash_name_heap; 216 | 217 | DROP TABLE hash_txt_heap; 218 | 219 | DROP TABLE hash_f8_heap; 220 | 221 | -- DROP TABLE hash_ovfl_heap; 222 | 223 | DROP TABLE bt_i4_heap; 224 | 225 | DROP TABLE bt_name_heap; 226 | 227 | DROP TABLE bt_txt_heap; 228 | 229 | DROP TABLE bt_f8_heap; 230 | 231 | 232 | DROP TABLE ABSTIME_TBL; 233 | 234 | DROP TABLE RELTIME_TBL; 235 | 236 | DROP TABLE TINTERVAL_TBL; 237 | 238 | -- 239 | -- VIRTUAL CLASS REMOVAL 240 | -- (also tests removal of rewrite rules) 241 | -- 242 | DROP VIEW street; 243 | 244 | DROP VIEW iexit; 245 | 246 | DROP VIEW toyemp; 247 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/euc_cn.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/valgog/pg_sql_parser/3c6c30e7518026ca871d125223ac2e3ff837f2fd/plpgsql-ast/src/test/resources/sql_parse_test/euc_cn.sql -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/euc_jp.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/valgog/pg_sql_parser/3c6c30e7518026ca871d125223ac2e3ff837f2fd/plpgsql-ast/src/test/resources/sql_parse_test/euc_jp.sql -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/euc_kr.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/valgog/pg_sql_parser/3c6c30e7518026ca871d125223ac2e3ff837f2fd/plpgsql-ast/src/test/resources/sql_parse_test/euc_kr.sql -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/euc_tw.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/valgog/pg_sql_parser/3c6c30e7518026ca871d125223ac2e3ff837f2fd/plpgsql-ast/src/test/resources/sql_parse_test/euc_tw.sql -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/float4.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- FLOAT4 3 | -- 4 | 5 | CREATE TABLE FLOAT4_TBL (f1 float4); 6 | 7 | INSERT INTO FLOAT4_TBL(f1) VALUES (' 0.0'); 8 | INSERT INTO FLOAT4_TBL(f1) VALUES ('1004.30 '); 9 | INSERT INTO FLOAT4_TBL(f1) VALUES (' -34.84 '); 10 | INSERT INTO FLOAT4_TBL(f1) VALUES ('1.2345678901234e+20'); 11 | INSERT INTO FLOAT4_TBL(f1) VALUES ('1.2345678901234e-20'); 12 | 13 | -- test for over and under flow 14 | INSERT INTO FLOAT4_TBL(f1) VALUES ('10e70'); 15 | INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e70'); 16 | INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-70'); 17 | INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-70'); 18 | 19 | -- bad input 20 | INSERT INTO FLOAT4_TBL(f1) VALUES (''); 21 | INSERT INTO FLOAT4_TBL(f1) VALUES (' '); 22 | INSERT INTO FLOAT4_TBL(f1) VALUES ('xyz'); 23 | INSERT INTO FLOAT4_TBL(f1) VALUES ('5.0.0'); 24 | INSERT INTO FLOAT4_TBL(f1) VALUES ('5 . 0'); 25 | INSERT INTO FLOAT4_TBL(f1) VALUES ('5. 0'); 26 | INSERT INTO FLOAT4_TBL(f1) VALUES (' - 3.0'); 27 | INSERT INTO FLOAT4_TBL(f1) VALUES ('123 5'); 28 | 29 | -- special inputs 30 | SELECT 'NaN'::float4; 31 | SELECT 'nan'::float4; 32 | SELECT ' NAN '::float4; 33 | SELECT 'infinity'::float4; 34 | SELECT ' -INFINiTY '::float4; 35 | -- bad special inputs 36 | SELECT 'N A N'::float4; 37 | SELECT 'NaN x'::float4; 38 | SELECT ' INFINITY x'::float4; 39 | 40 | SELECT 'Infinity'::float4 + 100.0; 41 | SELECT 'Infinity'::float4 / 'Infinity'::float4; 42 | SELECT 'nan'::float4 / 'nan'::float4; 43 | SELECT 'nan'::numeric::float4; 44 | 45 | SELECT '' AS five, * FROM FLOAT4_TBL; 46 | 47 | SELECT '' AS four, f.* FROM FLOAT4_TBL f WHERE f.f1 <> '1004.3'; 48 | 49 | SELECT '' AS one, f.* FROM FLOAT4_TBL f WHERE f.f1 = '1004.3'; 50 | 51 | SELECT '' AS three, f.* FROM FLOAT4_TBL f WHERE '1004.3' > f.f1; 52 | 53 | SELECT '' AS three, f.* FROM FLOAT4_TBL f WHERE f.f1 < '1004.3'; 54 | 55 | SELECT '' AS four, f.* FROM FLOAT4_TBL f WHERE '1004.3' >= f.f1; 56 | 57 | SELECT '' AS four, f.* FROM FLOAT4_TBL f WHERE f.f1 <= '1004.3'; 58 | 59 | SELECT '' AS three, f.f1, f.f1 * '-10' AS x FROM FLOAT4_TBL f 60 | WHERE f.f1 > '0.0'; 61 | 62 | SELECT '' AS three, f.f1, f.f1 + '-10' AS x FROM FLOAT4_TBL f 63 | WHERE f.f1 > '0.0'; 64 | 65 | SELECT '' AS three, f.f1, f.f1 / '-10' AS x FROM FLOAT4_TBL f 66 | WHERE f.f1 > '0.0'; 67 | 68 | SELECT '' AS three, f.f1, f.f1 - '-10' AS x FROM FLOAT4_TBL f 69 | WHERE f.f1 > '0.0'; 70 | 71 | -- test divide by zero 72 | SELECT '' AS bad, f.f1 / '0.0' from FLOAT4_TBL f; 73 | 74 | SELECT '' AS five, * FROM FLOAT4_TBL; 75 | 76 | -- test the unary float4abs operator 77 | SELECT '' AS five, f.f1, @f.f1 AS abs_f1 FROM FLOAT4_TBL f; 78 | 79 | UPDATE FLOAT4_TBL 80 | SET f1 = FLOAT4_TBL.f1 * '-1' 81 | WHERE FLOAT4_TBL.f1 > '0.0'; 82 | 83 | SELECT '' AS five, * FROM FLOAT4_TBL; 84 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/float8.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- FLOAT8 3 | -- 4 | 5 | CREATE TABLE FLOAT8_TBL(f1 float8); 6 | 7 | INSERT INTO FLOAT8_TBL(f1) VALUES (' 0.0 '); 8 | INSERT INTO FLOAT8_TBL(f1) VALUES ('1004.30 '); 9 | INSERT INTO FLOAT8_TBL(f1) VALUES (' -34.84'); 10 | INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e+200'); 11 | INSERT INTO FLOAT8_TBL(f1) VALUES ('1.2345678901234e-200'); 12 | 13 | -- test for underflow and overflow handling 14 | SELECT '10e400'::float8; 15 | SELECT '-10e400'::float8; 16 | SELECT '10e-400'::float8; 17 | SELECT '-10e-400'::float8; 18 | 19 | -- bad input 20 | INSERT INTO FLOAT8_TBL(f1) VALUES (''); 21 | INSERT INTO FLOAT8_TBL(f1) VALUES (' '); 22 | INSERT INTO FLOAT8_TBL(f1) VALUES ('xyz'); 23 | INSERT INTO FLOAT8_TBL(f1) VALUES ('5.0.0'); 24 | INSERT INTO FLOAT8_TBL(f1) VALUES ('5 . 0'); 25 | INSERT INTO FLOAT8_TBL(f1) VALUES ('5. 0'); 26 | INSERT INTO FLOAT8_TBL(f1) VALUES (' - 3'); 27 | INSERT INTO FLOAT8_TBL(f1) VALUES ('123 5'); 28 | 29 | -- special inputs 30 | SELECT 'NaN'::float8; 31 | SELECT 'nan'::float8; 32 | SELECT ' NAN '::float8; 33 | SELECT 'infinity'::float8; 34 | SELECT ' -INFINiTY '::float8; 35 | -- bad special inputs 36 | SELECT 'N A N'::float8; 37 | SELECT 'NaN x'::float8; 38 | SELECT ' INFINITY x'::float8; 39 | 40 | SELECT 'Infinity'::float8 + 100.0; 41 | SELECT 'Infinity'::float8 / 'Infinity'::float8; 42 | SELECT 'nan'::float8 / 'nan'::float8; 43 | SELECT 'nan'::numeric::float8; 44 | 45 | SELECT '' AS five, * FROM FLOAT8_TBL; 46 | 47 | SELECT '' AS four, f.* FROM FLOAT8_TBL f WHERE f.f1 <> '1004.3'; 48 | 49 | SELECT '' AS one, f.* FROM FLOAT8_TBL f WHERE f.f1 = '1004.3'; 50 | 51 | SELECT '' AS three, f.* FROM FLOAT8_TBL f WHERE '1004.3' > f.f1; 52 | 53 | SELECT '' AS three, f.* FROM FLOAT8_TBL f WHERE f.f1 < '1004.3'; 54 | 55 | SELECT '' AS four, f.* FROM FLOAT8_TBL f WHERE '1004.3' >= f.f1; 56 | 57 | SELECT '' AS four, f.* FROM FLOAT8_TBL f WHERE f.f1 <= '1004.3'; 58 | 59 | SELECT '' AS three, f.f1, f.f1 * '-10' AS x 60 | FROM FLOAT8_TBL f 61 | WHERE f.f1 > '0.0'; 62 | 63 | SELECT '' AS three, f.f1, f.f1 + '-10' AS x 64 | FROM FLOAT8_TBL f 65 | WHERE f.f1 > '0.0'; 66 | 67 | SELECT '' AS three, f.f1, f.f1 / '-10' AS x 68 | FROM FLOAT8_TBL f 69 | WHERE f.f1 > '0.0'; 70 | 71 | SELECT '' AS three, f.f1, f.f1 - '-10' AS x 72 | FROM FLOAT8_TBL f 73 | WHERE f.f1 > '0.0'; 74 | 75 | SELECT '' AS one, f.f1 ^ '2.0' AS square_f1 76 | FROM FLOAT8_TBL f where f.f1 = '1004.3'; 77 | 78 | -- absolute value 79 | SELECT '' AS five, f.f1, @f.f1 AS abs_f1 80 | FROM FLOAT8_TBL f; 81 | 82 | -- truncate 83 | SELECT '' AS five, f.f1, trunc(f.f1) AS trunc_f1 84 | FROM FLOAT8_TBL f; 85 | 86 | -- round 87 | SELECT '' AS five, f.f1, round(f.f1) AS round_f1 88 | FROM FLOAT8_TBL f; 89 | 90 | -- ceil / ceiling 91 | select ceil(f1) as ceil_f1 from float8_tbl f; 92 | select ceiling(f1) as ceiling_f1 from float8_tbl f; 93 | 94 | -- floor 95 | select floor(f1) as floor_f1 from float8_tbl f; 96 | 97 | -- sign 98 | select sign(f1) as sign_f1 from float8_tbl f; 99 | 100 | -- square root 101 | SELECT sqrt(float8 '64') AS eight; 102 | 103 | SELECT |/ float8 '64' AS eight; 104 | 105 | SELECT '' AS three, f.f1, |/f.f1 AS sqrt_f1 106 | FROM FLOAT8_TBL f 107 | WHERE f.f1 > '0.0'; 108 | 109 | -- power 110 | SELECT power(float8 '144', float8 '0.5'); 111 | 112 | -- take exp of ln(f.f1) 113 | SELECT '' AS three, f.f1, exp(ln(f.f1)) AS exp_ln_f1 114 | FROM FLOAT8_TBL f 115 | WHERE f.f1 > '0.0'; 116 | 117 | -- cube root 118 | SELECT ||/ float8 '27' AS three; 119 | 120 | SELECT '' AS five, f.f1, ||/f.f1 AS cbrt_f1 FROM FLOAT8_TBL f; 121 | 122 | 123 | SELECT '' AS five, * FROM FLOAT8_TBL; 124 | 125 | UPDATE FLOAT8_TBL 126 | SET f1 = FLOAT8_TBL.f1 * '-1' 127 | WHERE FLOAT8_TBL.f1 > '0.0'; 128 | 129 | SELECT '' AS bad, f.f1 * '1e200' from FLOAT8_TBL f; 130 | 131 | SELECT '' AS bad, f.f1 ^ '1e200' from FLOAT8_TBL f; 132 | 133 | SELECT 0 ^ 0 + 0 ^ 1 + 0 ^ 0.0 + 0 ^ 0.5; 134 | 135 | SELECT '' AS bad, ln(f.f1) from FLOAT8_TBL f where f.f1 = '0.0' ; 136 | 137 | SELECT '' AS bad, ln(f.f1) from FLOAT8_TBL f where f.f1 < '0.0' ; 138 | 139 | SELECT '' AS bad, exp(f.f1) from FLOAT8_TBL f; 140 | 141 | SELECT '' AS bad, f.f1 / '0.0' from FLOAT8_TBL f; 142 | 143 | SELECT '' AS five, * FROM FLOAT8_TBL; 144 | 145 | -- test for over- and underflow 146 | INSERT INTO FLOAT8_TBL(f1) VALUES ('10e400'); 147 | 148 | INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e400'); 149 | 150 | INSERT INTO FLOAT8_TBL(f1) VALUES ('10e-400'); 151 | 152 | INSERT INTO FLOAT8_TBL(f1) VALUES ('-10e-400'); 153 | 154 | -- maintain external table consistency across platforms 155 | -- delete all values and reinsert well-behaved ones 156 | 157 | DELETE FROM FLOAT8_TBL; 158 | 159 | INSERT INTO FLOAT8_TBL(f1) VALUES ('0.0'); 160 | 161 | INSERT INTO FLOAT8_TBL(f1) VALUES ('-34.84'); 162 | 163 | INSERT INTO FLOAT8_TBL(f1) VALUES ('-1004.30'); 164 | 165 | INSERT INTO FLOAT8_TBL(f1) VALUES ('-1.2345678901234e+200'); 166 | 167 | INSERT INTO FLOAT8_TBL(f1) VALUES ('-1.2345678901234e-200'); 168 | 169 | SELECT '' AS five, * FROM FLOAT8_TBL; 170 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/geometry.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- GEOMETRY 3 | -- 4 | 5 | -- Back off displayed precision a little bit to reduce platform-to-platform 6 | -- variation in results. 7 | SET extra_float_digits TO -3; 8 | 9 | -- 10 | -- Points 11 | -- 12 | 13 | SELECT '' AS four, center(f1) AS center 14 | FROM BOX_TBL; 15 | 16 | SELECT '' AS four, (@@ f1) AS center 17 | FROM BOX_TBL; 18 | 19 | SELECT '' AS six, point(f1) AS center 20 | FROM CIRCLE_TBL; 21 | 22 | SELECT '' AS six, (@@ f1) AS center 23 | FROM CIRCLE_TBL; 24 | 25 | SELECT '' AS two, (@@ f1) AS center 26 | FROM POLYGON_TBL 27 | WHERE (# f1) > 2; 28 | 29 | -- "is horizontal" function 30 | SELECT '' AS two, p1.f1 31 | FROM POINT_TBL p1 32 | WHERE ishorizontal(p1.f1, point '(0,0)'); 33 | 34 | -- "is horizontal" operator 35 | SELECT '' AS two, p1.f1 36 | FROM POINT_TBL p1 37 | WHERE p1.f1 ?- point '(0,0)'; 38 | 39 | -- "is vertical" function 40 | SELECT '' AS one, p1.f1 41 | FROM POINT_TBL p1 42 | WHERE isvertical(p1.f1, point '(5.1,34.5)'); 43 | 44 | -- "is vertical" operator 45 | SELECT '' AS one, p1.f1 46 | FROM POINT_TBL p1 47 | WHERE p1.f1 ?| point '(5.1,34.5)'; 48 | 49 | -- 50 | -- Line segments 51 | -- 52 | 53 | -- intersection 54 | SELECT '' AS count, p.f1, l.s, l.s # p.f1 AS intersection 55 | FROM LSEG_TBL l, POINT_TBL p; 56 | 57 | -- closest point 58 | SELECT '' AS thirty, p.f1, l.s, p.f1 ## l.s AS closest 59 | FROM LSEG_TBL l, POINT_TBL p; 60 | 61 | -- 62 | -- Lines 63 | -- 64 | 65 | -- 66 | -- Boxes 67 | -- 68 | 69 | SELECT '' as six, box(f1) AS box FROM CIRCLE_TBL; 70 | 71 | -- translation 72 | SELECT '' AS twentyfour, b.f1 + p.f1 AS translation 73 | FROM BOX_TBL b, POINT_TBL p; 74 | 75 | SELECT '' AS twentyfour, b.f1 - p.f1 AS translation 76 | FROM BOX_TBL b, POINT_TBL p; 77 | 78 | -- scaling and rotation 79 | SELECT '' AS twentyfour, b.f1 * p.f1 AS rotation 80 | FROM BOX_TBL b, POINT_TBL p; 81 | 82 | SELECT '' AS twenty, b.f1 / p.f1 AS rotation 83 | FROM BOX_TBL b, POINT_TBL p 84 | WHERE (p.f1 <-> point '(0,0)') >= 1; 85 | 86 | -- 87 | -- Paths 88 | -- 89 | 90 | SELECT '' AS eight, npoints(f1) AS npoints, f1 AS path FROM PATH_TBL; 91 | 92 | SELECT '' AS four, path(f1) FROM POLYGON_TBL; 93 | 94 | -- translation 95 | SELECT '' AS eight, p1.f1 + point '(10,10)' AS dist_add 96 | FROM PATH_TBL p1; 97 | 98 | -- scaling and rotation 99 | SELECT '' AS eight, p1.f1 * point '(2,-1)' AS dist_mul 100 | FROM PATH_TBL p1; 101 | 102 | -- 103 | -- Polygons 104 | -- 105 | 106 | -- containment 107 | SELECT '' AS twentyfour, p.f1, poly.f1, poly.f1 @> p.f1 AS contains 108 | FROM POLYGON_TBL poly, POINT_TBL p; 109 | 110 | SELECT '' AS twentyfour, p.f1, poly.f1, p.f1 <@ poly.f1 AS contained 111 | FROM POLYGON_TBL poly, POINT_TBL p; 112 | 113 | SELECT '' AS four, npoints(f1) AS npoints, f1 AS polygon 114 | FROM POLYGON_TBL; 115 | 116 | SELECT '' AS four, polygon(f1) 117 | FROM BOX_TBL; 118 | 119 | SELECT '' AS four, polygon(f1) 120 | FROM PATH_TBL WHERE isclosed(f1); 121 | 122 | SELECT '' AS four, f1 AS open_path, polygon( pclose(f1)) AS polygon 123 | FROM PATH_TBL 124 | WHERE isopen(f1); 125 | 126 | -- convert circles to polygons using the default number of points 127 | SELECT '' AS six, polygon(f1) 128 | FROM CIRCLE_TBL; 129 | 130 | -- convert the circle to an 8-point polygon 131 | SELECT '' AS six, polygon(8, f1) 132 | FROM CIRCLE_TBL; 133 | 134 | -- 135 | -- Circles 136 | -- 137 | 138 | SELECT '' AS six, circle(f1, 50.0) 139 | FROM POINT_TBL; 140 | 141 | SELECT '' AS four, circle(f1) 142 | FROM BOX_TBL; 143 | 144 | SELECT '' AS two, circle(f1) 145 | FROM POLYGON_TBL 146 | WHERE (# f1) >= 3; 147 | 148 | SELECT '' AS twentyfour, c1.f1 AS circle, p1.f1 AS point, (p1.f1 <-> c1.f1) AS distance 149 | FROM CIRCLE_TBL c1, POINT_TBL p1 150 | WHERE (p1.f1 <-> c1.f1) > 0 151 | ORDER BY distance, area(c1.f1), p1.f1[0]; 152 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/hash_index.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- HASH_INDEX 3 | -- grep 843938989 hash.data 4 | -- 5 | 6 | SELECT * FROM hash_i4_heap 7 | WHERE hash_i4_heap.random = 843938989; 8 | 9 | -- 10 | -- hash index 11 | -- grep 66766766 hash.data 12 | -- 13 | SELECT * FROM hash_i4_heap 14 | WHERE hash_i4_heap.random = 66766766; 15 | 16 | -- 17 | -- hash index 18 | -- grep 1505703298 hash.data 19 | -- 20 | SELECT * FROM hash_name_heap 21 | WHERE hash_name_heap.random = '1505703298'::name; 22 | 23 | -- 24 | -- hash index 25 | -- grep 7777777 hash.data 26 | -- 27 | SELECT * FROM hash_name_heap 28 | WHERE hash_name_heap.random = '7777777'::name; 29 | 30 | -- 31 | -- hash index 32 | -- grep 1351610853 hash.data 33 | -- 34 | SELECT * FROM hash_txt_heap 35 | WHERE hash_txt_heap.random = '1351610853'::text; 36 | 37 | -- 38 | -- hash index 39 | -- grep 111111112222222233333333 hash.data 40 | -- 41 | SELECT * FROM hash_txt_heap 42 | WHERE hash_txt_heap.random = '111111112222222233333333'::text; 43 | 44 | -- 45 | -- hash index 46 | -- grep 444705537 hash.data 47 | -- 48 | SELECT * FROM hash_f8_heap 49 | WHERE hash_f8_heap.random = '444705537'::float8; 50 | 51 | -- 52 | -- hash index 53 | -- grep 88888888 hash.data 54 | -- 55 | SELECT * FROM hash_f8_heap 56 | WHERE hash_f8_heap.random = '88888888'::float8; 57 | 58 | -- 59 | -- hash index 60 | -- grep '^90[^0-9]' hashovfl.data 61 | -- 62 | -- SELECT count(*) AS i988 FROM hash_ovfl_heap 63 | -- WHERE x = 90; 64 | 65 | -- 66 | -- hash index 67 | -- grep '^1000[^0-9]' hashovfl.data 68 | -- 69 | -- SELECT count(*) AS i0 FROM hash_ovfl_heap 70 | -- WHERE x = 1000; 71 | 72 | -- 73 | -- HASH 74 | -- 75 | UPDATE hash_i4_heap 76 | SET random = 1 77 | WHERE hash_i4_heap.seqno = 1492; 78 | 79 | SELECT h.seqno AS i1492, h.random AS i1 80 | FROM hash_i4_heap h 81 | WHERE h.random = 1; 82 | 83 | UPDATE hash_i4_heap 84 | SET seqno = 20000 85 | WHERE hash_i4_heap.random = 1492795354; 86 | 87 | SELECT h.seqno AS i20000 88 | FROM hash_i4_heap h 89 | WHERE h.random = 1492795354; 90 | 91 | UPDATE hash_name_heap 92 | SET random = '0123456789abcdef'::name 93 | WHERE hash_name_heap.seqno = 6543; 94 | 95 | SELECT h.seqno AS i6543, h.random AS c0_to_f 96 | FROM hash_name_heap h 97 | WHERE h.random = '0123456789abcdef'::name; 98 | 99 | UPDATE hash_name_heap 100 | SET seqno = 20000 101 | WHERE hash_name_heap.random = '76652222'::name; 102 | 103 | -- 104 | -- this is the row we just replaced; index scan should return zero rows 105 | -- 106 | SELECT h.seqno AS emptyset 107 | FROM hash_name_heap h 108 | WHERE h.random = '76652222'::name; 109 | 110 | UPDATE hash_txt_heap 111 | SET random = '0123456789abcdefghijklmnop'::text 112 | WHERE hash_txt_heap.seqno = 4002; 113 | 114 | SELECT h.seqno AS i4002, h.random AS c0_to_p 115 | FROM hash_txt_heap h 116 | WHERE h.random = '0123456789abcdefghijklmnop'::text; 117 | 118 | UPDATE hash_txt_heap 119 | SET seqno = 20000 120 | WHERE hash_txt_heap.random = '959363399'::text; 121 | 122 | SELECT h.seqno AS t20000 123 | FROM hash_txt_heap h 124 | WHERE h.random = '959363399'::text; 125 | 126 | UPDATE hash_f8_heap 127 | SET random = '-1234.1234'::float8 128 | WHERE hash_f8_heap.seqno = 8906; 129 | 130 | SELECT h.seqno AS i8096, h.random AS f1234_1234 131 | FROM hash_f8_heap h 132 | WHERE h.random = '-1234.1234'::float8; 133 | 134 | UPDATE hash_f8_heap 135 | SET seqno = 20000 136 | WHERE hash_f8_heap.random = '488912369'::float8; 137 | 138 | SELECT h.seqno AS f20000 139 | FROM hash_f8_heap h 140 | WHERE h.random = '488912369'::float8; 141 | 142 | -- UPDATE hash_ovfl_heap 143 | -- SET x = 1000 144 | -- WHERE x = 90; 145 | 146 | -- this vacuums the index as well 147 | -- VACUUM hash_ovfl_heap; 148 | 149 | -- SELECT count(*) AS i0 FROM hash_ovfl_heap 150 | -- WHERE x = 90; 151 | 152 | -- SELECT count(*) AS i988 FROM hash_ovfl_heap 153 | -- WHERE x = 1000; 154 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/hs_primary_extremes.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- Hot Standby tests 3 | -- 4 | -- hs_primary_extremes.sql 5 | -- 6 | 7 | drop table if exists hs_extreme; 8 | create table hs_extreme (col1 integer); 9 | 10 | CREATE OR REPLACE FUNCTION hs_subxids (n integer) 11 | RETURNS void 12 | LANGUAGE plpgsql 13 | AS $$ 14 | BEGIN 15 | IF n <= 0 THEN RETURN; END IF; 16 | INSERT INTO hs_extreme VALUES (n); 17 | PERFORM hs_subxids(n - 1); 18 | RETURN; 19 | EXCEPTION WHEN raise_exception THEN NULL; END; 20 | $$; 21 | 22 | BEGIN; 23 | SELECT hs_subxids(257); 24 | ROLLBACK; 25 | BEGIN; 26 | SELECT hs_subxids(257); 27 | COMMIT; 28 | 29 | set client_min_messages = 'warning'; 30 | 31 | CREATE OR REPLACE FUNCTION hs_locks_create (n integer) 32 | RETURNS void 33 | LANGUAGE plpgsql 34 | AS $$ 35 | BEGIN 36 | IF n <= 0 THEN 37 | CHECKPOINT; 38 | RETURN; 39 | END IF; 40 | EXECUTE 'CREATE TABLE hs_locks_' || n::text || ' ()'; 41 | PERFORM hs_locks_create(n - 1); 42 | RETURN; 43 | EXCEPTION WHEN raise_exception THEN NULL; END; 44 | $$; 45 | 46 | CREATE OR REPLACE FUNCTION hs_locks_drop (n integer) 47 | RETURNS void 48 | LANGUAGE plpgsql 49 | AS $$ 50 | BEGIN 51 | IF n <= 0 THEN 52 | CHECKPOINT; 53 | RETURN; 54 | END IF; 55 | EXECUTE 'DROP TABLE IF EXISTS hs_locks_' || n::text; 56 | PERFORM hs_locks_drop(n - 1); 57 | RETURN; 58 | EXCEPTION WHEN raise_exception THEN NULL; END; 59 | $$; 60 | 61 | BEGIN; 62 | SELECT hs_locks_drop(257); 63 | SELECT hs_locks_create(257); 64 | SELECT count(*) > 257 FROM pg_locks; 65 | ROLLBACK; 66 | BEGIN; 67 | SELECT hs_locks_drop(257); 68 | SELECT hs_locks_create(257); 69 | SELECT count(*) > 257 FROM pg_locks; 70 | COMMIT; 71 | SELECT hs_locks_drop(257); 72 | 73 | SELECT pg_switch_xlog(); 74 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/hs_primary_setup.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- Hot Standby tests 3 | -- 4 | -- hs_primary_setup.sql 5 | -- 6 | 7 | drop table if exists hs1; 8 | create table hs1 (col1 integer primary key); 9 | insert into hs1 values (1); 10 | 11 | drop table if exists hs2; 12 | create table hs2 (col1 integer primary key); 13 | insert into hs2 values (12); 14 | insert into hs2 values (13); 15 | 16 | drop table if exists hs3; 17 | create table hs3 (col1 integer primary key); 18 | insert into hs3 values (113); 19 | insert into hs3 values (114); 20 | insert into hs3 values (115); 21 | 22 | DROP sequence if exists hsseq; 23 | create sequence hsseq; 24 | 25 | SELECT pg_switch_xlog(); 26 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/hs_standby_allowed.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- Hot Standby tests 3 | -- 4 | -- hs_standby_allowed.sql 5 | -- 6 | 7 | -- SELECT 8 | 9 | select count(*) as should_be_1 from hs1; 10 | 11 | select count(*) as should_be_2 from hs2; 12 | 13 | select count(*) as should_be_3 from hs3; 14 | 15 | COPY hs1 TO '/tmp/copy_test'; 16 | \! cat /tmp/copy_test 17 | 18 | -- Access sequence directly 19 | select min_value as sequence_min_value from hsseq; 20 | 21 | -- Transactions 22 | 23 | begin; 24 | select count(*) as should_be_1 from hs1; 25 | end; 26 | 27 | begin transaction read only; 28 | select count(*) as should_be_1 from hs1; 29 | end; 30 | 31 | begin transaction isolation level serializable; 32 | select count(*) as should_be_1 from hs1; 33 | select count(*) as should_be_1 from hs1; 34 | select count(*) as should_be_1 from hs1; 35 | commit; 36 | 37 | begin; 38 | select count(*) as should_be_1 from hs1; 39 | commit; 40 | 41 | begin; 42 | select count(*) as should_be_1 from hs1; 43 | abort; 44 | 45 | start transaction; 46 | select count(*) as should_be_1 from hs1; 47 | commit; 48 | 49 | begin; 50 | select count(*) as should_be_1 from hs1; 51 | rollback; 52 | 53 | begin; 54 | select count(*) as should_be_1 from hs1; 55 | savepoint s; 56 | select count(*) as should_be_2 from hs2; 57 | commit; 58 | 59 | begin; 60 | select count(*) as should_be_1 from hs1; 61 | savepoint s; 62 | select count(*) as should_be_2 from hs2; 63 | release savepoint s; 64 | select count(*) as should_be_2 from hs2; 65 | savepoint s; 66 | select count(*) as should_be_3 from hs3; 67 | rollback to savepoint s; 68 | select count(*) as should_be_2 from hs2; 69 | commit; 70 | 71 | -- SET parameters 72 | 73 | -- has no effect on read only transactions, but we can still set it 74 | set synchronous_commit = on; 75 | show synchronous_commit; 76 | reset synchronous_commit; 77 | 78 | discard temp; 79 | discard all; 80 | 81 | -- CURSOR commands 82 | 83 | BEGIN; 84 | 85 | DECLARE hsc CURSOR FOR select * from hs3; 86 | 87 | FETCH next from hsc; 88 | fetch first from hsc; 89 | fetch last from hsc; 90 | fetch 1 from hsc; 91 | 92 | CLOSE hsc; 93 | 94 | COMMIT; 95 | 96 | -- Prepared plans 97 | 98 | PREPARE hsp AS select count(*) from hs1; 99 | PREPARE hsp_noexec (integer) AS insert into hs1 values ($1); 100 | 101 | EXECUTE hsp; 102 | 103 | DEALLOCATE hsp; 104 | 105 | -- LOCK 106 | 107 | BEGIN; 108 | LOCK hs1 IN ACCESS SHARE MODE; 109 | LOCK hs1 IN ROW SHARE MODE; 110 | LOCK hs1 IN ROW EXCLUSIVE MODE; 111 | COMMIT; 112 | 113 | -- LOAD 114 | -- should work, easier if there is no test for that... 115 | 116 | 117 | -- ALLOWED COMMANDS 118 | 119 | CHECKPOINT; 120 | 121 | discard all; 122 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/hs_standby_check.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- Hot Standby tests 3 | -- 4 | -- hs_standby_check.sql 5 | -- 6 | 7 | -- 8 | -- If the query below returns false then all other tests will fail after it. 9 | -- 10 | select case pg_is_in_recovery() when false then 11 | 'These tests are intended only for execution on a standby server that is reading ' || 12 | 'WAL from a server upon which the regression database is already created and into ' || 13 | 'which src/test/regress/sql/hs_primary_setup.sql has been run' 14 | else 15 | 'Tests are running on a standby server during recovery' 16 | end; 17 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/hs_standby_disallowed.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- Hot Standby tests 3 | -- 4 | -- hs_standby_disallowed.sql 5 | -- 6 | 7 | SET transaction_read_only = off; 8 | 9 | begin transaction read write; 10 | commit; 11 | 12 | -- SELECT 13 | 14 | select * from hs1 FOR SHARE; 15 | select * from hs1 FOR UPDATE; 16 | 17 | -- DML 18 | BEGIN; 19 | insert into hs1 values (37); 20 | ROLLBACK; 21 | BEGIN; 22 | delete from hs1 where col1 = 1; 23 | ROLLBACK; 24 | BEGIN; 25 | update hs1 set col1 = NULL where col1 > 0; 26 | ROLLBACK; 27 | BEGIN; 28 | truncate hs3; 29 | ROLLBACK; 30 | 31 | -- DDL 32 | 33 | create temporary table hstemp1 (col1 integer); 34 | BEGIN; 35 | drop table hs2; 36 | ROLLBACK; 37 | BEGIN; 38 | create table hs4 (col1 integer); 39 | ROLLBACK; 40 | 41 | -- Sequences 42 | 43 | SELECT nextval('hsseq'); 44 | 45 | -- Two-phase commit transaction stuff 46 | 47 | BEGIN; 48 | SELECT count(*) FROM hs1; 49 | PREPARE TRANSACTION 'foobar'; 50 | ROLLBACK; 51 | BEGIN; 52 | SELECT count(*) FROM hs1; 53 | COMMIT PREPARED 'foobar'; 54 | ROLLBACK; 55 | 56 | BEGIN; 57 | SELECT count(*) FROM hs1; 58 | PREPARE TRANSACTION 'foobar'; 59 | ROLLBACK PREPARED 'foobar'; 60 | ROLLBACK; 61 | 62 | BEGIN; 63 | SELECT count(*) FROM hs1; 64 | ROLLBACK PREPARED 'foobar'; 65 | ROLLBACK; 66 | 67 | 68 | -- Locks 69 | BEGIN; 70 | LOCK hs1; 71 | COMMIT; 72 | BEGIN; 73 | LOCK hs1 IN SHARE UPDATE EXCLUSIVE MODE; 74 | COMMIT; 75 | BEGIN; 76 | LOCK hs1 IN SHARE MODE; 77 | COMMIT; 78 | BEGIN; 79 | LOCK hs1 IN SHARE ROW EXCLUSIVE MODE; 80 | COMMIT; 81 | BEGIN; 82 | LOCK hs1 IN EXCLUSIVE MODE; 83 | COMMIT; 84 | BEGIN; 85 | LOCK hs1 IN ACCESS EXCLUSIVE MODE; 86 | COMMIT; 87 | 88 | -- Listen 89 | listen a; 90 | notify a; 91 | unlisten a; 92 | unlisten *; 93 | 94 | -- disallowed commands 95 | 96 | ANALYZE hs1; 97 | 98 | VACUUM hs2; 99 | 100 | CLUSTER hs2 using hs1_pkey; 101 | 102 | REINDEX TABLE hs2; 103 | 104 | REVOKE SELECT ON hs1 FROM PUBLIC; 105 | GRANT SELECT ON hs1 TO PUBLIC; 106 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/hs_standby_functions.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- Hot Standby tests 3 | -- 4 | -- hs_standby_functions.sql 5 | -- 6 | 7 | -- should fail 8 | select txid_current(); 9 | 10 | select length(txid_current_snapshot()::text) >= 4; 11 | 12 | select pg_start_backup('should fail'); 13 | select pg_switch_xlog(); 14 | select pg_stop_backup(); 15 | 16 | -- should return no rows 17 | select * from pg_prepared_xacts; 18 | 19 | -- just the startup process 20 | select locktype, virtualxid, virtualtransaction, mode, granted 21 | from pg_locks where virtualxid = '1/1'; 22 | 23 | -- suicide is painless 24 | select pg_cancel_backend(pg_backend_pid()); 25 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/inet.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- INET 3 | -- 4 | 5 | -- prepare the table... 6 | 7 | DROP TABLE INET_TBL; 8 | CREATE TABLE INET_TBL (c cidr, i inet); 9 | INSERT INTO INET_TBL (c, i) VALUES ('192.168.1', '192.168.1.226/24'); 10 | INSERT INTO INET_TBL (c, i) VALUES ('192.168.1.0/26', '192.168.1.226'); 11 | INSERT INTO INET_TBL (c, i) VALUES ('192.168.1', '192.168.1.0/24'); 12 | INSERT INTO INET_TBL (c, i) VALUES ('192.168.1', '192.168.1.0/25'); 13 | INSERT INTO INET_TBL (c, i) VALUES ('192.168.1', '192.168.1.255/24'); 14 | INSERT INTO INET_TBL (c, i) VALUES ('192.168.1', '192.168.1.255/25'); 15 | INSERT INTO INET_TBL (c, i) VALUES ('10', '10.1.2.3/8'); 16 | INSERT INTO INET_TBL (c, i) VALUES ('10.0.0.0', '10.1.2.3/8'); 17 | INSERT INTO INET_TBL (c, i) VALUES ('10.1.2.3', '10.1.2.3/32'); 18 | INSERT INTO INET_TBL (c, i) VALUES ('10.1.2', '10.1.2.3/24'); 19 | INSERT INTO INET_TBL (c, i) VALUES ('10.1', '10.1.2.3/16'); 20 | INSERT INTO INET_TBL (c, i) VALUES ('10', '10.1.2.3/8'); 21 | INSERT INTO INET_TBL (c, i) VALUES ('10', '11.1.2.3/8'); 22 | INSERT INTO INET_TBL (c, i) VALUES ('10', '9.1.2.3/8'); 23 | INSERT INTO INET_TBL (c, i) VALUES ('10:23::f1', '10:23::f1/64'); 24 | INSERT INTO INET_TBL (c, i) VALUES ('10:23::8000/113', '10:23::ffff'); 25 | INSERT INTO INET_TBL (c, i) VALUES ('::ffff:1.2.3.4', '::4.3.2.1/24'); 26 | -- check that CIDR rejects invalid input: 27 | INSERT INTO INET_TBL (c, i) VALUES ('192.168.1.2/30', '192.168.1.226'); 28 | INSERT INTO INET_TBL (c, i) VALUES ('1234::1234::1234', '::1.2.3.4'); 29 | -- check that CIDR rejects invalid input when converting from text: 30 | INSERT INTO INET_TBL (c, i) VALUES (cidr('192.168.1.2/30'), '192.168.1.226'); 31 | INSERT INTO INET_TBL (c, i) VALUES (cidr('ffff:ffff:ffff:ffff::/24'), '::192.168.1.226'); 32 | SELECT '' AS ten, c AS cidr, i AS inet FROM INET_TBL; 33 | 34 | -- now test some support functions 35 | 36 | SELECT '' AS ten, i AS inet, host(i), text(i), family(i) FROM INET_TBL; 37 | SELECT '' AS ten, c AS cidr, broadcast(c), 38 | i AS inet, broadcast(i) FROM INET_TBL; 39 | SELECT '' AS ten, c AS cidr, network(c) AS "network(cidr)", 40 | i AS inet, network(i) AS "network(inet)" FROM INET_TBL; 41 | SELECT '' AS ten, c AS cidr, masklen(c) AS "masklen(cidr)", 42 | i AS inet, masklen(i) AS "masklen(inet)" FROM INET_TBL; 43 | 44 | SELECT '' AS four, c AS cidr, masklen(c) AS "masklen(cidr)", 45 | i AS inet, masklen(i) AS "masklen(inet)" FROM INET_TBL 46 | WHERE masklen(c) <= 8; 47 | 48 | SELECT '' AS six, c AS cidr, i AS inet FROM INET_TBL 49 | WHERE c = i; 50 | 51 | SELECT '' AS ten, i, c, 52 | i < c AS lt, i <= c AS le, i = c AS eq, 53 | i >= c AS ge, i > c AS gt, i <> c AS ne, 54 | i << c AS sb, i <<= c AS sbe, 55 | i >> c AS sup, i >>= c AS spe 56 | FROM INET_TBL; 57 | 58 | -- check the conversion to/from text and set_netmask 59 | SELECT '' AS ten, set_masklen(inet(text(i)), 24) FROM INET_TBL; 60 | -- check that index works correctly 61 | CREATE INDEX inet_idx1 ON inet_tbl(i); 62 | SET enable_seqscan TO off; 63 | SELECT * FROM inet_tbl WHERE i<<'192.168.1.0/24'::cidr; 64 | SELECT * FROM inet_tbl WHERE i<<='192.168.1.0/24'::cidr; 65 | SET enable_seqscan TO on; 66 | DROP INDEX inet_idx1; 67 | 68 | -- simple tests of inet boolean and arithmetic operators 69 | SELECT i, ~i AS "~i" FROM inet_tbl; 70 | SELECT i, c, i & c AS "and" FROM inet_tbl; 71 | SELECT i, c, i | c AS "or" FROM inet_tbl; 72 | SELECT i, i + 500 AS "i+500" FROM inet_tbl; 73 | SELECT i, i - 500 AS "i-500" FROM inet_tbl; 74 | SELECT i, c, i - c AS "minus" FROM inet_tbl; 75 | SELECT '127.0.0.1'::inet + 257; 76 | SELECT ('127.0.0.1'::inet + 257) - 257; 77 | SELECT '127::1'::inet + 257; 78 | SELECT ('127::1'::inet + 257) - 257; 79 | SELECT '127.0.0.2'::inet - ('127.0.0.2'::inet + 500); 80 | SELECT '127.0.0.2'::inet - ('127.0.0.2'::inet - 500); 81 | SELECT '127::2'::inet - ('127::2'::inet + 500); 82 | SELECT '127::2'::inet - ('127::2'::inet - 500); 83 | -- these should give overflow errors: 84 | SELECT '127.0.0.1'::inet + 10000000000; 85 | SELECT '127.0.0.1'::inet - 10000000000; 86 | SELECT '126::1'::inet - '127::2'::inet; 87 | SELECT '127::1'::inet - '126::2'::inet; 88 | -- but not these 89 | SELECT '127::1'::inet + 10000000000; 90 | SELECT '127::1'::inet - '127::2'::inet; 91 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/insert.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- insert with DEFAULT in the target_list 3 | -- 4 | create table inserttest (col1 int4, col2 int4 NOT NULL, col3 text default 'testing'); 5 | insert into inserttest (col1, col2, col3) values (DEFAULT, DEFAULT, DEFAULT); 6 | insert into inserttest (col2, col3) values (3, DEFAULT); 7 | insert into inserttest (col1, col2, col3) values (DEFAULT, 5, DEFAULT); 8 | insert into inserttest values (DEFAULT, 5, 'test'); 9 | insert into inserttest values (DEFAULT, 7); 10 | 11 | select * from inserttest; 12 | 13 | -- 14 | -- insert with similar expression / target_list values (all fail) 15 | -- 16 | insert into inserttest (col1, col2, col3) values (DEFAULT, DEFAULT); 17 | insert into inserttest (col1, col2, col3) values (1, 2); 18 | insert into inserttest (col1) values (1, 2); 19 | insert into inserttest (col1) values (DEFAULT, DEFAULT); 20 | 21 | select * from inserttest; 22 | 23 | -- 24 | -- VALUES test 25 | -- 26 | insert into inserttest values(10, 20, '40'), (-1, 2, DEFAULT), 27 | ((select 2), (select i from (values(3)) as foo (i)), 'values are fun!'); 28 | 29 | select * from inserttest; 30 | 31 | -- 32 | -- TOASTed value test 33 | -- 34 | insert into inserttest values(30, 50, repeat('x', 10000)); 35 | 36 | select col1, col2, char_length(col3) from inserttest; 37 | 38 | drop table inserttest; 39 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/int2.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- INT2 3 | -- 4 | 5 | CREATE TABLE INT2_TBL(f1 int2); 6 | 7 | INSERT INTO INT2_TBL(f1) VALUES ('0 '); 8 | 9 | INSERT INTO INT2_TBL(f1) VALUES (' 1234 '); 10 | 11 | INSERT INTO INT2_TBL(f1) VALUES (' -1234'); 12 | 13 | INSERT INTO INT2_TBL(f1) VALUES ('34.5'); 14 | 15 | -- largest and smallest values 16 | INSERT INTO INT2_TBL(f1) VALUES ('32767'); 17 | 18 | INSERT INTO INT2_TBL(f1) VALUES ('-32767'); 19 | 20 | -- bad input values -- should give errors 21 | INSERT INTO INT2_TBL(f1) VALUES ('100000'); 22 | INSERT INTO INT2_TBL(f1) VALUES ('asdf'); 23 | INSERT INTO INT2_TBL(f1) VALUES (' '); 24 | INSERT INTO INT2_TBL(f1) VALUES ('- 1234'); 25 | INSERT INTO INT2_TBL(f1) VALUES ('4 444'); 26 | INSERT INTO INT2_TBL(f1) VALUES ('123 dt'); 27 | INSERT INTO INT2_TBL(f1) VALUES (''); 28 | 29 | 30 | SELECT '' AS five, * FROM INT2_TBL; 31 | 32 | SELECT '' AS four, i.* FROM INT2_TBL i WHERE i.f1 <> int2 '0'; 33 | 34 | SELECT '' AS four, i.* FROM INT2_TBL i WHERE i.f1 <> int4 '0'; 35 | 36 | SELECT '' AS one, i.* FROM INT2_TBL i WHERE i.f1 = int2 '0'; 37 | 38 | SELECT '' AS one, i.* FROM INT2_TBL i WHERE i.f1 = int4 '0'; 39 | 40 | SELECT '' AS two, i.* FROM INT2_TBL i WHERE i.f1 < int2 '0'; 41 | 42 | SELECT '' AS two, i.* FROM INT2_TBL i WHERE i.f1 < int4 '0'; 43 | 44 | SELECT '' AS three, i.* FROM INT2_TBL i WHERE i.f1 <= int2 '0'; 45 | 46 | SELECT '' AS three, i.* FROM INT2_TBL i WHERE i.f1 <= int4 '0'; 47 | 48 | SELECT '' AS two, i.* FROM INT2_TBL i WHERE i.f1 > int2 '0'; 49 | 50 | SELECT '' AS two, i.* FROM INT2_TBL i WHERE i.f1 > int4 '0'; 51 | 52 | SELECT '' AS three, i.* FROM INT2_TBL i WHERE i.f1 >= int2 '0'; 53 | 54 | SELECT '' AS three, i.* FROM INT2_TBL i WHERE i.f1 >= int4 '0'; 55 | 56 | -- positive odds 57 | SELECT '' AS one, i.* FROM INT2_TBL i WHERE (i.f1 % int2 '2') = int2 '1'; 58 | 59 | -- any evens 60 | SELECT '' AS three, i.* FROM INT2_TBL i WHERE (i.f1 % int4 '2') = int2 '0'; 61 | 62 | SELECT '' AS five, i.f1, i.f1 * int2 '2' AS x FROM INT2_TBL i; 63 | 64 | SELECT '' AS five, i.f1, i.f1 * int2 '2' AS x FROM INT2_TBL i 65 | WHERE abs(f1) < 16384; 66 | 67 | SELECT '' AS five, i.f1, i.f1 * int4 '2' AS x FROM INT2_TBL i; 68 | 69 | SELECT '' AS five, i.f1, i.f1 + int2 '2' AS x FROM INT2_TBL i; 70 | 71 | SELECT '' AS five, i.f1, i.f1 + int2 '2' AS x FROM INT2_TBL i 72 | WHERE f1 < 32766; 73 | 74 | SELECT '' AS five, i.f1, i.f1 + int4 '2' AS x FROM INT2_TBL i; 75 | 76 | SELECT '' AS five, i.f1, i.f1 - int2 '2' AS x FROM INT2_TBL i; 77 | 78 | SELECT '' AS five, i.f1, i.f1 - int2 '2' AS x FROM INT2_TBL i 79 | WHERE f1 > -32767; 80 | 81 | SELECT '' AS five, i.f1, i.f1 - int4 '2' AS x FROM INT2_TBL i; 82 | 83 | SELECT '' AS five, i.f1, i.f1 / int2 '2' AS x FROM INT2_TBL i; 84 | 85 | SELECT '' AS five, i.f1, i.f1 / int4 '2' AS x FROM INT2_TBL i; 86 | 87 | -- corner cases 88 | SELECT (-1::int2<<15)::text; 89 | SELECT ((-1::int2<<15)+1::int2)::text; 90 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/int4.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- INT4 3 | -- 4 | 5 | CREATE TABLE INT4_TBL(f1 int4); 6 | 7 | INSERT INTO INT4_TBL(f1) VALUES (' 0 '); 8 | 9 | INSERT INTO INT4_TBL(f1) VALUES ('123456 '); 10 | 11 | INSERT INTO INT4_TBL(f1) VALUES (' -123456'); 12 | 13 | INSERT INTO INT4_TBL(f1) VALUES ('34.5'); 14 | 15 | -- largest and smallest values 16 | INSERT INTO INT4_TBL(f1) VALUES ('2147483647'); 17 | 18 | INSERT INTO INT4_TBL(f1) VALUES ('-2147483647'); 19 | 20 | -- bad input values -- should give errors 21 | INSERT INTO INT4_TBL(f1) VALUES ('1000000000000'); 22 | INSERT INTO INT4_TBL(f1) VALUES ('asdf'); 23 | INSERT INTO INT4_TBL(f1) VALUES (' '); 24 | INSERT INTO INT4_TBL(f1) VALUES (' asdf '); 25 | INSERT INTO INT4_TBL(f1) VALUES ('- 1234'); 26 | INSERT INTO INT4_TBL(f1) VALUES ('123 5'); 27 | INSERT INTO INT4_TBL(f1) VALUES (''); 28 | 29 | 30 | SELECT '' AS five, * FROM INT4_TBL; 31 | 32 | SELECT '' AS four, i.* FROM INT4_TBL i WHERE i.f1 <> int2 '0'; 33 | 34 | SELECT '' AS four, i.* FROM INT4_TBL i WHERE i.f1 <> int4 '0'; 35 | 36 | SELECT '' AS one, i.* FROM INT4_TBL i WHERE i.f1 = int2 '0'; 37 | 38 | SELECT '' AS one, i.* FROM INT4_TBL i WHERE i.f1 = int4 '0'; 39 | 40 | SELECT '' AS two, i.* FROM INT4_TBL i WHERE i.f1 < int2 '0'; 41 | 42 | SELECT '' AS two, i.* FROM INT4_TBL i WHERE i.f1 < int4 '0'; 43 | 44 | SELECT '' AS three, i.* FROM INT4_TBL i WHERE i.f1 <= int2 '0'; 45 | 46 | SELECT '' AS three, i.* FROM INT4_TBL i WHERE i.f1 <= int4 '0'; 47 | 48 | SELECT '' AS two, i.* FROM INT4_TBL i WHERE i.f1 > int2 '0'; 49 | 50 | SELECT '' AS two, i.* FROM INT4_TBL i WHERE i.f1 > int4 '0'; 51 | 52 | SELECT '' AS three, i.* FROM INT4_TBL i WHERE i.f1 >= int2 '0'; 53 | 54 | SELECT '' AS three, i.* FROM INT4_TBL i WHERE i.f1 >= int4 '0'; 55 | 56 | -- positive odds 57 | SELECT '' AS one, i.* FROM INT4_TBL i WHERE (i.f1 % int2 '2') = int2 '1'; 58 | 59 | -- any evens 60 | SELECT '' AS three, i.* FROM INT4_TBL i WHERE (i.f1 % int4 '2') = int2 '0'; 61 | 62 | SELECT '' AS five, i.f1, i.f1 * int2 '2' AS x FROM INT4_TBL i; 63 | 64 | SELECT '' AS five, i.f1, i.f1 * int2 '2' AS x FROM INT4_TBL i 65 | WHERE abs(f1) < 1073741824; 66 | 67 | SELECT '' AS five, i.f1, i.f1 * int4 '2' AS x FROM INT4_TBL i; 68 | 69 | SELECT '' AS five, i.f1, i.f1 * int4 '2' AS x FROM INT4_TBL i 70 | WHERE abs(f1) < 1073741824; 71 | 72 | SELECT '' AS five, i.f1, i.f1 + int2 '2' AS x FROM INT4_TBL i; 73 | 74 | SELECT '' AS five, i.f1, i.f1 + int2 '2' AS x FROM INT4_TBL i 75 | WHERE f1 < 2147483646; 76 | 77 | SELECT '' AS five, i.f1, i.f1 + int4 '2' AS x FROM INT4_TBL i; 78 | 79 | SELECT '' AS five, i.f1, i.f1 + int4 '2' AS x FROM INT4_TBL i 80 | WHERE f1 < 2147483646; 81 | 82 | SELECT '' AS five, i.f1, i.f1 - int2 '2' AS x FROM INT4_TBL i; 83 | 84 | SELECT '' AS five, i.f1, i.f1 - int2 '2' AS x FROM INT4_TBL i 85 | WHERE f1 > -2147483647; 86 | 87 | SELECT '' AS five, i.f1, i.f1 - int4 '2' AS x FROM INT4_TBL i; 88 | 89 | SELECT '' AS five, i.f1, i.f1 - int4 '2' AS x FROM INT4_TBL i 90 | WHERE f1 > -2147483647; 91 | 92 | SELECT '' AS five, i.f1, i.f1 / int2 '2' AS x FROM INT4_TBL i; 93 | 94 | SELECT '' AS five, i.f1, i.f1 / int4 '2' AS x FROM INT4_TBL i; 95 | 96 | -- 97 | -- more complex expressions 98 | -- 99 | 100 | -- variations on unary minus parsing 101 | SELECT -2+3 AS one; 102 | 103 | SELECT 4-2 AS two; 104 | 105 | SELECT 2- -1 AS three; 106 | 107 | SELECT 2 - -2 AS four; 108 | 109 | SELECT int2 '2' * int2 '2' = int2 '16' / int2 '4' AS true; 110 | 111 | SELECT int4 '2' * int2 '2' = int2 '16' / int4 '4' AS true; 112 | 113 | SELECT int2 '2' * int4 '2' = int4 '16' / int2 '4' AS true; 114 | 115 | SELECT int4 '1000' < int4 '999' AS false; 116 | 117 | SELECT 4! AS twenty_four; 118 | 119 | SELECT !!3 AS six; 120 | 121 | SELECT 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 AS ten; 122 | 123 | SELECT 2 + 2 / 2 AS three; 124 | 125 | SELECT (2 + 2) / 2 AS two; 126 | 127 | -- corner case 128 | SELECT (-1::int4<<31)::text; 129 | SELECT ((-1::int4<<31)+1)::text; 130 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/json.sql: -------------------------------------------------------------------------------- 1 | -- Strings. 2 | SELECT '""'::json; -- OK. 3 | SELECT $$''$$::json; -- ERROR, single quotes are not allowed 4 | SELECT '"abc"'::json; -- OK 5 | SELECT '"abc'::json; -- ERROR, quotes not closed 6 | SELECT '"abc 7 | def"'::json; -- ERROR, unescaped newline in string constant 8 | SELECT '"\n\"\\"'::json; -- OK, legal escapes 9 | SELECT '"\v"'::json; -- ERROR, not a valid JSON escape 10 | SELECT '"\u"'::json; -- ERROR, incomplete escape 11 | SELECT '"\u00"'::json; -- ERROR, incomplete escape 12 | SELECT '"\u000g"'::json; -- ERROR, g is not a hex digit 13 | SELECT '"\u0000"'::json; -- OK, legal escape 14 | SELECT '"\uaBcD"'::json; -- OK, uppercase and lower case both OK 15 | 16 | -- Numbers. 17 | SELECT '1'::json; -- OK 18 | SELECT '0'::json; -- OK 19 | SELECT '01'::json; -- ERROR, not valid according to JSON spec 20 | SELECT '0.1'::json; -- OK 21 | SELECT '9223372036854775808'::json; -- OK, even though it's too large for int8 22 | SELECT '1e100'::json; -- OK 23 | SELECT '1.3e100'::json; -- OK 24 | SELECT '1f2'::json; -- ERROR 25 | SELECT '0.x1'::json; -- ERROR 26 | SELECT '1.3ex100'::json; -- ERROR 27 | 28 | -- Arrays. 29 | SELECT '[]'::json; -- OK 30 | SELECT '[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]'::json; -- OK 31 | SELECT '[1,2]'::json; -- OK 32 | SELECT '[1,2,]'::json; -- ERROR, trailing comma 33 | SELECT '[1,2'::json; -- ERROR, no closing bracket 34 | SELECT '[1,[2]'::json; -- ERROR, no closing bracket 35 | 36 | -- Objects. 37 | SELECT '{}'::json; -- OK 38 | SELECT '{"abc"}'::json; -- ERROR, no value 39 | SELECT '{"abc":1}'::json; -- OK 40 | SELECT '{1:"abc"}'::json; -- ERROR, keys must be strings 41 | SELECT '{"abc",1}'::json; -- ERROR, wrong separator 42 | SELECT '{"abc"=1}'::json; -- ERROR, totally wrong separator 43 | SELECT '{"abc"::1}'::json; -- ERROR, another wrong separator 44 | SELECT '{"abc":1,"def":2,"ghi":[3,4],"hij":{"klm":5,"nop":[6]}}'::json; -- OK 45 | SELECT '{"abc":1:2}'::json; -- ERROR, colon in wrong spot 46 | SELECT '{"abc":1,3}'::json; -- ERROR, no value 47 | 48 | -- Miscellaneous stuff. 49 | SELECT 'true'::json; -- OK 50 | SELECT 'false'::json; -- OK 51 | SELECT 'null'::json; -- OK 52 | SELECT ' true '::json; -- OK, even with extra whitespace 53 | SELECT 'true false'::json; -- ERROR, too many values 54 | SELECT 'true, false'::json; -- ERROR, too many values 55 | SELECT 'truf'::json; -- ERROR, not a keyword 56 | SELECT 'trues'::json; -- ERROR, not a keyword 57 | SELECT ''::json; -- ERROR, no value 58 | SELECT ' '::json; -- ERROR, no value 59 | 60 | --constructors 61 | -- array_to_json 62 | 63 | SELECT array_to_json(array(select 1 as a)); 64 | SELECT array_to_json(array_agg(q),false) from (select x as b, x * 2 as c from generate_series(1,3) x) q; 65 | SELECT array_to_json(array_agg(q),true) from (select x as b, x * 2 as c from generate_series(1,3) x) q; 66 | SELECT array_to_json(array_agg(q),false) 67 | FROM ( SELECT $$a$$ || x AS b, y AS c, 68 | ARRAY[ROW(x.*,ARRAY[1,2,3]), 69 | ROW(y.*,ARRAY[4,5,6])] AS z 70 | FROM generate_series(1,2) x, 71 | generate_series(4,5) y) q; 72 | SELECT array_to_json(array_agg(x),false) from generate_series(5,10) x; 73 | SELECT array_to_json('{{1,5},{99,100}}'::int[]); 74 | 75 | -- row_to_json 76 | SELECT row_to_json(row(1,'foo')); 77 | 78 | SELECT row_to_json(q) 79 | FROM (SELECT $$a$$ || x AS b, 80 | y AS c, 81 | ARRAY[ROW(x.*,ARRAY[1,2,3]), 82 | ROW(y.*,ARRAY[4,5,6])] AS z 83 | FROM generate_series(1,2) x, 84 | generate_series(4,5) y) q; 85 | 86 | SELECT row_to_json(q,true) 87 | FROM (SELECT $$a$$ || x AS b, 88 | y AS c, 89 | ARRAY[ROW(x.*,ARRAY[1,2,3]), 90 | ROW(y.*,ARRAY[4,5,6])] AS z 91 | FROM generate_series(1,2) x, 92 | generate_series(4,5) y) q; 93 | 94 | CREATE TEMP TABLE rows AS 95 | SELECT x, 'txt' || x as y 96 | FROM generate_series(1,3) AS x; 97 | 98 | SELECT row_to_json(q,true) 99 | FROM rows q; 100 | 101 | SELECT row_to_json(row((select array_agg(x) as d from generate_series(5,10) x)),false); 102 | 103 | -- non-numeric output 104 | SELECT row_to_json(q) 105 | FROM (SELECT 'NaN'::float8 AS "float8field") q; 106 | 107 | SELECT row_to_json(q) 108 | FROM (SELECT 'Infinity'::float8 AS "float8field") q; 109 | 110 | SELECT row_to_json(q) 111 | FROM (SELECT '-Infinity'::float8 AS "float8field") q; 112 | 113 | -- json input 114 | SELECT row_to_json(q) 115 | FROM (SELECT '{"a":1,"b": [2,3,4,"d","e","f"],"c":{"p":1,"q":2}}'::json AS "jsonfield") q; 116 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/limit.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- LIMIT 3 | -- Check the LIMIT/OFFSET feature of SELECT 4 | -- 5 | 6 | SELECT ''::text AS two, unique1, unique2, stringu1 7 | FROM onek WHERE unique1 > 50 8 | ORDER BY unique1 LIMIT 2; 9 | SELECT ''::text AS five, unique1, unique2, stringu1 10 | FROM onek WHERE unique1 > 60 11 | ORDER BY unique1 LIMIT 5; 12 | SELECT ''::text AS two, unique1, unique2, stringu1 13 | FROM onek WHERE unique1 > 60 AND unique1 < 63 14 | ORDER BY unique1 LIMIT 5; 15 | SELECT ''::text AS three, unique1, unique2, stringu1 16 | FROM onek WHERE unique1 > 100 17 | ORDER BY unique1 LIMIT 3 OFFSET 20; 18 | SELECT ''::text AS zero, unique1, unique2, stringu1 19 | FROM onek WHERE unique1 < 50 20 | ORDER BY unique1 DESC LIMIT 8 OFFSET 99; 21 | SELECT ''::text AS eleven, unique1, unique2, stringu1 22 | FROM onek WHERE unique1 < 50 23 | ORDER BY unique1 DESC LIMIT 20 OFFSET 39; 24 | SELECT ''::text AS ten, unique1, unique2, stringu1 25 | FROM onek 26 | ORDER BY unique1 OFFSET 990; 27 | SELECT ''::text AS five, unique1, unique2, stringu1 28 | FROM onek 29 | ORDER BY unique1 OFFSET 990 LIMIT 5; 30 | SELECT ''::text AS five, unique1, unique2, stringu1 31 | FROM onek 32 | ORDER BY unique1 LIMIT 5 OFFSET 900; 33 | 34 | -- Stress test for variable LIMIT in conjunction with bounded-heap sorting 35 | 36 | SELECT 37 | (SELECT n 38 | FROM (VALUES (1)) AS x, 39 | (SELECT n FROM generate_series(1,10) AS n 40 | ORDER BY n LIMIT 1 OFFSET s-1) AS y) AS z 41 | FROM generate_series(1,10) AS s; 42 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/lseg.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- LSEG 3 | -- Line segments 4 | -- 5 | 6 | --DROP TABLE LSEG_TBL; 7 | CREATE TABLE LSEG_TBL (s lseg); 8 | 9 | INSERT INTO LSEG_TBL VALUES ('[(1,2),(3,4)]'); 10 | INSERT INTO LSEG_TBL VALUES ('(0,0),(6,6)'); 11 | INSERT INTO LSEG_TBL VALUES ('10,-10 ,-3,-4'); 12 | INSERT INTO LSEG_TBL VALUES ('[-1e6,2e2,3e5, -4e1]'); 13 | INSERT INTO LSEG_TBL VALUES ('(11,22,33,44)'); 14 | 15 | -- bad values for parser testing 16 | INSERT INTO LSEG_TBL VALUES ('(3asdf,2 ,3,4r2)'); 17 | INSERT INTO LSEG_TBL VALUES ('[1,2,3, 4'); 18 | INSERT INTO LSEG_TBL VALUES ('[(,2),(3,4)]'); 19 | INSERT INTO LSEG_TBL VALUES ('[(1,2),(3,4)'); 20 | 21 | select * from LSEG_TBL; 22 | 23 | SELECT * FROM LSEG_TBL WHERE s <= lseg '[(1,2),(3,4)]'; 24 | 25 | SELECT * FROM LSEG_TBL WHERE (s <-> lseg '[(1,2),(3,4)]') < 10; 26 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/macaddr.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- macaddr 3 | -- 4 | 5 | CREATE TABLE macaddr_data (a int, b macaddr); 6 | 7 | INSERT INTO macaddr_data VALUES (1, '08:00:2b:01:02:03'); 8 | INSERT INTO macaddr_data VALUES (2, '08-00-2b-01-02-03'); 9 | INSERT INTO macaddr_data VALUES (3, '08002b:010203'); 10 | INSERT INTO macaddr_data VALUES (4, '08002b-010203'); 11 | INSERT INTO macaddr_data VALUES (5, '0800.2b01.0203'); 12 | INSERT INTO macaddr_data VALUES (6, '08002b010203'); 13 | INSERT INTO macaddr_data VALUES (7, '0800:2b01:0203'); -- invalid 14 | INSERT INTO macaddr_data VALUES (8, 'not even close'); -- invalid 15 | 16 | INSERT INTO macaddr_data VALUES (10, '08:00:2b:01:02:04'); 17 | INSERT INTO macaddr_data VALUES (11, '08:00:2b:01:02:02'); 18 | INSERT INTO macaddr_data VALUES (12, '08:00:2a:01:02:03'); 19 | INSERT INTO macaddr_data VALUES (13, '08:00:2c:01:02:03'); 20 | INSERT INTO macaddr_data VALUES (14, '08:00:2a:01:02:04'); 21 | 22 | SELECT * FROM macaddr_data; 23 | 24 | CREATE INDEX macaddr_data_btree ON macaddr_data USING btree (b); 25 | CREATE INDEX macaddr_data_hash ON macaddr_data USING hash (b); 26 | 27 | SELECT a, b, trunc(b) FROM macaddr_data ORDER BY 2, 1; 28 | 29 | SELECT b < '08:00:2b:01:02:04' FROM macaddr_data WHERE a = 1; -- true 30 | SELECT b > '08:00:2b:01:02:04' FROM macaddr_data WHERE a = 1; -- false 31 | SELECT b > '08:00:2b:01:02:03' FROM macaddr_data WHERE a = 1; -- false 32 | SELECT b <= '08:00:2b:01:02:04' FROM macaddr_data WHERE a = 1; -- true 33 | SELECT b >= '08:00:2b:01:02:04' FROM macaddr_data WHERE a = 1; -- false 34 | SELECT b = '08:00:2b:01:02:03' FROM macaddr_data WHERE a = 1; -- true 35 | SELECT b <> '08:00:2b:01:02:04' FROM macaddr_data WHERE a = 1; -- true 36 | SELECT b <> '08:00:2b:01:02:03' FROM macaddr_data WHERE a = 1; -- false 37 | 38 | SELECT ~b FROM macaddr_data; 39 | SELECT b & '00:00:00:ff:ff:ff' FROM macaddr_data; 40 | SELECT b | '01:02:03:04:05:06' FROM macaddr_data; 41 | 42 | DROP TABLE macaddr_data; 43 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/money.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- MONEY 3 | -- 4 | 5 | CREATE TABLE money_data (m money); 6 | 7 | INSERT INTO money_data VALUES ('123'); 8 | SELECT * FROM money_data; 9 | SELECT m + '123' FROM money_data; 10 | SELECT m + '123.45' FROM money_data; 11 | SELECT m - '123.45' FROM money_data; 12 | SELECT m * 2 FROM money_data; 13 | SELECT m / 2 FROM money_data; 14 | 15 | -- All true 16 | SELECT m = '$123.00' FROM money_data; 17 | SELECT m != '$124.00' FROM money_data; 18 | SELECT m <= '$123.00' FROM money_data; 19 | SELECT m >= '$123.00' FROM money_data; 20 | SELECT m < '$124.00' FROM money_data; 21 | SELECT m > '$122.00' FROM money_data; 22 | 23 | -- All false 24 | SELECT m = '$123.01' FROM money_data; 25 | SELECT m != '$123.00' FROM money_data; 26 | SELECT m <= '$122.99' FROM money_data; 27 | SELECT m >= '$123.01' FROM money_data; 28 | SELECT m > '$124.00' FROM money_data; 29 | SELECT m < '$122.00' FROM money_data; 30 | 31 | SELECT cashlarger(m, '$124.00') FROM money_data; 32 | SELECT cashsmaller(m, '$124.00') FROM money_data; 33 | SELECT cash_words(m) FROM money_data; 34 | SELECT cash_words(m + '1.23') FROM money_data; 35 | 36 | DELETE FROM money_data; 37 | INSERT INTO money_data VALUES ('$123.45'); 38 | SELECT * FROM money_data; 39 | 40 | DELETE FROM money_data; 41 | INSERT INTO money_data VALUES ('$123.451'); 42 | SELECT * FROM money_data; 43 | 44 | DELETE FROM money_data; 45 | INSERT INTO money_data VALUES ('$123.454'); 46 | SELECT * FROM money_data; 47 | 48 | DELETE FROM money_data; 49 | INSERT INTO money_data VALUES ('$123.455'); 50 | SELECT * FROM money_data; 51 | 52 | DELETE FROM money_data; 53 | INSERT INTO money_data VALUES ('$123.456'); 54 | SELECT * FROM money_data; 55 | 56 | DELETE FROM money_data; 57 | INSERT INTO money_data VALUES ('$123.459'); 58 | SELECT * FROM money_data; 59 | 60 | -- Cast int4/int8 to money 61 | SELECT 1234567890::money; 62 | SELECT 12345678901234567::money; 63 | SELECT 123456789012345678::money; 64 | SELECT 9223372036854775807::money; 65 | SELECT (-12345)::money; 66 | SELECT (-1234567890)::money; 67 | SELECT (-12345678901234567)::money; 68 | SELECT (-123456789012345678)::money; 69 | SELECT (-9223372036854775808)::money; 70 | SELECT 1234567890::int4::money; 71 | SELECT 12345678901234567::int8::money; 72 | SELECT (-1234567890)::int4::money; 73 | SELECT (-12345678901234567)::int8::money; 74 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/mule_internal.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/valgog/pg_sql_parser/3c6c30e7518026ca871d125223ac2e3ff837f2fd/plpgsql-ast/src/test/resources/sql_parse_test/mule_internal.sql -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/name.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- NAME 3 | -- all inputs are silently truncated at NAMEDATALEN-1 (63) characters 4 | -- 5 | 6 | -- fixed-length by reference 7 | SELECT name 'name string' = name 'name string' AS "True"; 8 | 9 | SELECT name 'name string' = name 'name string ' AS "False"; 10 | 11 | -- 12 | -- 13 | -- 14 | 15 | CREATE TABLE NAME_TBL(f1 name); 16 | 17 | INSERT INTO NAME_TBL(f1) VALUES ('1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCDEFGHIJKLMNOPQR'); 18 | 19 | INSERT INTO NAME_TBL(f1) VALUES ('1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqr'); 20 | 21 | INSERT INTO NAME_TBL(f1) VALUES ('asdfghjkl;'); 22 | 23 | INSERT INTO NAME_TBL(f1) VALUES ('343f%2a'); 24 | 25 | INSERT INTO NAME_TBL(f1) VALUES ('d34aaasdf'); 26 | 27 | INSERT INTO NAME_TBL(f1) VALUES (''); 28 | 29 | INSERT INTO NAME_TBL(f1) VALUES ('1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ'); 30 | 31 | 32 | SELECT '' AS seven, * FROM NAME_TBL; 33 | 34 | SELECT '' AS six, c.f1 FROM NAME_TBL c WHERE c.f1 <> '1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCDEFGHIJKLMNOPQR'; 35 | 36 | SELECT '' AS one, c.f1 FROM NAME_TBL c WHERE c.f1 = '1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCDEFGHIJKLMNOPQR'; 37 | 38 | SELECT '' AS three, c.f1 FROM NAME_TBL c WHERE c.f1 < '1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCDEFGHIJKLMNOPQR'; 39 | 40 | SELECT '' AS four, c.f1 FROM NAME_TBL c WHERE c.f1 <= '1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCDEFGHIJKLMNOPQR'; 41 | 42 | SELECT '' AS three, c.f1 FROM NAME_TBL c WHERE c.f1 > '1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCDEFGHIJKLMNOPQR'; 43 | 44 | SELECT '' AS four, c.f1 FROM NAME_TBL c WHERE c.f1 >= '1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCDEFGHIJKLMNOPQR'; 45 | 46 | SELECT '' AS seven, c.f1 FROM NAME_TBL c WHERE c.f1 ~ '.*'; 47 | 48 | SELECT '' AS zero, c.f1 FROM NAME_TBL c WHERE c.f1 !~ '.*'; 49 | 50 | SELECT '' AS three, c.f1 FROM NAME_TBL c WHERE c.f1 ~ '[0-9]'; 51 | 52 | SELECT '' AS two, c.f1 FROM NAME_TBL c WHERE c.f1 ~ '.*asdf.*'; 53 | 54 | DROP TABLE NAME_TBL; 55 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/namespace.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- Regression tests for schemas (namespaces) 3 | -- 4 | 5 | CREATE SCHEMA test_schema_1 6 | CREATE UNIQUE INDEX abc_a_idx ON abc (a) 7 | 8 | CREATE VIEW abc_view AS 9 | SELECT a+1 AS a, b+1 AS b FROM abc 10 | 11 | CREATE TABLE abc ( 12 | a serial, 13 | b int UNIQUE 14 | ); 15 | 16 | -- verify that the objects were created 17 | SELECT COUNT(*) FROM pg_class WHERE relnamespace = 18 | (SELECT oid FROM pg_namespace WHERE nspname = 'test_schema_1'); 19 | 20 | INSERT INTO test_schema_1.abc DEFAULT VALUES; 21 | INSERT INTO test_schema_1.abc DEFAULT VALUES; 22 | INSERT INTO test_schema_1.abc DEFAULT VALUES; 23 | 24 | SELECT * FROM test_schema_1.abc; 25 | SELECT * FROM test_schema_1.abc_view; 26 | 27 | DROP SCHEMA test_schema_1 CASCADE; 28 | 29 | -- verify that the objects were dropped 30 | SELECT COUNT(*) FROM pg_class WHERE relnamespace = 31 | (SELECT oid FROM pg_namespace WHERE nspname = 'test_schema_1'); 32 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/numerology.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- NUMEROLOGY 3 | -- Test various combinations of numeric types and functions. 4 | -- 5 | 6 | -- 7 | -- Test implicit type conversions 8 | -- This fails for Postgres v6.1 (and earlier?) 9 | -- so let's try explicit conversions for now - tgl 97/05/07 10 | -- 11 | 12 | CREATE TABLE TEMP_FLOAT (f1 FLOAT8); 13 | 14 | INSERT INTO TEMP_FLOAT (f1) 15 | SELECT float8(f1) FROM INT4_TBL; 16 | 17 | INSERT INTO TEMP_FLOAT (f1) 18 | SELECT float8(f1) FROM INT2_TBL; 19 | 20 | SELECT '' AS ten, f1 FROM TEMP_FLOAT 21 | ORDER BY f1; 22 | 23 | -- int4 24 | 25 | CREATE TABLE TEMP_INT4 (f1 INT4); 26 | 27 | INSERT INTO TEMP_INT4 (f1) 28 | SELECT int4(f1) FROM FLOAT8_TBL 29 | WHERE (f1 > -2147483647) AND (f1 < 2147483647); 30 | 31 | INSERT INTO TEMP_INT4 (f1) 32 | SELECT int4(f1) FROM INT2_TBL; 33 | 34 | SELECT '' AS nine, f1 FROM TEMP_INT4 35 | ORDER BY f1; 36 | 37 | -- int2 38 | 39 | CREATE TABLE TEMP_INT2 (f1 INT2); 40 | 41 | INSERT INTO TEMP_INT2 (f1) 42 | SELECT int2(f1) FROM FLOAT8_TBL 43 | WHERE (f1 >= -32767) AND (f1 <= 32767); 44 | 45 | INSERT INTO TEMP_INT2 (f1) 46 | SELECT int2(f1) FROM INT4_TBL 47 | WHERE (f1 >= -32767) AND (f1 <= 32767); 48 | 49 | SELECT '' AS five, f1 FROM TEMP_INT2 50 | ORDER BY f1; 51 | 52 | -- 53 | -- Group-by combinations 54 | -- 55 | 56 | CREATE TABLE TEMP_GROUP (f1 INT4, f2 INT4, f3 FLOAT8); 57 | 58 | INSERT INTO TEMP_GROUP 59 | SELECT 1, (- i.f1), (- f.f1) 60 | FROM INT4_TBL i, FLOAT8_TBL f; 61 | 62 | INSERT INTO TEMP_GROUP 63 | SELECT 2, i.f1, f.f1 64 | FROM INT4_TBL i, FLOAT8_TBL f; 65 | 66 | SELECT DISTINCT f1 AS two FROM TEMP_GROUP ORDER BY 1; 67 | 68 | SELECT f1 AS two, max(f3) AS max_float, min(f3) as min_float 69 | FROM TEMP_GROUP 70 | GROUP BY f1 71 | ORDER BY two, max_float, min_float; 72 | 73 | -- GROUP BY a result column name is not legal per SQL92, but we accept it 74 | -- anyway (if the name is not the name of any column exposed by FROM). 75 | SELECT f1 AS two, max(f3) AS max_float, min(f3) AS min_float 76 | FROM TEMP_GROUP 77 | GROUP BY two 78 | ORDER BY two, max_float, min_float; 79 | 80 | SELECT f1 AS two, (max(f3) + 1) AS max_plus_1, (min(f3) - 1) AS min_minus_1 81 | FROM TEMP_GROUP 82 | GROUP BY f1 83 | ORDER BY two, min_minus_1; 84 | 85 | SELECT f1 AS two, 86 | max(f2) + min(f2) AS max_plus_min, 87 | min(f3) - 1 AS min_minus_1 88 | FROM TEMP_GROUP 89 | GROUP BY f1 90 | ORDER BY two, min_minus_1; 91 | 92 | DROP TABLE TEMP_INT2; 93 | 94 | DROP TABLE TEMP_INT4; 95 | 96 | DROP TABLE TEMP_FLOAT; 97 | 98 | DROP TABLE TEMP_GROUP; 99 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/oid.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- OID 3 | -- 4 | 5 | CREATE TABLE OID_TBL(f1 oid); 6 | 7 | INSERT INTO OID_TBL(f1) VALUES ('1234'); 8 | INSERT INTO OID_TBL(f1) VALUES ('1235'); 9 | INSERT INTO OID_TBL(f1) VALUES ('987'); 10 | INSERT INTO OID_TBL(f1) VALUES ('-1040'); 11 | INSERT INTO OID_TBL(f1) VALUES ('99999999'); 12 | INSERT INTO OID_TBL(f1) VALUES ('5 '); 13 | INSERT INTO OID_TBL(f1) VALUES (' 10 '); 14 | -- leading/trailing hard tab is also allowed 15 | INSERT INTO OID_TBL(f1) VALUES (' 15 '); 16 | 17 | -- bad inputs 18 | INSERT INTO OID_TBL(f1) VALUES (''); 19 | INSERT INTO OID_TBL(f1) VALUES (' '); 20 | INSERT INTO OID_TBL(f1) VALUES ('asdfasd'); 21 | INSERT INTO OID_TBL(f1) VALUES ('99asdfasd'); 22 | INSERT INTO OID_TBL(f1) VALUES ('5 d'); 23 | INSERT INTO OID_TBL(f1) VALUES (' 5d'); 24 | INSERT INTO OID_TBL(f1) VALUES ('5 5'); 25 | INSERT INTO OID_TBL(f1) VALUES (' - 500'); 26 | INSERT INTO OID_TBL(f1) VALUES ('32958209582039852935'); 27 | INSERT INTO OID_TBL(f1) VALUES ('-23582358720398502385'); 28 | 29 | SELECT '' AS six, * FROM OID_TBL; 30 | 31 | SELECT '' AS one, o.* FROM OID_TBL o WHERE o.f1 = 1234; 32 | 33 | SELECT '' AS five, o.* FROM OID_TBL o WHERE o.f1 <> '1234'; 34 | 35 | SELECT '' AS three, o.* FROM OID_TBL o WHERE o.f1 <= '1234'; 36 | 37 | SELECT '' AS two, o.* FROM OID_TBL o WHERE o.f1 < '1234'; 38 | 39 | SELECT '' AS four, o.* FROM OID_TBL o WHERE o.f1 >= '1234'; 40 | 41 | SELECT '' AS three, o.* FROM OID_TBL o WHERE o.f1 > '1234'; 42 | 43 | DROP TABLE OID_TBL; 44 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/path.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- PATH 3 | -- 4 | 5 | --DROP TABLE PATH_TBL; 6 | 7 | CREATE TABLE PATH_TBL (f1 path); 8 | 9 | INSERT INTO PATH_TBL VALUES ('[(1,2),(3,4)]'); 10 | 11 | INSERT INTO PATH_TBL VALUES ('((1,2),(3,4))'); 12 | 13 | INSERT INTO PATH_TBL VALUES ('[(0,0),(3,0),(4,5),(1,6)]'); 14 | 15 | INSERT INTO PATH_TBL VALUES ('((1,2),(3,4))'); 16 | 17 | INSERT INTO PATH_TBL VALUES ('1,2 ,3,4'); 18 | 19 | INSERT INTO PATH_TBL VALUES ('[1,2,3, 4]'); 20 | 21 | INSERT INTO PATH_TBL VALUES ('[11,12,13,14]'); 22 | 23 | INSERT INTO PATH_TBL VALUES ('(11,12,13,14)'); 24 | 25 | -- bad values for parser testing 26 | INSERT INTO PATH_TBL VALUES ('[(,2),(3,4)]'); 27 | 28 | INSERT INTO PATH_TBL VALUES ('[(1,2),(3,4)'); 29 | 30 | SELECT f1 FROM PATH_TBL; 31 | 32 | SELECT '' AS count, f1 AS open_path FROM PATH_TBL WHERE isopen(f1); 33 | 34 | SELECT '' AS count, f1 AS closed_path FROM PATH_TBL WHERE isclosed(f1); 35 | 36 | SELECT '' AS count, pclose(f1) AS closed_path FROM PATH_TBL; 37 | 38 | SELECT '' AS count, popen(f1) AS open_path FROM PATH_TBL; 39 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/plancache.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- Tests to exercise the plan caching/invalidation mechanism 3 | -- 4 | 5 | CREATE TEMP TABLE pcachetest AS SELECT * FROM int8_tbl; 6 | 7 | -- create and use a cached plan 8 | PREPARE prepstmt AS SELECT * FROM pcachetest; 9 | 10 | EXECUTE prepstmt; 11 | 12 | -- and one with parameters 13 | PREPARE prepstmt2(bigint) AS SELECT * FROM pcachetest WHERE q1 = $1; 14 | 15 | EXECUTE prepstmt2(123); 16 | 17 | -- invalidate the plans and see what happens 18 | DROP TABLE pcachetest; 19 | 20 | EXECUTE prepstmt; 21 | EXECUTE prepstmt2(123); 22 | 23 | -- recreate the temp table (this demonstrates that the raw plan is 24 | -- purely textual and doesn't depend on OIDs, for instance) 25 | CREATE TEMP TABLE pcachetest AS SELECT * FROM int8_tbl ORDER BY 2; 26 | 27 | EXECUTE prepstmt; 28 | EXECUTE prepstmt2(123); 29 | 30 | -- prepared statements should prevent change in output tupdesc, 31 | -- since clients probably aren't expecting that to change on the fly 32 | ALTER TABLE pcachetest ADD COLUMN q3 bigint; 33 | 34 | EXECUTE prepstmt; 35 | EXECUTE prepstmt2(123); 36 | 37 | -- but we're nice guys and will let you undo your mistake 38 | ALTER TABLE pcachetest DROP COLUMN q3; 39 | 40 | EXECUTE prepstmt; 41 | EXECUTE prepstmt2(123); 42 | 43 | -- Try it with a view, which isn't directly used in the resulting plan 44 | -- but should trigger invalidation anyway 45 | CREATE TEMP VIEW pcacheview AS 46 | SELECT * FROM pcachetest; 47 | 48 | PREPARE vprep AS SELECT * FROM pcacheview; 49 | 50 | EXECUTE vprep; 51 | 52 | CREATE OR REPLACE TEMP VIEW pcacheview AS 53 | SELECT q1, q2/2 AS q2 FROM pcachetest; 54 | 55 | EXECUTE vprep; 56 | 57 | -- Check basic SPI plan invalidation 58 | 59 | create function cache_test(int) returns int as $$ 60 | declare total int; 61 | begin 62 | create temp table t1(f1 int); 63 | insert into t1 values($1); 64 | insert into t1 values(11); 65 | insert into t1 values(12); 66 | insert into t1 values(13); 67 | select sum(f1) into total from t1; 68 | drop table t1; 69 | return total; 70 | end 71 | $$ language plpgsql; 72 | 73 | select cache_test(1); 74 | select cache_test(2); 75 | select cache_test(3); 76 | 77 | -- Check invalidation of plpgsql "simple expression" 78 | 79 | create temp view v1 as 80 | select 2+2 as f1; 81 | 82 | create function cache_test_2() returns int as $$ 83 | begin 84 | return f1 from v1; 85 | end$$ language plpgsql; 86 | 87 | select cache_test_2(); 88 | 89 | create or replace temp view v1 as 90 | select 2+2+4 as f1; 91 | select cache_test_2(); 92 | 93 | create or replace temp view v1 as 94 | select 2+2+4+(select max(unique1) from tenk1) as f1; 95 | select cache_test_2(); 96 | 97 | --- Check that change of search_path is ignored by replans 98 | 99 | create schema s1 100 | create table abc (f1 int); 101 | 102 | create schema s2 103 | create table abc (f1 int); 104 | 105 | insert into s1.abc values(123); 106 | insert into s2.abc values(456); 107 | 108 | set search_path = s1; 109 | 110 | prepare p1 as select f1 from abc; 111 | 112 | execute p1; 113 | 114 | set search_path = s2; 115 | 116 | select f1 from abc; 117 | 118 | execute p1; 119 | 120 | alter table s1.abc add column f2 float8; -- force replan 121 | 122 | execute p1; 123 | 124 | drop schema s1 cascade; 125 | drop schema s2 cascade; 126 | 127 | reset search_path; 128 | 129 | -- Check that invalidation deals with regclass constants 130 | 131 | create temp sequence seq; 132 | 133 | prepare p2 as select nextval('seq'); 134 | 135 | execute p2; 136 | 137 | drop sequence seq; 138 | 139 | create temp sequence seq; 140 | 141 | execute p2; 142 | 143 | -- Check DDL via SPI, immediately followed by SPI plan re-use 144 | -- (bug in original coding) 145 | 146 | create function cachebug() returns void as $$ 147 | declare r int; 148 | begin 149 | drop table if exists temptable cascade; 150 | create temp table temptable as select * from generate_series(1,3) as f1; 151 | create temp view vv as select * from temptable; 152 | for r in select * from vv loop 153 | raise notice '%', r; 154 | end loop; 155 | end$$ language plpgsql; 156 | 157 | select cachebug(); 158 | select cachebug(); 159 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/point.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- POINT 3 | -- 4 | 5 | CREATE TABLE POINT_TBL(f1 point); 6 | 7 | INSERT INTO POINT_TBL(f1) VALUES ('(0.0,0.0)'); 8 | 9 | INSERT INTO POINT_TBL(f1) VALUES ('(-10.0,0.0)'); 10 | 11 | INSERT INTO POINT_TBL(f1) VALUES ('(-3.0,4.0)'); 12 | 13 | INSERT INTO POINT_TBL(f1) VALUES ('(5.1, 34.5)'); 14 | 15 | INSERT INTO POINT_TBL(f1) VALUES ('(-5.0,-12.0)'); 16 | 17 | -- bad format points 18 | INSERT INTO POINT_TBL(f1) VALUES ('asdfasdf'); 19 | 20 | INSERT INTO POINT_TBL(f1) VALUES ('10.0,10.0'); 21 | 22 | INSERT INTO POINT_TBL(f1) VALUES ('(10.0 10.0)'); 23 | 24 | INSERT INTO POINT_TBL(f1) VALUES ('(10.0,10.0'); 25 | 26 | 27 | SELECT '' AS six, * FROM POINT_TBL; 28 | 29 | -- left of 30 | SELECT '' AS three, p.* FROM POINT_TBL p WHERE p.f1 << '(0.0, 0.0)'; 31 | 32 | -- right of 33 | SELECT '' AS three, p.* FROM POINT_TBL p WHERE '(0.0,0.0)' >> p.f1; 34 | 35 | -- above 36 | SELECT '' AS one, p.* FROM POINT_TBL p WHERE '(0.0,0.0)' >^ p.f1; 37 | 38 | -- below 39 | SELECT '' AS one, p.* FROM POINT_TBL p WHERE p.f1 <^ '(0.0, 0.0)'; 40 | 41 | -- equal 42 | SELECT '' AS one, p.* FROM POINT_TBL p WHERE p.f1 ~= '(5.1, 34.5)'; 43 | 44 | -- point in box 45 | SELECT '' AS three, p.* FROM POINT_TBL p 46 | WHERE p.f1 <@ box '(0,0,100,100)'; 47 | 48 | SELECT '' AS three, p.* FROM POINT_TBL p 49 | WHERE box '(0,0,100,100)' @> p.f1; 50 | 51 | SELECT '' AS three, p.* FROM POINT_TBL p 52 | WHERE not p.f1 <@ box '(0,0,100,100)'; 53 | 54 | SELECT '' AS two, p.* FROM POINT_TBL p 55 | WHERE p.f1 <@ path '[(0,0),(-10,0),(-10,10)]'; 56 | 57 | SELECT '' AS three, p.* FROM POINT_TBL p 58 | WHERE not box '(0,0,100,100)' @> p.f1; 59 | 60 | SELECT '' AS six, p.f1, p.f1 <-> point '(0,0)' AS dist 61 | FROM POINT_TBL p 62 | ORDER BY dist; 63 | 64 | SELECT '' AS thirtysix, p1.f1 AS point1, p2.f1 AS point2, p1.f1 <-> p2.f1 AS dist 65 | FROM POINT_TBL p1, POINT_TBL p2 66 | ORDER BY dist, p1.f1[0], p2.f1[0]; 67 | 68 | SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2 69 | FROM POINT_TBL p1, POINT_TBL p2 70 | WHERE (p1.f1 <-> p2.f1) > 3; 71 | 72 | -- put distance result into output to allow sorting with GEQ optimizer - tgl 97/05/10 73 | SELECT '' AS fifteen, p1.f1 AS point1, p2.f1 AS point2, (p1.f1 <-> p2.f1) AS distance 74 | FROM POINT_TBL p1, POINT_TBL p2 75 | WHERE (p1.f1 <-> p2.f1) > 3 and p1.f1 << p2.f1 76 | ORDER BY distance, p1.f1[0], p2.f1[0]; 77 | 78 | -- put distance result into output to allow sorting with GEQ optimizer - tgl 97/05/10 79 | SELECT '' AS three, p1.f1 AS point1, p2.f1 AS point2, (p1.f1 <-> p2.f1) AS distance 80 | FROM POINT_TBL p1, POINT_TBL p2 81 | WHERE (p1.f1 <-> p2.f1) > 3 and p1.f1 << p2.f1 and p1.f1 >^ p2.f1 82 | ORDER BY distance; 83 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/portals_p2.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- PORTALS_P2 3 | -- 4 | 5 | BEGIN; 6 | 7 | DECLARE foo13 CURSOR FOR 8 | SELECT * FROM onek WHERE unique1 = 50; 9 | 10 | DECLARE foo14 CURSOR FOR 11 | SELECT * FROM onek WHERE unique1 = 51; 12 | 13 | DECLARE foo15 CURSOR FOR 14 | SELECT * FROM onek WHERE unique1 = 52; 15 | 16 | DECLARE foo16 CURSOR FOR 17 | SELECT * FROM onek WHERE unique1 = 53; 18 | 19 | DECLARE foo17 CURSOR FOR 20 | SELECT * FROM onek WHERE unique1 = 54; 21 | 22 | DECLARE foo18 CURSOR FOR 23 | SELECT * FROM onek WHERE unique1 = 55; 24 | 25 | DECLARE foo19 CURSOR FOR 26 | SELECT * FROM onek WHERE unique1 = 56; 27 | 28 | DECLARE foo20 CURSOR FOR 29 | SELECT * FROM onek WHERE unique1 = 57; 30 | 31 | DECLARE foo21 CURSOR FOR 32 | SELECT * FROM onek WHERE unique1 = 58; 33 | 34 | DECLARE foo22 CURSOR FOR 35 | SELECT * FROM onek WHERE unique1 = 59; 36 | 37 | DECLARE foo23 CURSOR FOR 38 | SELECT * FROM onek WHERE unique1 = 60; 39 | 40 | DECLARE foo24 CURSOR FOR 41 | SELECT * FROM onek2 WHERE unique1 = 50; 42 | 43 | DECLARE foo25 CURSOR FOR 44 | SELECT * FROM onek2 WHERE unique1 = 60; 45 | 46 | FETCH all in foo13; 47 | 48 | FETCH all in foo14; 49 | 50 | FETCH all in foo15; 51 | 52 | FETCH all in foo16; 53 | 54 | FETCH all in foo17; 55 | 56 | FETCH all in foo18; 57 | 58 | FETCH all in foo19; 59 | 60 | FETCH all in foo20; 61 | 62 | FETCH all in foo21; 63 | 64 | FETCH all in foo22; 65 | 66 | FETCH all in foo23; 67 | 68 | FETCH all in foo24; 69 | 70 | FETCH all in foo25; 71 | 72 | CLOSE foo13; 73 | 74 | CLOSE foo14; 75 | 76 | CLOSE foo15; 77 | 78 | CLOSE foo16; 79 | 80 | CLOSE foo17; 81 | 82 | CLOSE foo18; 83 | 84 | CLOSE foo19; 85 | 86 | CLOSE foo20; 87 | 88 | CLOSE foo21; 89 | 90 | CLOSE foo22; 91 | 92 | CLOSE foo23; 93 | 94 | CLOSE foo24; 95 | 96 | CLOSE foo25; 97 | 98 | END; 99 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/prepare.sql: -------------------------------------------------------------------------------- 1 | -- Regression tests for prepareable statements. We query the content 2 | -- of the pg_prepared_statements view as prepared statements are 3 | -- created and removed. 4 | 5 | SELECT name, statement, parameter_types FROM pg_prepared_statements; 6 | 7 | PREPARE q1 AS SELECT 1 AS a; 8 | EXECUTE q1; 9 | 10 | SELECT name, statement, parameter_types FROM pg_prepared_statements; 11 | 12 | -- should fail 13 | PREPARE q1 AS SELECT 2; 14 | 15 | -- should succeed 16 | DEALLOCATE q1; 17 | PREPARE q1 AS SELECT 2; 18 | EXECUTE q1; 19 | 20 | PREPARE q2 AS SELECT 2 AS b; 21 | SELECT name, statement, parameter_types FROM pg_prepared_statements; 22 | 23 | -- sql92 syntax 24 | DEALLOCATE PREPARE q1; 25 | 26 | SELECT name, statement, parameter_types FROM pg_prepared_statements; 27 | 28 | DEALLOCATE PREPARE q2; 29 | -- the view should return the empty set again 30 | SELECT name, statement, parameter_types FROM pg_prepared_statements; 31 | 32 | -- parameterized queries 33 | PREPARE q2(text) AS 34 | SELECT datname, datistemplate, datallowconn 35 | FROM pg_database WHERE datname = $1; 36 | 37 | EXECUTE q2('postgres'); 38 | 39 | PREPARE q3(text, int, float, boolean, oid, smallint) AS 40 | SELECT * FROM tenk1 WHERE string4 = $1 AND (four = $2 OR 41 | ten = $3::bigint OR true = $4 OR oid = $5 OR odd = $6::int) 42 | ORDER BY unique1; 43 | 44 | EXECUTE q3('AAAAxx', 5::smallint, 10.5::float, false, 500::oid, 4::bigint); 45 | 46 | -- too few params 47 | EXECUTE q3('bool'); 48 | 49 | -- too many params 50 | EXECUTE q3('bytea', 5::smallint, 10.5::float, false, 500::oid, 4::bigint, true); 51 | 52 | -- wrong param types 53 | EXECUTE q3(5::smallint, 10.5::float, false, 500::oid, 4::bigint, 'bytea'); 54 | 55 | -- invalid type 56 | PREPARE q4(nonexistenttype) AS SELECT $1; 57 | 58 | -- create table as execute 59 | PREPARE q5(int, text) AS 60 | SELECT * FROM tenk1 WHERE unique1 = $1 OR stringu1 = $2 61 | ORDER BY unique1; 62 | CREATE TEMPORARY TABLE q5_prep_results AS EXECUTE q5(200, 'DTAAAA'); 63 | SELECT * FROM q5_prep_results; 64 | 65 | -- unknown or unspecified parameter types: should succeed 66 | PREPARE q6 AS 67 | SELECT * FROM tenk1 WHERE unique1 = $1 AND stringu1 = $2; 68 | PREPARE q7(unknown) AS 69 | SELECT * FROM road WHERE thepath = $1; 70 | 71 | SELECT name, statement, parameter_types FROM pg_prepared_statements 72 | ORDER BY name; 73 | 74 | -- test DEALLOCATE ALL; 75 | DEALLOCATE ALL; 76 | SELECT name, statement, parameter_types FROM pg_prepared_statements 77 | ORDER BY name; 78 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/prepared_xacts.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- PREPARED TRANSACTIONS (two-phase commit) 3 | -- 4 | -- We can't readily test persistence of prepared xacts within the 5 | -- regression script framework, unfortunately. Note that a crash 6 | -- isn't really needed ... stopping and starting the postmaster would 7 | -- be enough, but we can't even do that here. 8 | 9 | 10 | -- create a simple table that we'll use in the tests 11 | CREATE TABLE pxtest1 (foobar VARCHAR(10)); 12 | 13 | INSERT INTO pxtest1 VALUES ('aaa'); 14 | 15 | 16 | -- Test PREPARE TRANSACTION 17 | BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; 18 | UPDATE pxtest1 SET foobar = 'bbb' WHERE foobar = 'aaa'; 19 | SELECT * FROM pxtest1; 20 | PREPARE TRANSACTION 'foo1'; 21 | 22 | SELECT * FROM pxtest1; 23 | 24 | -- Test pg_prepared_xacts system view 25 | SELECT gid FROM pg_prepared_xacts; 26 | 27 | -- Test ROLLBACK PREPARED 28 | ROLLBACK PREPARED 'foo1'; 29 | 30 | SELECT * FROM pxtest1; 31 | 32 | SELECT gid FROM pg_prepared_xacts; 33 | 34 | 35 | -- Test COMMIT PREPARED 36 | BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; 37 | INSERT INTO pxtest1 VALUES ('ddd'); 38 | SELECT * FROM pxtest1; 39 | PREPARE TRANSACTION 'foo2'; 40 | 41 | SELECT * FROM pxtest1; 42 | 43 | COMMIT PREPARED 'foo2'; 44 | 45 | SELECT * FROM pxtest1; 46 | 47 | -- Test duplicate gids 48 | BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; 49 | UPDATE pxtest1 SET foobar = 'eee' WHERE foobar = 'ddd'; 50 | SELECT * FROM pxtest1; 51 | PREPARE TRANSACTION 'foo3'; 52 | 53 | SELECT gid FROM pg_prepared_xacts; 54 | 55 | BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; 56 | INSERT INTO pxtest1 VALUES ('fff'); 57 | 58 | -- This should fail, because the gid foo3 is already in use 59 | PREPARE TRANSACTION 'foo3'; 60 | 61 | SELECT * FROM pxtest1; 62 | 63 | ROLLBACK PREPARED 'foo3'; 64 | 65 | SELECT * FROM pxtest1; 66 | 67 | -- Test serialization failure (SSI) 68 | BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; 69 | UPDATE pxtest1 SET foobar = 'eee' WHERE foobar = 'ddd'; 70 | SELECT * FROM pxtest1; 71 | PREPARE TRANSACTION 'foo4'; 72 | 73 | SELECT gid FROM pg_prepared_xacts; 74 | 75 | BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; 76 | SELECT * FROM pxtest1; 77 | 78 | -- This should fail, because the two transactions have a write-skew anomaly 79 | INSERT INTO pxtest1 VALUES ('fff'); 80 | PREPARE TRANSACTION 'foo5'; 81 | 82 | SELECT gid FROM pg_prepared_xacts; 83 | 84 | ROLLBACK PREPARED 'foo4'; 85 | 86 | SELECT gid FROM pg_prepared_xacts; 87 | 88 | -- Clean up 89 | DROP TABLE pxtest1; 90 | 91 | -- Test subtransactions 92 | BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; 93 | CREATE TABLE pxtest2 (a int); 94 | INSERT INTO pxtest2 VALUES (1); 95 | SAVEPOINT a; 96 | INSERT INTO pxtest2 VALUES (2); 97 | ROLLBACK TO a; 98 | SAVEPOINT b; 99 | INSERT INTO pxtest2 VALUES (3); 100 | PREPARE TRANSACTION 'regress-one'; 101 | 102 | CREATE TABLE pxtest3(fff int); 103 | 104 | -- Test shared invalidation 105 | BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; 106 | DROP TABLE pxtest3; 107 | CREATE TABLE pxtest4 (a int); 108 | INSERT INTO pxtest4 VALUES (1); 109 | INSERT INTO pxtest4 VALUES (2); 110 | DECLARE foo CURSOR FOR SELECT * FROM pxtest4; 111 | -- Fetch 1 tuple, keeping the cursor open 112 | FETCH 1 FROM foo; 113 | PREPARE TRANSACTION 'regress-two'; 114 | 115 | -- No such cursor 116 | FETCH 1 FROM foo; 117 | 118 | -- Table doesn't exist, the creation hasn't been committed yet 119 | SELECT * FROM pxtest2; 120 | 121 | -- There should be two prepared transactions 122 | SELECT gid FROM pg_prepared_xacts; 123 | 124 | -- pxtest3 should be locked because of the pending DROP 125 | set statement_timeout to 2000; 126 | SELECT * FROM pxtest3; 127 | reset statement_timeout; 128 | 129 | -- Disconnect, we will continue testing in a different backend 130 | \c - 131 | 132 | -- There should still be two prepared transactions 133 | SELECT gid FROM pg_prepared_xacts; 134 | 135 | -- pxtest3 should still be locked because of the pending DROP 136 | set statement_timeout to 2000; 137 | SELECT * FROM pxtest3; 138 | reset statement_timeout; 139 | 140 | -- Commit table creation 141 | COMMIT PREPARED 'regress-one'; 142 | \d pxtest2 143 | SELECT * FROM pxtest2; 144 | 145 | -- There should be one prepared transaction 146 | SELECT gid FROM pg_prepared_xacts; 147 | 148 | -- Commit table drop 149 | COMMIT PREPARED 'regress-two'; 150 | SELECT * FROM pxtest3; 151 | 152 | -- There should be no prepared transactions 153 | SELECT gid FROM pg_prepared_xacts; 154 | 155 | -- Clean up 156 | DROP TABLE pxtest2; 157 | DROP TABLE pxtest3; -- will still be there if prepared xacts are disabled 158 | DROP TABLE pxtest4; 159 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/query_with_complex_where_clause.sql: -------------------------------------------------------------------------------- 1 | SELECT ft_id 2 | INTO a 3 | FROM t.my_fancy_table 4 | JOIN t.other_table ON ot_id = mft_my_fancy_table_id 5 | LEFT JOIN z.might_be_there_table ON mbtt_id = mft_id 6 | WHERE ft_id = 0 7 | AND ft_id2 < 10 8 | AND ft_id3 >= 0 9 | OR ft_id4 <= ft_id3 10 | OR ft_id5 = 'TEXT' 11 | AND ft_id5 = '"text with double quotes"' 12 | OR ft_id6 LIKE '%t' 13 | AND ft_id7 ILIKE '%small' 14 | OR ft_id6 LIKE 't' 15 | AND ft_id7 ILIKE 'small' 16 | AND ft_id8 = (1 + 3) 17 | AND ft_id9 = myArr[0] 18 | LIMIT 1 ; -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/query_with_join.sql: -------------------------------------------------------------------------------- 1 | SELECT ft_id 2 | FROM t.my_fancy_table 3 | JOIN a.here on b.id = c.id 4 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/query_with_left_join.sql: -------------------------------------------------------------------------------- 1 | SELECT ft_id 2 | FROM t.my_fancy_table 3 | LEFT JOIN a.here on b.id = c.id 4 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/query_with_many_joins.sql: -------------------------------------------------------------------------------- 1 | SELECT ft_id 2 | FROM t.my_fancy_table 3 | LEFT JOIN a.here on b.id = c.id 4 | JOIN d.here on e.id = f.id -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/random.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- RANDOM 3 | -- Test the random function 4 | -- 5 | 6 | -- count the number of tuples originally, should be 1000 7 | SELECT count(*) FROM onek; 8 | 9 | -- pick three random rows, they shouldn't match 10 | (SELECT unique1 AS random 11 | FROM onek ORDER BY random() LIMIT 1) 12 | INTERSECT 13 | (SELECT unique1 AS random 14 | FROM onek ORDER BY random() LIMIT 1) 15 | INTERSECT 16 | (SELECT unique1 AS random 17 | FROM onek ORDER BY random() LIMIT 1); 18 | 19 | -- count roughly 1/10 of the tuples 20 | SELECT count(*) AS random INTO RANDOM_TBL 21 | FROM onek WHERE random() < 1.0/10; 22 | 23 | -- select again, the count should be different 24 | INSERT INTO RANDOM_TBL (random) 25 | SELECT count(*) 26 | FROM onek WHERE random() < 1.0/10; 27 | 28 | -- select again, the count should be different 29 | INSERT INTO RANDOM_TBL (random) 30 | SELECT count(*) 31 | FROM onek WHERE random() < 1.0/10; 32 | 33 | -- select again, the count should be different 34 | INSERT INTO RANDOM_TBL (random) 35 | SELECT count(*) 36 | FROM onek WHERE random() < 1.0/10; 37 | 38 | -- now test that they are different counts 39 | SELECT random, count(random) FROM RANDOM_TBL 40 | GROUP BY random HAVING count(random) > 3; 41 | 42 | SELECT AVG(random) FROM RANDOM_TBL 43 | HAVING AVG(random) NOT BETWEEN 80 AND 120; 44 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/regex.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- Regular expression tests 3 | -- 4 | 5 | -- Don't want to have to double backslashes in regexes 6 | set standard_conforming_strings = on; 7 | 8 | -- Test simple quantified backrefs 9 | select 'bbbbb' ~ '^([bc])\1*$' as t; 10 | select 'ccc' ~ '^([bc])\1*$' as t; 11 | select 'xxx' ~ '^([bc])\1*$' as f; 12 | select 'bbc' ~ '^([bc])\1*$' as f; 13 | select 'b' ~ '^([bc])\1*$' as t; 14 | 15 | -- Test quantified backref within a larger expression 16 | select 'abc abc abc' ~ '^(\w+)( \1)+$' as t; 17 | select 'abc abd abc' ~ '^(\w+)( \1)+$' as f; 18 | select 'abc abc abd' ~ '^(\w+)( \1)+$' as f; 19 | select 'abc abc abc' ~ '^(.+)( \1)+$' as t; 20 | select 'abc abd abc' ~ '^(.+)( \1)+$' as f; 21 | select 'abc abc abd' ~ '^(.+)( \1)+$' as f; 22 | 23 | -- Test some cases that crashed in 9.2beta1 due to pmatch[] array overrun 24 | select substring('asd TO foo' from ' TO (([a-z0-9._]+|"([^"]+|"")+")+)'); 25 | select substring('a' from '((a))+'); 26 | select substring('a' from '((a)+)'); 27 | 28 | -- Test conversion of regex patterns to indexable conditions 29 | explain (costs off) select * from pg_proc where proname ~ 'abc'; 30 | explain (costs off) select * from pg_proc where proname ~ '^abc'; 31 | explain (costs off) select * from pg_proc where proname ~ '^abc$'; 32 | explain (costs off) select * from pg_proc where proname ~ '^abcd*e'; 33 | explain (costs off) select * from pg_proc where proname ~ '^abc+d'; 34 | explain (costs off) select * from pg_proc where proname ~ '^(abc)(def)'; 35 | explain (costs off) select * from pg_proc where proname ~ '^(abc)$'; 36 | explain (costs off) select * from pg_proc where proname ~ '^(abc)?d'; 37 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/reltime.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- RELTIME 3 | -- 4 | 5 | CREATE TABLE RELTIME_TBL (f1 reltime); 6 | 7 | INSERT INTO RELTIME_TBL (f1) VALUES ('@ 1 minute'); 8 | 9 | INSERT INTO RELTIME_TBL (f1) VALUES ('@ 5 hour'); 10 | 11 | INSERT INTO RELTIME_TBL (f1) VALUES ('@ 10 day'); 12 | 13 | INSERT INTO RELTIME_TBL (f1) VALUES ('@ 34 year'); 14 | 15 | INSERT INTO RELTIME_TBL (f1) VALUES ('@ 3 months'); 16 | 17 | INSERT INTO RELTIME_TBL (f1) VALUES ('@ 14 seconds ago'); 18 | 19 | 20 | -- badly formatted reltimes 21 | INSERT INTO RELTIME_TBL (f1) VALUES ('badly formatted reltime'); 22 | 23 | INSERT INTO RELTIME_TBL (f1) VALUES ('@ 30 eons ago'); 24 | 25 | -- test reltime operators 26 | 27 | SELECT '' AS six, * FROM RELTIME_TBL; 28 | 29 | SELECT '' AS five, * FROM RELTIME_TBL 30 | WHERE RELTIME_TBL.f1 <> reltime '@ 10 days'; 31 | 32 | SELECT '' AS three, * FROM RELTIME_TBL 33 | WHERE RELTIME_TBL.f1 <= reltime '@ 5 hours'; 34 | 35 | SELECT '' AS three, * FROM RELTIME_TBL 36 | WHERE RELTIME_TBL.f1 < reltime '@ 1 day'; 37 | 38 | SELECT '' AS one, * FROM RELTIME_TBL 39 | WHERE RELTIME_TBL.f1 = reltime '@ 34 years'; 40 | 41 | SELECT '' AS two, * FROM RELTIME_TBL 42 | WHERE RELTIME_TBL.f1 >= reltime '@ 1 month'; 43 | 44 | SELECT '' AS five, * FROM RELTIME_TBL 45 | WHERE RELTIME_TBL.f1 > reltime '@ 3 seconds ago'; 46 | 47 | SELECT '' AS fifteen, r1.*, r2.* 48 | FROM RELTIME_TBL r1, RELTIME_TBL r2 49 | WHERE r1.f1 > r2.f1 50 | ORDER BY r1.f1, r2.f1; 51 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/returning.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- Test INSERT/UPDATE/DELETE RETURNING 3 | -- 4 | 5 | -- Simple cases 6 | 7 | CREATE TEMP TABLE foo (f1 serial, f2 text, f3 int default 42); 8 | 9 | INSERT INTO foo (f2,f3) 10 | VALUES ('test', DEFAULT), ('More', 11), (upper('more'), 7+9) 11 | RETURNING *, f1+f3 AS sum; 12 | 13 | SELECT * FROM foo; 14 | 15 | UPDATE foo SET f2 = lower(f2), f3 = DEFAULT RETURNING foo.*, f1+f3 AS sum13; 16 | 17 | SELECT * FROM foo; 18 | 19 | DELETE FROM foo WHERE f1 > 2 RETURNING f3, f2, f1, least(f1,f3); 20 | 21 | SELECT * FROM foo; 22 | 23 | -- Subplans and initplans in the RETURNING list 24 | 25 | INSERT INTO foo SELECT f1+10, f2, f3+99 FROM foo 26 | RETURNING *, f1+112 IN (SELECT q1 FROM int8_tbl) AS subplan, 27 | EXISTS(SELECT * FROM int4_tbl) AS initplan; 28 | 29 | UPDATE foo SET f3 = f3 * 2 30 | WHERE f1 > 10 31 | RETURNING *, f1+112 IN (SELECT q1 FROM int8_tbl) AS subplan, 32 | EXISTS(SELECT * FROM int4_tbl) AS initplan; 33 | 34 | DELETE FROM foo 35 | WHERE f1 > 10 36 | RETURNING *, f1+112 IN (SELECT q1 FROM int8_tbl) AS subplan, 37 | EXISTS(SELECT * FROM int4_tbl) AS initplan; 38 | 39 | -- Joins 40 | 41 | UPDATE foo SET f3 = f3*2 42 | FROM int4_tbl i 43 | WHERE foo.f1 + 123455 = i.f1 44 | RETURNING foo.*, i.f1 as "i.f1"; 45 | 46 | SELECT * FROM foo; 47 | 48 | DELETE FROM foo 49 | USING int4_tbl i 50 | WHERE foo.f1 + 123455 = i.f1 51 | RETURNING foo.*, i.f1 as "i.f1"; 52 | 53 | SELECT * FROM foo; 54 | 55 | -- Check inheritance cases 56 | 57 | CREATE TEMP TABLE foochild (fc int) INHERITS (foo); 58 | 59 | INSERT INTO foochild VALUES(123,'child',999,-123); 60 | 61 | ALTER TABLE foo ADD COLUMN f4 int8 DEFAULT 99; 62 | 63 | SELECT * FROM foo; 64 | SELECT * FROM foochild; 65 | 66 | UPDATE foo SET f4 = f4 + f3 WHERE f4 = 99 RETURNING *; 67 | 68 | SELECT * FROM foo; 69 | SELECT * FROM foochild; 70 | 71 | UPDATE foo SET f3 = f3*2 72 | FROM int8_tbl i 73 | WHERE foo.f1 = i.q2 74 | RETURNING *; 75 | 76 | SELECT * FROM foo; 77 | SELECT * FROM foochild; 78 | 79 | DELETE FROM foo 80 | USING int8_tbl i 81 | WHERE foo.f1 = i.q2 82 | RETURNING *; 83 | 84 | SELECT * FROM foo; 85 | SELECT * FROM foochild; 86 | 87 | DROP TABLE foochild; 88 | 89 | -- Rules and views 90 | 91 | CREATE TEMP VIEW voo AS SELECT f1, f2 FROM foo; 92 | 93 | CREATE RULE voo_i AS ON INSERT TO voo DO INSTEAD 94 | INSERT INTO foo VALUES(new.*, 57); 95 | 96 | INSERT INTO voo VALUES(11,'zit'); 97 | -- fails: 98 | INSERT INTO voo VALUES(12,'zoo') RETURNING *, f1*2; 99 | 100 | -- fails, incompatible list: 101 | CREATE OR REPLACE RULE voo_i AS ON INSERT TO voo DO INSTEAD 102 | INSERT INTO foo VALUES(new.*, 57) RETURNING *; 103 | 104 | CREATE OR REPLACE RULE voo_i AS ON INSERT TO voo DO INSTEAD 105 | INSERT INTO foo VALUES(new.*, 57) RETURNING f1, f2; 106 | 107 | -- should still work 108 | INSERT INTO voo VALUES(13,'zit2'); 109 | -- works now 110 | INSERT INTO voo VALUES(14,'zoo2') RETURNING *; 111 | 112 | SELECT * FROM foo; 113 | SELECT * FROM voo; 114 | 115 | CREATE OR REPLACE RULE voo_u AS ON UPDATE TO voo DO INSTEAD 116 | UPDATE foo SET f1 = new.f1, f2 = new.f2 WHERE f1 = old.f1 117 | RETURNING f1, f2; 118 | 119 | update voo set f1 = f1 + 1 where f2 = 'zoo2'; 120 | update voo set f1 = f1 + 1 where f2 = 'zoo2' RETURNING *, f1*2; 121 | 122 | SELECT * FROM foo; 123 | SELECT * FROM voo; 124 | 125 | CREATE OR REPLACE RULE voo_d AS ON DELETE TO voo DO INSTEAD 126 | DELETE FROM foo WHERE f1 = old.f1 127 | RETURNING f1, f2; 128 | 129 | DELETE FROM foo WHERE f1 = 13; 130 | DELETE FROM foo WHERE f2 = 'zit' RETURNING *; 131 | 132 | SELECT * FROM foo; 133 | SELECT * FROM voo; 134 | 135 | -- Try a join case 136 | 137 | CREATE TEMP TABLE joinme (f2j text, other int); 138 | INSERT INTO joinme VALUES('more', 12345); 139 | INSERT INTO joinme VALUES('zoo2', 54321); 140 | INSERT INTO joinme VALUES('other', 0); 141 | 142 | CREATE TEMP VIEW joinview AS 143 | SELECT foo.*, other FROM foo JOIN joinme ON (f2 = f2j); 144 | 145 | SELECT * FROM joinview; 146 | 147 | CREATE RULE joinview_u AS ON UPDATE TO joinview DO INSTEAD 148 | UPDATE foo SET f1 = new.f1, f3 = new.f3 149 | FROM joinme WHERE f2 = f2j AND f2 = old.f2 150 | RETURNING foo.*, other; 151 | 152 | UPDATE joinview SET f1 = f1 + 1 WHERE f3 = 57 RETURNING *, other + 1; 153 | 154 | SELECT * FROM joinview; 155 | SELECT * FROM foo; 156 | SELECT * FROM voo; 157 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/sanity_check.sql: -------------------------------------------------------------------------------- 1 | VACUUM; 2 | 3 | -- 4 | -- sanity check, if we don't have indices the test will take years to 5 | -- complete. But skip TOAST relations (since they will have varying 6 | -- names depending on the current OID counter) as well as temp tables 7 | -- of other backends (to avoid timing-dependent behavior). 8 | -- 9 | SELECT relname, relhasindex 10 | FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = relnamespace 11 | WHERE relkind = 'r' AND (nspname ~ '^pg_temp_') IS NOT TRUE 12 | ORDER BY relname; 13 | 14 | -- 15 | -- another sanity check: every system catalog that has OIDs should have 16 | -- a unique index on OID. This ensures that the OIDs will be unique, 17 | -- even after the OID counter wraps around. 18 | -- We exclude non-system tables from the check by looking at nspname. 19 | -- 20 | SELECT relname, nspname 21 | FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = relnamespace 22 | WHERE relhasoids 23 | AND ((nspname ~ '^pg_') IS NOT FALSE) 24 | AND NOT EXISTS (SELECT 1 FROM pg_index i WHERE indrelid = c.oid 25 | AND indkey[0] = -2 AND indnatts = 1 26 | AND indisunique AND indimmediate); 27 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/select_distinct.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- SELECT_DISTINCT 3 | -- 4 | 5 | -- 6 | -- awk '{print $3;}' onek.data | sort -n | uniq 7 | -- 8 | SELECT DISTINCT two FROM tmp ORDER BY 1; 9 | 10 | -- 11 | -- awk '{print $5;}' onek.data | sort -n | uniq 12 | -- 13 | SELECT DISTINCT ten FROM tmp ORDER BY 1; 14 | 15 | -- 16 | -- awk '{print $16;}' onek.data | sort -d | uniq 17 | -- 18 | SELECT DISTINCT string4 FROM tmp ORDER BY 1; 19 | 20 | -- 21 | -- awk '{print $3,$16,$5;}' onek.data | sort -d | uniq | 22 | -- sort +0n -1 +1d -2 +2n -3 23 | -- 24 | SELECT DISTINCT two, string4, ten 25 | FROM tmp 26 | ORDER BY two using <, string4 using <, ten using <; 27 | 28 | -- 29 | -- awk '{print $2;}' person.data | 30 | -- awk '{if(NF!=1){print $2;}else{print;}}' - emp.data | 31 | -- awk '{if(NF!=1){print $2;}else{print;}}' - student.data | 32 | -- awk 'BEGIN{FS=" ";}{if(NF!=1){print $5;}else{print;}}' - stud_emp.data | 33 | -- sort -n -r | uniq 34 | -- 35 | SELECT DISTINCT p.age FROM person* p ORDER BY age using >; 36 | 37 | -- 38 | -- Also, some tests of IS DISTINCT FROM, which doesn't quite deserve its 39 | -- very own regression file. 40 | -- 41 | 42 | CREATE TEMP TABLE disttable (f1 integer); 43 | INSERT INTO DISTTABLE VALUES(1); 44 | INSERT INTO DISTTABLE VALUES(2); 45 | INSERT INTO DISTTABLE VALUES(3); 46 | INSERT INTO DISTTABLE VALUES(NULL); 47 | 48 | -- basic cases 49 | SELECT f1, f1 IS DISTINCT FROM 2 as "not 2" FROM disttable; 50 | SELECT f1, f1 IS DISTINCT FROM NULL as "not null" FROM disttable; 51 | SELECT f1, f1 IS DISTINCT FROM f1 as "false" FROM disttable; 52 | SELECT f1, f1 IS DISTINCT FROM f1+1 as "not null" FROM disttable; 53 | 54 | -- check that optimizer constant-folds it properly 55 | SELECT 1 IS DISTINCT FROM 2 as "yes"; 56 | SELECT 2 IS DISTINCT FROM 2 as "no"; 57 | SELECT 2 IS DISTINCT FROM null as "yes"; 58 | SELECT null IS DISTINCT FROM null as "no"; 59 | 60 | -- negated form 61 | SELECT 1 IS NOT DISTINCT FROM 2 as "no"; 62 | SELECT 2 IS NOT DISTINCT FROM 2 as "yes"; 63 | SELECT 2 IS NOT DISTINCT FROM null as "no"; 64 | SELECT null IS NOT DISTINCT FROM null as "yes"; 65 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/select_distinct_on.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- SELECT_DISTINCT_ON 3 | -- 4 | 5 | SELECT DISTINCT ON (string4) string4, two, ten 6 | FROM tmp 7 | ORDER BY string4 using <, two using >, ten using <; 8 | 9 | -- this will fail due to conflict of ordering requirements 10 | SELECT DISTINCT ON (string4, ten) string4, two, ten 11 | FROM tmp 12 | ORDER BY string4 using <, two using <, ten using <; 13 | 14 | SELECT DISTINCT ON (string4, ten) string4, ten, two 15 | FROM tmp 16 | ORDER BY string4 using <, ten using >, two using <; 17 | 18 | -- bug #5049: early 8.4.x chokes on volatile DISTINCT ON clauses 19 | select distinct on (1) floor(random()) as r, f1 from int4_tbl order by 1,2; 20 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/select_having.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- SELECT_HAVING 3 | -- 4 | 5 | -- load test data 6 | CREATE TABLE test_having (a int, b int, c char(8), d char); 7 | INSERT INTO test_having VALUES (0, 1, 'XXXX', 'A'); 8 | INSERT INTO test_having VALUES (1, 2, 'AAAA', 'b'); 9 | INSERT INTO test_having VALUES (2, 2, 'AAAA', 'c'); 10 | INSERT INTO test_having VALUES (3, 3, 'BBBB', 'D'); 11 | INSERT INTO test_having VALUES (4, 3, 'BBBB', 'e'); 12 | INSERT INTO test_having VALUES (5, 3, 'bbbb', 'F'); 13 | INSERT INTO test_having VALUES (6, 4, 'cccc', 'g'); 14 | INSERT INTO test_having VALUES (7, 4, 'cccc', 'h'); 15 | INSERT INTO test_having VALUES (8, 4, 'CCCC', 'I'); 16 | INSERT INTO test_having VALUES (9, 4, 'CCCC', 'j'); 17 | 18 | SELECT b, c FROM test_having 19 | GROUP BY b, c HAVING count(*) = 1 ORDER BY b, c; 20 | 21 | -- HAVING is effectively equivalent to WHERE in this case 22 | SELECT b, c FROM test_having 23 | GROUP BY b, c HAVING b = 3 ORDER BY b, c; 24 | 25 | SELECT lower(c), count(c) FROM test_having 26 | GROUP BY lower(c) HAVING count(*) > 2 OR min(a) = max(a) 27 | ORDER BY lower(c); 28 | 29 | SELECT c, max(a) FROM test_having 30 | GROUP BY c HAVING count(*) > 2 OR min(a) = max(a) 31 | ORDER BY c; 32 | 33 | -- test degenerate cases involving HAVING without GROUP BY 34 | -- Per SQL spec, these should generate 0 or 1 row, even without aggregates 35 | 36 | SELECT min(a), max(a) FROM test_having HAVING min(a) = max(a); 37 | SELECT min(a), max(a) FROM test_having HAVING min(a) < max(a); 38 | 39 | -- errors: ungrouped column references 40 | SELECT a FROM test_having HAVING min(a) < max(a); 41 | SELECT 1 AS one FROM test_having HAVING a > 1; 42 | 43 | -- the really degenerate case: need not scan table at all 44 | SELECT 1 AS one FROM test_having HAVING 1 > 2; 45 | SELECT 1 AS one FROM test_having HAVING 1 < 2; 46 | 47 | -- and just to prove that we aren't scanning the table: 48 | SELECT 1 AS one FROM test_having WHERE 1/a = 1 HAVING 1 < 2; 49 | 50 | DROP TABLE test_having; 51 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/select_into.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- SELECT_INTO 3 | -- 4 | 5 | SELECT * 6 | INTO TABLE tmp1 7 | FROM onek 8 | WHERE onek.unique1 < 2; 9 | 10 | DROP TABLE tmp1; 11 | 12 | SELECT * 13 | INTO TABLE tmp1 14 | FROM onek2 15 | WHERE onek2.unique1 < 2; 16 | 17 | DROP TABLE tmp1; 18 | 19 | -- 20 | -- SELECT INTO and INSERT permission, if owner is not allowed to insert. 21 | -- 22 | CREATE SCHEMA selinto_schema; 23 | CREATE USER selinto_user; 24 | ALTER DEFAULT PRIVILEGES FOR ROLE selinto_user 25 | REVOKE INSERT ON TABLES FROM selinto_user; 26 | GRANT ALL ON SCHEMA selinto_schema TO public; 27 | 28 | SET SESSION AUTHORIZATION selinto_user; 29 | SELECT * INTO TABLE selinto_schema.tmp1 30 | FROM pg_class WHERE relname like '%a%'; -- Error 31 | SELECT oid AS clsoid, relname, relnatts + 10 AS x 32 | INTO selinto_schema.tmp2 33 | FROM pg_class WHERE relname like '%b%'; -- Error 34 | CREATE TABLE selinto_schema.tmp3 (a,b,c) 35 | AS SELECT oid,relname,relacl FROM pg_class 36 | WHERE relname like '%c%'; -- Error 37 | RESET SESSION AUTHORIZATION; 38 | 39 | ALTER DEFAULT PRIVILEGES FOR ROLE selinto_user 40 | GRANT INSERT ON TABLES TO selinto_user; 41 | 42 | SET SESSION AUTHORIZATION selinto_user; 43 | SELECT * INTO TABLE selinto_schema.tmp1 44 | FROM pg_class WHERE relname like '%a%'; -- OK 45 | SELECT oid AS clsoid, relname, relnatts + 10 AS x 46 | INTO selinto_schema.tmp2 47 | FROM pg_class WHERE relname like '%b%'; -- OK 48 | CREATE TABLE selinto_schema.tmp3 (a,b,c) 49 | AS SELECT oid,relname,relacl FROM pg_class 50 | WHERE relname like '%c%'; -- OK 51 | RESET SESSION AUTHORIZATION; 52 | 53 | DROP SCHEMA selinto_schema CASCADE; 54 | DROP USER selinto_user; 55 | 56 | -- 57 | -- CREATE TABLE AS/SELECT INTO as last command in a SQL function 58 | -- have been known to cause problems 59 | -- 60 | CREATE FUNCTION make_table() RETURNS VOID 61 | AS $$ 62 | CREATE TABLE created_table AS SELECT * FROM int8_tbl; 63 | $$ LANGUAGE SQL; 64 | 65 | SELECT make_table(); 66 | 67 | SELECT * FROM created_table; 68 | 69 | DROP TABLE created_table; 70 | 71 | -- 72 | -- Disallowed uses of SELECT ... INTO. All should fail 73 | -- 74 | DECLARE foo CURSOR FOR SELECT 1 INTO b; 75 | COPY (SELECT 1 INTO frak UNION SELECT 2) TO 'blob'; 76 | SELECT * FROM (SELECT 1 INTO f) bar; 77 | CREATE VIEW foo AS SELECT 1 INTO b; 78 | INSERT INTO b SELECT 1 INTO f; 79 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/simple_sql.sql: -------------------------------------------------------------------------------- 1 | select c_id 2 | from zal_data.commission 3 | where c_status = 'NEW' 4 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/sql_ascii.sql: -------------------------------------------------------------------------------- 1 | drop table computer_terms; 2 | create table computer_terms(term text, category text, comments char(16)); 3 | create index computer_terms_index1 on computer_terms using btree(term); 4 | create index computer_terms_index2 on computer_terms using btree(category); 5 | insert into computer_terms values('computer display', 'X-A01-Y', 'a comment 1'); 6 | insert into computer_terms values('computer graphics', 'T-B01-Y', 'a comment 2'); 7 | insert into computer_terms values('computer programmer', 'S-Z01-Y', 'a comment 3'); 8 | vacuum computer_terms; 9 | select * from computer_terms; 10 | select * from computer_terms where category = 'X-A01-Y'; 11 | select * from computer_terms where category ~* 'x-a01-y'; 12 | select * from computer_terms where category like '_-A01-_'; 13 | select * from computer_terms where category like '_-A%'; 14 | select * from computer_terms where term ~ 'computer [dg]'; 15 | select * from computer_terms where term ~* 'computer [DG]'; 16 | select *,character_length(term) from computer_terms; 17 | select *,octet_length(term) from computer_terms; 18 | select *,position('s' in term) from computer_terms; 19 | select *,substring(term from 10 for 4) from computer_terms; 20 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/stats.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- Test Statistics Collector 3 | -- 4 | -- Must be run after tenk2 has been created (by create_table), 5 | -- populated (by create_misc) and indexed (by create_index). 6 | -- 7 | 8 | -- conditio sine qua non 9 | SHOW track_counts; -- must be on 10 | 11 | -- ensure that both seqscan and indexscan plans are allowed 12 | SET enable_seqscan TO on; 13 | SET enable_indexscan TO on; 14 | -- for the moment, we don't want index-only scans here 15 | SET enable_indexonlyscan TO off; 16 | 17 | -- wait to let any prior tests finish dumping out stats; 18 | -- else our messages might get lost due to contention 19 | SELECT pg_sleep(2.0); 20 | 21 | -- save counters 22 | CREATE TEMP TABLE prevstats AS 23 | SELECT t.seq_scan, t.seq_tup_read, t.idx_scan, t.idx_tup_fetch, 24 | (b.heap_blks_read + b.heap_blks_hit) AS heap_blks, 25 | (b.idx_blks_read + b.idx_blks_hit) AS idx_blks 26 | FROM pg_catalog.pg_stat_user_tables AS t, 27 | pg_catalog.pg_statio_user_tables AS b 28 | WHERE t.relname='tenk2' AND b.relname='tenk2'; 29 | 30 | -- function to wait for counters to advance 31 | create function wait_for_stats() returns void as $$ 32 | declare 33 | start_time timestamptz := clock_timestamp(); 34 | updated bool; 35 | begin 36 | -- we don't want to wait forever; loop will exit after 30 seconds 37 | for i in 1 .. 300 loop 38 | 39 | -- check to see if indexscan has been sensed 40 | SELECT (st.idx_scan >= pr.idx_scan + 1) INTO updated 41 | FROM pg_stat_user_tables AS st, pg_class AS cl, prevstats AS pr 42 | WHERE st.relname='tenk2' AND cl.relname='tenk2'; 43 | 44 | exit when updated; 45 | 46 | -- wait a little 47 | perform pg_sleep(0.1); 48 | 49 | -- reset stats snapshot so we can test again 50 | perform pg_stat_clear_snapshot(); 51 | 52 | end loop; 53 | 54 | -- report time waited in postmaster log (where it won't change test output) 55 | raise log 'wait_for_stats delayed % seconds', 56 | extract(epoch from clock_timestamp() - start_time); 57 | end 58 | $$ language plpgsql; 59 | 60 | -- do a seqscan 61 | SELECT count(*) FROM tenk2; 62 | -- do an indexscan 63 | SELECT count(*) FROM tenk2 WHERE unique1 = 1; 64 | 65 | -- force the rate-limiting logic in pgstat_report_tabstat() to time out 66 | -- and send a message 67 | SELECT pg_sleep(1.0); 68 | 69 | -- wait for stats collector to update 70 | SELECT wait_for_stats(); 71 | 72 | -- check effects 73 | SELECT st.seq_scan >= pr.seq_scan + 1, 74 | st.seq_tup_read >= pr.seq_tup_read + cl.reltuples, 75 | st.idx_scan >= pr.idx_scan + 1, 76 | st.idx_tup_fetch >= pr.idx_tup_fetch + 1 77 | FROM pg_stat_user_tables AS st, pg_class AS cl, prevstats AS pr 78 | WHERE st.relname='tenk2' AND cl.relname='tenk2'; 79 | SELECT st.heap_blks_read + st.heap_blks_hit >= pr.heap_blks + cl.relpages, 80 | st.idx_blks_read + st.idx_blks_hit >= pr.idx_blks + 1 81 | FROM pg_statio_user_tables AS st, pg_class AS cl, prevstats AS pr 82 | WHERE st.relname='tenk2' AND cl.relname='tenk2'; 83 | 84 | -- End of Stats Test 85 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/temp.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- TEMP 3 | -- Test temp relations and indexes 4 | -- 5 | 6 | -- test temp table/index masking 7 | 8 | CREATE TABLE temptest(col int); 9 | 10 | CREATE INDEX i_temptest ON temptest(col); 11 | 12 | CREATE TEMP TABLE temptest(tcol int); 13 | 14 | CREATE INDEX i_temptest ON temptest(tcol); 15 | 16 | SELECT * FROM temptest; 17 | 18 | DROP INDEX i_temptest; 19 | 20 | DROP TABLE temptest; 21 | 22 | SELECT * FROM temptest; 23 | 24 | DROP INDEX i_temptest; 25 | 26 | DROP TABLE temptest; 27 | 28 | -- test temp table selects 29 | 30 | CREATE TABLE temptest(col int); 31 | 32 | INSERT INTO temptest VALUES (1); 33 | 34 | CREATE TEMP TABLE temptest(tcol float); 35 | 36 | INSERT INTO temptest VALUES (2.1); 37 | 38 | SELECT * FROM temptest; 39 | 40 | DROP TABLE temptest; 41 | 42 | SELECT * FROM temptest; 43 | 44 | DROP TABLE temptest; 45 | 46 | -- test temp table deletion 47 | 48 | CREATE TEMP TABLE temptest(col int); 49 | 50 | \c 51 | 52 | SELECT * FROM temptest; 53 | 54 | -- Test ON COMMIT DELETE ROWS 55 | 56 | CREATE TEMP TABLE temptest(col int) ON COMMIT DELETE ROWS; 57 | 58 | BEGIN; 59 | INSERT INTO temptest VALUES (1); 60 | INSERT INTO temptest VALUES (2); 61 | 62 | SELECT * FROM temptest; 63 | COMMIT; 64 | 65 | SELECT * FROM temptest; 66 | 67 | DROP TABLE temptest; 68 | 69 | BEGIN; 70 | CREATE TEMP TABLE temptest(col) ON COMMIT DELETE ROWS AS SELECT 1; 71 | 72 | SELECT * FROM temptest; 73 | COMMIT; 74 | 75 | SELECT * FROM temptest; 76 | 77 | DROP TABLE temptest; 78 | 79 | -- Test ON COMMIT DROP 80 | 81 | BEGIN; 82 | 83 | CREATE TEMP TABLE temptest(col int) ON COMMIT DROP; 84 | 85 | INSERT INTO temptest VALUES (1); 86 | INSERT INTO temptest VALUES (2); 87 | 88 | SELECT * FROM temptest; 89 | COMMIT; 90 | 91 | SELECT * FROM temptest; 92 | 93 | BEGIN; 94 | CREATE TEMP TABLE temptest(col) ON COMMIT DROP AS SELECT 1; 95 | 96 | SELECT * FROM temptest; 97 | COMMIT; 98 | 99 | SELECT * FROM temptest; 100 | 101 | -- ON COMMIT is only allowed for TEMP 102 | 103 | CREATE TABLE temptest(col int) ON COMMIT DELETE ROWS; 104 | CREATE TABLE temptest(col) ON COMMIT DELETE ROWS AS SELECT 1; 105 | 106 | -- Test foreign keys 107 | BEGIN; 108 | CREATE TEMP TABLE temptest1(col int PRIMARY KEY); 109 | CREATE TEMP TABLE temptest2(col int REFERENCES temptest1) 110 | ON COMMIT DELETE ROWS; 111 | INSERT INTO temptest1 VALUES (1); 112 | INSERT INTO temptest2 VALUES (1); 113 | COMMIT; 114 | SELECT * FROM temptest1; 115 | SELECT * FROM temptest2; 116 | 117 | BEGIN; 118 | CREATE TEMP TABLE temptest3(col int PRIMARY KEY) ON COMMIT DELETE ROWS; 119 | CREATE TEMP TABLE temptest4(col int REFERENCES temptest3); 120 | COMMIT; 121 | 122 | -- Test manipulation of temp schema's placement in search path 123 | 124 | create table public.whereami (f1 text); 125 | insert into public.whereami values ('public'); 126 | 127 | create temp table whereami (f1 text); 128 | insert into whereami values ('temp'); 129 | 130 | create function public.whoami() returns text 131 | as $$select 'public'::text$$ language sql; 132 | 133 | create function pg_temp.whoami() returns text 134 | as $$select 'temp'::text$$ language sql; 135 | 136 | -- default should have pg_temp implicitly first, but only for tables 137 | select * from whereami; 138 | select whoami(); 139 | 140 | -- can list temp first explicitly, but it still doesn't affect functions 141 | set search_path = pg_temp, public; 142 | select * from whereami; 143 | select whoami(); 144 | 145 | -- or put it last for security 146 | set search_path = public, pg_temp; 147 | select * from whereami; 148 | select whoami(); 149 | 150 | -- you can invoke a temp function explicitly, though 151 | select pg_temp.whoami(); 152 | 153 | drop table public.whereami; 154 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/text.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- TEXT 3 | -- 4 | 5 | SELECT text 'this is a text string' = text 'this is a text string' AS true; 6 | 7 | SELECT text 'this is a text string' = text 'this is a text strin' AS false; 8 | 9 | CREATE TABLE TEXT_TBL (f1 text); 10 | 11 | INSERT INTO TEXT_TBL VALUES ('doh!'); 12 | INSERT INTO TEXT_TBL VALUES ('hi de ho neighbor'); 13 | 14 | SELECT '' AS two, * FROM TEXT_TBL; 15 | 16 | -- As of 8.3 we have removed most implicit casts to text, so that for example 17 | -- this no longer works: 18 | 19 | select length(42); 20 | 21 | -- But as a special exception for usability's sake, we still allow implicit 22 | -- casting to text in concatenations, so long as the other input is text or 23 | -- an unknown literal. So these work: 24 | 25 | select 'four: '::text || 2+2; 26 | select 'four: ' || 2+2; 27 | 28 | -- but not this: 29 | 30 | select 3 || 4.0; 31 | 32 | /* 33 | * various string functions 34 | */ 35 | select concat('one'); 36 | select concat(1,2,3,'hello',true, false, to_date('20100309','YYYYMMDD')); 37 | select concat_ws('#','one'); 38 | select concat_ws('#',1,2,3,'hello',true, false, to_date('20100309','YYYYMMDD')); 39 | select concat_ws(',',10,20,null,30); 40 | select concat_ws('',10,20,null,30); 41 | select concat_ws(NULL,10,20,null,30) is null; 42 | select reverse('abcde'); 43 | select i, left('ahoj', i), right('ahoj', i) from generate_series(-5, 5) t(i) order by i; 44 | select quote_literal(''); 45 | select quote_literal('abc'''); 46 | select quote_literal(e'\\'); 47 | 48 | /* 49 | * format 50 | */ 51 | select format(NULL); 52 | select format('Hello'); 53 | select format('Hello %s', 'World'); 54 | select format('Hello %%'); 55 | select format('Hello %%%%'); 56 | -- should fail 57 | select format('Hello %s %s', 'World'); 58 | select format('Hello %s'); 59 | select format('Hello %x', 20); 60 | -- check literal and sql identifiers 61 | select format('INSERT INTO %I VALUES(%L,%L)', 'mytab', 10, 'Hello'); 62 | select format('%s%s%s','Hello', NULL,'World'); 63 | select format('INSERT INTO %I VALUES(%L,%L)', 'mytab', 10, NULL); 64 | select format('INSERT INTO %I VALUES(%L,%L)', 'mytab', NULL, 'Hello'); 65 | -- should fail, sql identifier cannot be NULL 66 | select format('INSERT INTO %I VALUES(%L,%L)', NULL, 10, 'Hello'); 67 | -- check positional placeholders 68 | select format('%1$s %3$s', 1, 2, 3); 69 | select format('%1$s %12$s', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12); 70 | -- should fail 71 | select format('%1$s %4$s', 1, 2, 3); 72 | select format('%1$s %13$s', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12); 73 | select format('%1s', 1); 74 | select format('%1$', 1); 75 | select format('%1$1', 1); 76 | --checkk mix of positional and ordered placeholders 77 | select format('Hello %s %1$s %s', 'World', 'Hello again'); 78 | select format('Hello %s %s, %2$s %2$s', 'World', 'Hello again'); 79 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/time.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- TIME 3 | -- 4 | 5 | CREATE TABLE TIME_TBL (f1 time(2)); 6 | 7 | INSERT INTO TIME_TBL VALUES ('00:00'); 8 | INSERT INTO TIME_TBL VALUES ('01:00'); 9 | -- as of 7.4, timezone spec should be accepted and ignored 10 | INSERT INTO TIME_TBL VALUES ('02:03 PST'); 11 | INSERT INTO TIME_TBL VALUES ('11:59 EDT'); 12 | INSERT INTO TIME_TBL VALUES ('12:00'); 13 | INSERT INTO TIME_TBL VALUES ('12:01'); 14 | INSERT INTO TIME_TBL VALUES ('23:59'); 15 | INSERT INTO TIME_TBL VALUES ('11:59:59.99 PM'); 16 | 17 | INSERT INTO TIME_TBL VALUES ('2003-03-07 15:36:39 America/New_York'); 18 | INSERT INTO TIME_TBL VALUES ('2003-07-07 15:36:39 America/New_York'); 19 | -- this should fail (the timezone offset is not known) 20 | INSERT INTO TIME_TBL VALUES ('15:36:39 America/New_York'); 21 | 22 | 23 | SELECT f1 AS "Time" FROM TIME_TBL; 24 | 25 | SELECT f1 AS "Three" FROM TIME_TBL WHERE f1 < '05:06:07'; 26 | 27 | SELECT f1 AS "Five" FROM TIME_TBL WHERE f1 > '05:06:07'; 28 | 29 | SELECT f1 AS "None" FROM TIME_TBL WHERE f1 < '00:00'; 30 | 31 | SELECT f1 AS "Eight" FROM TIME_TBL WHERE f1 >= '00:00'; 32 | 33 | -- 34 | -- TIME simple math 35 | -- 36 | -- We now make a distinction between time and intervals, 37 | -- and adding two times together makes no sense at all. 38 | -- Leave in one query to show that it is rejected, 39 | -- and do the rest of the testing in horology.sql 40 | -- where we do mixed-type arithmetic. - thomas 2000-12-02 41 | 42 | SELECT f1 + time '00:01' AS "Illegal" FROM TIME_TBL; 43 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/timetz.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- TIMETZ 3 | -- 4 | 5 | CREATE TABLE TIMETZ_TBL (f1 time(2) with time zone); 6 | 7 | INSERT INTO TIMETZ_TBL VALUES ('00:01 PDT'); 8 | INSERT INTO TIMETZ_TBL VALUES ('01:00 PDT'); 9 | INSERT INTO TIMETZ_TBL VALUES ('02:03 PDT'); 10 | INSERT INTO TIMETZ_TBL VALUES ('07:07 PST'); 11 | INSERT INTO TIMETZ_TBL VALUES ('08:08 EDT'); 12 | INSERT INTO TIMETZ_TBL VALUES ('11:59 PDT'); 13 | INSERT INTO TIMETZ_TBL VALUES ('12:00 PDT'); 14 | INSERT INTO TIMETZ_TBL VALUES ('12:01 PDT'); 15 | INSERT INTO TIMETZ_TBL VALUES ('23:59 PDT'); 16 | INSERT INTO TIMETZ_TBL VALUES ('11:59:59.99 PM PDT'); 17 | 18 | INSERT INTO TIMETZ_TBL VALUES ('2003-03-07 15:36:39 America/New_York'); 19 | INSERT INTO TIMETZ_TBL VALUES ('2003-07-07 15:36:39 America/New_York'); 20 | -- this should fail (the timezone offset is not known) 21 | INSERT INTO TIMETZ_TBL VALUES ('15:36:39 America/New_York'); 22 | 23 | SELECT f1 AS "Time TZ" FROM TIMETZ_TBL; 24 | 25 | SELECT f1 AS "Three" FROM TIMETZ_TBL WHERE f1 < '05:06:07-07'; 26 | 27 | SELECT f1 AS "Seven" FROM TIMETZ_TBL WHERE f1 > '05:06:07-07'; 28 | 29 | SELECT f1 AS "None" FROM TIMETZ_TBL WHERE f1 < '00:00-07'; 30 | 31 | SELECT f1 AS "Ten" FROM TIMETZ_TBL WHERE f1 >= '00:00-07'; 32 | 33 | -- 34 | -- TIME simple math 35 | -- 36 | -- We now make a distinction between time and intervals, 37 | -- and adding two times together makes no sense at all. 38 | -- Leave in one query to show that it is rejected, 39 | -- and do the rest of the testing in horology.sql 40 | -- where we do mixed-type arithmetic. - thomas 2000-12-02 41 | 42 | SELECT f1 + time with time zone '00:01' AS "Illegal" FROM TIMETZ_TBL; 43 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/tinterval.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- TINTERVAL 3 | -- 4 | 5 | CREATE TABLE TINTERVAL_TBL (f1 tinterval); 6 | 7 | -- Should accept any abstime, 8 | -- so do not bother with extensive testing of values 9 | 10 | INSERT INTO TINTERVAL_TBL (f1) 11 | VALUES ('["-infinity" "infinity"]'); 12 | 13 | INSERT INTO TINTERVAL_TBL (f1) 14 | VALUES ('["May 10, 1947 23:59:12" "Jan 14, 1973 03:14:21"]'); 15 | 16 | INSERT INTO TINTERVAL_TBL (f1) 17 | VALUES ('["Sep 4, 1983 23:59:12" "Oct 4, 1983 23:59:12"]'); 18 | 19 | INSERT INTO TINTERVAL_TBL (f1) 20 | VALUES ('["epoch" "Mon May 1 00:30:30 1995"]'); 21 | 22 | INSERT INTO TINTERVAL_TBL (f1) 23 | VALUES ('["Feb 15 1990 12:15:03" "2001-09-23 11:12:13"]'); 24 | 25 | 26 | -- badly formatted tintervals 27 | INSERT INTO TINTERVAL_TBL (f1) 28 | VALUES ('["bad time specifications" ""]'); 29 | 30 | INSERT INTO TINTERVAL_TBL (f1) 31 | VALUES ('["" "infinity"]'); 32 | 33 | -- test tinterval operators 34 | 35 | SELECT '' AS five, * FROM TINTERVAL_TBL; 36 | 37 | -- length == 38 | SELECT '' AS one, t.* 39 | FROM TINTERVAL_TBL t 40 | WHERE t.f1 #= '@ 1 months'; 41 | 42 | -- length <> 43 | SELECT '' AS three, t.* 44 | FROM TINTERVAL_TBL t 45 | WHERE t.f1 #<> '@ 1 months'; 46 | 47 | -- length < 48 | SELECT '' AS zero, t.* 49 | FROM TINTERVAL_TBL t 50 | WHERE t.f1 #< '@ 1 month'; 51 | 52 | -- length <= 53 | SELECT '' AS one, t.* 54 | FROM TINTERVAL_TBL t 55 | WHERE t.f1 #<= '@ 1 month'; 56 | 57 | -- length > 58 | SELECT '' AS three, t.* 59 | FROM TINTERVAL_TBL t 60 | WHERE t.f1 #> '@ 1 year'; 61 | 62 | -- length >= 63 | SELECT '' AS three, t.* 64 | FROM TINTERVAL_TBL t 65 | WHERE t.f1 #>= '@ 3 years'; 66 | 67 | -- overlaps 68 | SELECT '' AS three, t1.* 69 | FROM TINTERVAL_TBL t1 70 | WHERE t1.f1 && 71 | tinterval '["Aug 15 14:23:19 1983" "Sep 16 14:23:19 1983"]'; 72 | 73 | SELECT '' AS five, t1.f1, t2.f1 74 | FROM TINTERVAL_TBL t1, TINTERVAL_TBL t2 75 | WHERE t1.f1 && t2.f1 and 76 | t1.f1 = t2.f1 77 | ORDER BY t1.f1, t2.f1; 78 | 79 | SELECT '' AS fourteen, t1.f1 AS interval1, t2.f1 AS interval2 80 | FROM TINTERVAL_TBL t1, TINTERVAL_TBL t2 81 | WHERE t1.f1 && t2.f1 and not t1.f1 = t2.f1 82 | ORDER BY interval1, interval2; 83 | 84 | -- contains 85 | SELECT '' AS five, t1.f1 86 | FROM TINTERVAL_TBL t1 87 | WHERE not t1.f1 << 88 | tinterval '["Aug 15 14:23:19 1980" "Sep 16 14:23:19 1990"]' 89 | ORDER BY t1.f1; 90 | 91 | -- make time interval 92 | SELECT '' AS three, t1.f1 93 | FROM TINTERVAL_TBL t1 94 | WHERE t1.f1 && 95 | (abstime 'Aug 15 14:23:19 1983' <#> 96 | abstime 'Sep 16 14:23:19 1983') 97 | ORDER BY t1.f1; 98 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/tsdicts.sql: -------------------------------------------------------------------------------- 1 | --Test text search dictionaries and configurations 2 | 3 | -- Test ISpell dictionary with ispell affix file 4 | CREATE TEXT SEARCH DICTIONARY ispell ( 5 | Template=ispell, 6 | DictFile=ispell_sample, 7 | AffFile=ispell_sample 8 | ); 9 | 10 | SELECT ts_lexize('ispell', 'skies'); 11 | SELECT ts_lexize('ispell', 'bookings'); 12 | SELECT ts_lexize('ispell', 'booking'); 13 | SELECT ts_lexize('ispell', 'foot'); 14 | SELECT ts_lexize('ispell', 'foots'); 15 | SELECT ts_lexize('ispell', 'rebookings'); 16 | SELECT ts_lexize('ispell', 'rebooking'); 17 | SELECT ts_lexize('ispell', 'rebook'); 18 | SELECT ts_lexize('ispell', 'unbookings'); 19 | SELECT ts_lexize('ispell', 'unbooking'); 20 | SELECT ts_lexize('ispell', 'unbook'); 21 | 22 | SELECT ts_lexize('ispell', 'footklubber'); 23 | SELECT ts_lexize('ispell', 'footballklubber'); 24 | SELECT ts_lexize('ispell', 'ballyklubber'); 25 | SELECT ts_lexize('ispell', 'footballyklubber'); 26 | 27 | -- Test ISpell dictionary with hunspell affix file 28 | CREATE TEXT SEARCH DICTIONARY hunspell ( 29 | Template=ispell, 30 | DictFile=ispell_sample, 31 | AffFile=hunspell_sample 32 | ); 33 | 34 | SELECT ts_lexize('hunspell', 'skies'); 35 | SELECT ts_lexize('hunspell', 'bookings'); 36 | SELECT ts_lexize('hunspell', 'booking'); 37 | SELECT ts_lexize('hunspell', 'foot'); 38 | SELECT ts_lexize('hunspell', 'foots'); 39 | SELECT ts_lexize('hunspell', 'rebookings'); 40 | SELECT ts_lexize('hunspell', 'rebooking'); 41 | SELECT ts_lexize('hunspell', 'rebook'); 42 | SELECT ts_lexize('hunspell', 'unbookings'); 43 | SELECT ts_lexize('hunspell', 'unbooking'); 44 | SELECT ts_lexize('hunspell', 'unbook'); 45 | 46 | SELECT ts_lexize('hunspell', 'footklubber'); 47 | SELECT ts_lexize('hunspell', 'footballklubber'); 48 | SELECT ts_lexize('hunspell', 'ballyklubber'); 49 | SELECT ts_lexize('hunspell', 'footballyklubber'); 50 | 51 | -- Synonim dictionary 52 | CREATE TEXT SEARCH DICTIONARY synonym ( 53 | Template=synonym, 54 | Synonyms=synonym_sample 55 | ); 56 | 57 | SELECT ts_lexize('synonym', 'PoStGrEs'); 58 | SELECT ts_lexize('synonym', 'Gogle'); 59 | SELECT ts_lexize('synonym', 'indices'); 60 | 61 | -- Create and simple test thesaurus dictionary 62 | -- More tests in configuration checks because ts_lexize() 63 | -- cannot pass more than one word to thesaurus. 64 | CREATE TEXT SEARCH DICTIONARY thesaurus ( 65 | Template=thesaurus, 66 | DictFile=thesaurus_sample, 67 | Dictionary=english_stem 68 | ); 69 | 70 | SELECT ts_lexize('thesaurus', 'one'); 71 | 72 | -- Test ispell dictionary in configuration 73 | CREATE TEXT SEARCH CONFIGURATION ispell_tst ( 74 | COPY=english 75 | ); 76 | 77 | ALTER TEXT SEARCH CONFIGURATION ispell_tst ALTER MAPPING FOR 78 | word, numword, asciiword, hword, numhword, asciihword, hword_part, hword_numpart, hword_asciipart 79 | WITH ispell, english_stem; 80 | 81 | SELECT to_tsvector('ispell_tst', 'Booking the skies after rebookings for footballklubber from a foot'); 82 | SELECT to_tsquery('ispell_tst', 'footballklubber'); 83 | SELECT to_tsquery('ispell_tst', 'footballyklubber:b & rebookings:A & sky'); 84 | 85 | -- Test ispell dictionary with hunspell affix in configuration 86 | CREATE TEXT SEARCH CONFIGURATION hunspell_tst ( 87 | COPY=ispell_tst 88 | ); 89 | 90 | ALTER TEXT SEARCH CONFIGURATION hunspell_tst ALTER MAPPING 91 | REPLACE ispell WITH hunspell; 92 | 93 | SELECT to_tsvector('hunspell_tst', 'Booking the skies after rebookings for footballklubber from a foot'); 94 | SELECT to_tsquery('hunspell_tst', 'footballklubber'); 95 | SELECT to_tsquery('hunspell_tst', 'footballyklubber:b & rebookings:A & sky'); 96 | 97 | -- Test synonym dictionary in configuration 98 | CREATE TEXT SEARCH CONFIGURATION synonym_tst ( 99 | COPY=english 100 | ); 101 | 102 | ALTER TEXT SEARCH CONFIGURATION synonym_tst ALTER MAPPING FOR 103 | asciiword, hword_asciipart, asciihword 104 | WITH synonym, english_stem; 105 | 106 | SELECT to_tsvector('synonym_tst', 'Postgresql is often called as postgres or pgsql and pronounced as postgre'); 107 | SELECT to_tsvector('synonym_tst', 'Most common mistake is to write Gogle instead of Google'); 108 | SELECT to_tsvector('synonym_tst', 'Indexes or indices - Which is right plural form of index?'); 109 | SELECT to_tsquery('synonym_tst', 'Index & indices'); 110 | 111 | -- test thesaurus in configuration 112 | -- see thesaurus_sample.ths to understand 'odd' resulting tsvector 113 | CREATE TEXT SEARCH CONFIGURATION thesaurus_tst ( 114 | COPY=synonym_tst 115 | ); 116 | 117 | ALTER TEXT SEARCH CONFIGURATION thesaurus_tst ALTER MAPPING FOR 118 | asciiword, hword_asciipart, asciihword 119 | WITH synonym, thesaurus, english_stem; 120 | 121 | SELECT to_tsvector('thesaurus_tst', 'one postgres one two one two three one'); 122 | SELECT to_tsvector('thesaurus_tst', 'Supernovae star is very new star and usually called supernovae (abbrevation SN)'); 123 | SELECT to_tsvector('thesaurus_tst', 'Booking tickets is looking like a booking a tickets'); 124 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/tstypes.sql: -------------------------------------------------------------------------------- 1 | --Base tsvector test 2 | 3 | SELECT '1'::tsvector; 4 | SELECT '1 '::tsvector; 5 | SELECT ' 1'::tsvector; 6 | SELECT ' 1 '::tsvector; 7 | SELECT '1 2'::tsvector; 8 | SELECT '''1 2'''::tsvector; 9 | SELECT E'''1 \\''2'''::tsvector; 10 | SELECT E'''1 \\''2''3'::tsvector; 11 | SELECT E'''1 \\''2'' 3'::tsvector; 12 | SELECT E'''1 \\''2'' '' 3'' 4 '::tsvector; 13 | SELECT $$'\\as' ab\c ab\\c AB\\\c ab\\\\c$$::tsvector; 14 | SELECT tsvectorin(tsvectorout($$'\\as' ab\c ab\\c AB\\\c ab\\\\c$$::tsvector)); 15 | SELECT '''w'':4A,3B,2C,1D,5 a:8'; 16 | SELECT 'a:3A b:2a'::tsvector || 'ba:1234 a:1B'; 17 | SELECT setweight('w:12B w:13* w:12,5,6 a:1,3* a:3 w asd:1dc asd zxc:81,567,222A'::tsvector, 'c'); 18 | SELECT strip('w:12B w:13* w:12,5,6 a:1,3* a:3 w asd:1dc asd'::tsvector); 19 | 20 | --Base tsquery test 21 | SELECT '1'::tsquery; 22 | SELECT '1 '::tsquery; 23 | SELECT ' 1'::tsquery; 24 | SELECT ' 1 '::tsquery; 25 | SELECT '''1 2'''::tsquery; 26 | SELECT E'''1 \\''2'''::tsquery; 27 | SELECT '!1'::tsquery; 28 | SELECT '1|2'::tsquery; 29 | SELECT '1|!2'::tsquery; 30 | SELECT '!1|2'::tsquery; 31 | SELECT '!1|!2'::tsquery; 32 | SELECT '!(!1|!2)'::tsquery; 33 | SELECT '!(!1|2)'::tsquery; 34 | SELECT '!(1|!2)'::tsquery; 35 | SELECT '!(1|2)'::tsquery; 36 | SELECT '1&2'::tsquery; 37 | SELECT '!1&2'::tsquery; 38 | SELECT '1&!2'::tsquery; 39 | SELECT '!1&!2'::tsquery; 40 | SELECT '(1&2)'::tsquery; 41 | SELECT '1&(2)'::tsquery; 42 | SELECT '!(1)&2'::tsquery; 43 | SELECT '!(1&2)'::tsquery; 44 | SELECT '1|2&3'::tsquery; 45 | SELECT '1|(2&3)'::tsquery; 46 | SELECT '(1|2)&3'::tsquery; 47 | SELECT '1|2&!3'::tsquery; 48 | SELECT '1|!2&3'::tsquery; 49 | SELECT '!1|2&3'::tsquery; 50 | SELECT '!1|(2&3)'::tsquery; 51 | SELECT '!(1|2)&3'::tsquery; 52 | SELECT '(!1|2)&3'::tsquery; 53 | SELECT '1|(2|(4|(5|6)))'::tsquery; 54 | SELECT '1|2|4|5|6'::tsquery; 55 | SELECT '1&(2&(4&(5&6)))'::tsquery; 56 | SELECT '1&2&4&5&6'::tsquery; 57 | SELECT '1&(2&(4&(5|6)))'::tsquery; 58 | SELECT '1&(2&(4&(5|!6)))'::tsquery; 59 | SELECT E'1&(''2''&('' 4''&(\\|5 | ''6 \\'' !|&'')))'::tsquery; 60 | SELECT $$'\\as'$$::tsquery; 61 | SELECT 'a:* & nbb:*ac | doo:a* | goo'::tsquery; 62 | 63 | SELECT 'a' < 'b & c'::tsquery as "true"; 64 | SELECT 'a' > 'b & c'::tsquery as "false"; 65 | SELECT 'a | f' < 'b & c'::tsquery as "true"; 66 | SELECT 'a | ff' < 'b & c'::tsquery as "false"; 67 | SELECT 'a | f | g' < 'b & c'::tsquery as "false"; 68 | 69 | SELECT numnode( 'new'::tsquery ); 70 | SELECT numnode( 'new & york'::tsquery ); 71 | SELECT numnode( 'new & york | qwery'::tsquery ); 72 | 73 | SELECT 'foo & bar'::tsquery && 'asd'; 74 | SELECT 'foo & bar'::tsquery || 'asd & fg'; 75 | SELECT 'foo & bar'::tsquery || !!'asd & fg'::tsquery; 76 | SELECT 'foo & bar'::tsquery && 'asd | fg'; 77 | 78 | -- tsvector-tsquery operations 79 | 80 | SELECT 'a b:89 ca:23A,64b d:34c'::tsvector @@ 'd:AC & ca' as "true"; 81 | SELECT 'a b:89 ca:23A,64b d:34c'::tsvector @@ 'd:AC & ca:B' as "true"; 82 | SELECT 'a b:89 ca:23A,64b d:34c'::tsvector @@ 'd:AC & ca:A' as "true"; 83 | SELECT 'a b:89 ca:23A,64b d:34c'::tsvector @@ 'd:AC & ca:C' as "false"; 84 | SELECT 'a b:89 ca:23A,64b d:34c'::tsvector @@ 'd:AC & ca:CB' as "true"; 85 | SELECT 'a b:89 ca:23A,64b d:34c'::tsvector @@ 'd:AC & c:*C' as "false"; 86 | SELECT 'a b:89 ca:23A,64b d:34c'::tsvector @@ 'd:AC & c:*CB' as "true"; 87 | SELECT 'a b:89 ca:23A,64b cb:80c d:34c'::tsvector @@ 'd:AC & c:*C' as "true"; 88 | SELECT 'a b:89 ca:23A,64c cb:80b d:34c'::tsvector @@ 'd:AC & c:*C' as "true"; 89 | SELECT 'a b:89 ca:23A,64c cb:80b d:34c'::tsvector @@ 'd:AC & c:*B' as "true"; 90 | 91 | SELECT 'supernova'::tsvector @@ 'super'::tsquery AS "false"; 92 | SELECT 'supeanova supernova'::tsvector @@ 'super'::tsquery AS "false"; 93 | SELECT 'supeznova supernova'::tsvector @@ 'super'::tsquery AS "false"; 94 | SELECT 'supernova'::tsvector @@ 'super:*'::tsquery AS "true"; 95 | SELECT 'supeanova supernova'::tsvector @@ 'super:*'::tsquery AS "true"; 96 | SELECT 'supeznova supernova'::tsvector @@ 'super:*'::tsquery AS "true"; 97 | 98 | SELECT ts_rank(' a:1 s:2C d g'::tsvector, 'a | s'); 99 | SELECT ts_rank(' a:1 sa:2C d g'::tsvector, 'a | s'); 100 | SELECT ts_rank(' a:1 sa:2C d g'::tsvector, 'a | s:*'); 101 | SELECT ts_rank(' a:1 sa:2C d g'::tsvector, 'a | sa:*'); 102 | SELECT ts_rank(' a:1 s:2B d g'::tsvector, 'a | s'); 103 | SELECT ts_rank(' a:1 s:2 d g'::tsvector, 'a | s'); 104 | SELECT ts_rank(' a:1 s:2C d g'::tsvector, 'a & s'); 105 | SELECT ts_rank(' a:1 s:2B d g'::tsvector, 'a & s'); 106 | SELECT ts_rank(' a:1 s:2 d g'::tsvector, 'a & s'); 107 | 108 | SELECT ts_rank_cd(' a:1 s:2C d g'::tsvector, 'a | s'); 109 | SELECT ts_rank_cd(' a:1 sa:2C d g'::tsvector, 'a | s'); 110 | SELECT ts_rank_cd(' a:1 sa:2C d g'::tsvector, 'a | s:*'); 111 | SELECT ts_rank_cd(' a:1 sa:2C d g'::tsvector, 'a | sa:*'); 112 | SELECT ts_rank_cd(' a:1 sa:3C sab:2c d g'::tsvector, 'a | sa:*'); 113 | SELECT ts_rank_cd(' a:1 s:2B d g'::tsvector, 'a | s'); 114 | SELECT ts_rank_cd(' a:1 s:2 d g'::tsvector, 'a | s'); 115 | SELECT ts_rank_cd(' a:1 s:2C d g'::tsvector, 'a & s'); 116 | SELECT ts_rank_cd(' a:1 s:2B d g'::tsvector, 'a & s'); 117 | SELECT ts_rank_cd(' a:1 s:2 d g'::tsvector, 'a & s'); 118 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/txid.sql: -------------------------------------------------------------------------------- 1 | -- txid_snapshot data type and related functions 2 | 3 | -- i/o 4 | select '12:13:'::txid_snapshot; 5 | select '12:18:14,16'::txid_snapshot; 6 | 7 | -- errors 8 | select '31:12:'::txid_snapshot; 9 | select '0:1:'::txid_snapshot; 10 | select '12:13:0'::txid_snapshot; 11 | select '12:16:14,13'::txid_snapshot; 12 | select '12:16:14,14'::txid_snapshot; 13 | 14 | create temp table snapshot_test ( 15 | nr integer, 16 | snap txid_snapshot 17 | ); 18 | 19 | insert into snapshot_test values (1, '12:13:'); 20 | insert into snapshot_test values (2, '12:20:13,15,18'); 21 | insert into snapshot_test values (3, '100001:100009:100005,100007,100008'); 22 | insert into snapshot_test values (4, '100:150:101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131'); 23 | select snap from snapshot_test order by nr; 24 | 25 | select txid_snapshot_xmin(snap), 26 | txid_snapshot_xmax(snap), 27 | txid_snapshot_xip(snap) 28 | from snapshot_test order by nr; 29 | 30 | select id, txid_visible_in_snapshot(id, snap) 31 | from snapshot_test, generate_series(11, 21) id 32 | where nr = 2; 33 | 34 | -- test bsearch 35 | select id, txid_visible_in_snapshot(id, snap) 36 | from snapshot_test, generate_series(90, 160) id 37 | where nr = 4; 38 | 39 | -- test current values also 40 | select txid_current() >= txid_snapshot_xmin(txid_current_snapshot()); 41 | 42 | -- we can't assume current is always less than xmax, however 43 | 44 | select txid_visible_in_snapshot(txid_current(), txid_current_snapshot()); 45 | 46 | -- test 64bitness 47 | 48 | select txid_snapshot '1000100010001000:1000100010001100:1000100010001012,1000100010001013'; 49 | select txid_visible_in_snapshot('1000100010001012', '1000100010001000:1000100010001100:1000100010001012,1000100010001013'); 50 | select txid_visible_in_snapshot('1000100010001015', '1000100010001000:1000100010001100:1000100010001012,1000100010001013'); 51 | 52 | -- test 64bit overflow 53 | SELECT txid_snapshot '1:9223372036854775807:3'; 54 | SELECT txid_snapshot '1:9223372036854775808:3'; 55 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/typed_table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE ttable1 OF nothing; 2 | 3 | CREATE TYPE person_type AS (id int, name text); 4 | CREATE TABLE persons OF person_type; 5 | CREATE TABLE IF NOT EXISTS persons OF person_type; 6 | SELECT * FROM persons; 7 | \d persons 8 | 9 | CREATE FUNCTION get_all_persons() RETURNS SETOF person_type 10 | LANGUAGE SQL 11 | AS $$ 12 | SELECT * FROM persons; 13 | $$; 14 | 15 | SELECT * FROM get_all_persons(); 16 | 17 | -- certain ALTER TABLE operations on typed tables are not allowed 18 | ALTER TABLE persons ADD COLUMN comment text; 19 | ALTER TABLE persons DROP COLUMN name; 20 | ALTER TABLE persons RENAME COLUMN id TO num; 21 | ALTER TABLE persons ALTER COLUMN name TYPE varchar; 22 | CREATE TABLE stuff (id int); 23 | ALTER TABLE persons INHERIT stuff; 24 | 25 | CREATE TABLE personsx OF person_type (myname WITH OPTIONS NOT NULL); -- error 26 | 27 | CREATE TABLE persons2 OF person_type ( 28 | id WITH OPTIONS PRIMARY KEY, 29 | UNIQUE (name) 30 | ); 31 | 32 | \d persons2 33 | 34 | CREATE TABLE persons3 OF person_type ( 35 | PRIMARY KEY (id), 36 | name WITH OPTIONS DEFAULT '' 37 | ); 38 | 39 | \d persons3 40 | 41 | CREATE TABLE persons4 OF person_type ( 42 | name WITH OPTIONS NOT NULL, 43 | name WITH OPTIONS DEFAULT '' -- error, specified more than once 44 | ); 45 | 46 | DROP TYPE person_type RESTRICT; 47 | DROP TYPE person_type CASCADE; 48 | 49 | CREATE TABLE persons5 OF stuff; -- only CREATE TYPE AS types may be used 50 | 51 | DROP TABLE stuff; 52 | 53 | 54 | -- implicit casting 55 | 56 | CREATE TYPE person_type AS (id int, name text); 57 | CREATE TABLE persons OF person_type; 58 | INSERT INTO persons VALUES (1, 'test'); 59 | 60 | CREATE FUNCTION namelen(person_type) RETURNS int LANGUAGE SQL AS $$ SELECT length($1.name) $$; 61 | SELECT id, namelen(persons) FROM persons; 62 | 63 | DROP TYPE person_type CASCADE; 64 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/update.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- UPDATE syntax tests 3 | -- 4 | 5 | CREATE TABLE update_test ( 6 | a INT DEFAULT 10, 7 | b INT, 8 | c TEXT 9 | ); 10 | 11 | INSERT INTO update_test VALUES (5, 10, 'foo'); 12 | INSERT INTO update_test(b, a) VALUES (15, 10); 13 | 14 | SELECT * FROM update_test; 15 | 16 | UPDATE update_test SET a = DEFAULT, b = DEFAULT; 17 | 18 | SELECT * FROM update_test; 19 | 20 | -- aliases for the UPDATE target table 21 | UPDATE update_test AS t SET b = 10 WHERE t.a = 10; 22 | 23 | SELECT * FROM update_test; 24 | 25 | UPDATE update_test t SET b = t.b + 10 WHERE t.a = 10; 26 | 27 | SELECT * FROM update_test; 28 | 29 | -- 30 | -- Test VALUES in FROM 31 | -- 32 | 33 | UPDATE update_test SET a=v.i FROM (VALUES(100, 20)) AS v(i, j) 34 | WHERE update_test.b = v.j; 35 | 36 | SELECT * FROM update_test; 37 | 38 | -- 39 | -- Test multiple-set-clause syntax 40 | -- 41 | 42 | UPDATE update_test SET (c,b,a) = ('bugle', b+11, DEFAULT) WHERE c = 'foo'; 43 | SELECT * FROM update_test; 44 | UPDATE update_test SET (c,b) = ('car', a+b), a = a + 1 WHERE a = 10; 45 | SELECT * FROM update_test; 46 | -- fail, multi assignment to same column: 47 | UPDATE update_test SET (c,b) = ('car', a+b), b = a + 1 WHERE a = 10; 48 | 49 | -- XXX this should work, but doesn't yet: 50 | UPDATE update_test SET (a,b) = (select a,b FROM update_test where c = 'foo') 51 | WHERE a = 10; 52 | 53 | -- if an alias for the target table is specified, don't allow references 54 | -- to the original table name 55 | UPDATE update_test AS t SET b = update_test.b + 10 WHERE t.a = 10; 56 | 57 | -- Make sure that we can update to a TOASTed value. 58 | UPDATE update_test SET c = repeat('x', 10000) WHERE c = 'car'; 59 | SELECT a, b, char_length(c) FROM update_test; 60 | 61 | DROP TABLE update_test; 62 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/uuid.sql: -------------------------------------------------------------------------------- 1 | -- regression test for the uuid datatype 2 | -- creating test tables 3 | CREATE TABLE guid1 4 | ( 5 | guid_field UUID, 6 | text_field TEXT DEFAULT(now()) 7 | ); 8 | CREATE TABLE guid2 9 | ( 10 | guid_field UUID, 11 | text_field TEXT DEFAULT(now()) 12 | ); 13 | 14 | -- inserting invalid data tests 15 | -- too long 16 | INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-1111-111111111111F'); 17 | -- too short 18 | INSERT INTO guid1(guid_field) VALUES('{11111111-1111-1111-1111-11111111111}'); 19 | -- valid data but invalid format 20 | INSERT INTO guid1(guid_field) VALUES('111-11111-1111-1111-1111-111111111111'); 21 | INSERT INTO guid1(guid_field) VALUES('{22222222-2222-2222-2222-222222222222 '); 22 | -- invalid data 23 | INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-G111-111111111111'); 24 | INSERT INTO guid1(guid_field) VALUES('11+11111-1111-1111-1111-111111111111'); 25 | 26 | --inserting three input formats 27 | INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-1111-111111111111'); 28 | INSERT INTO guid1(guid_field) VALUES('{22222222-2222-2222-2222-222222222222}'); 29 | INSERT INTO guid1(guid_field) VALUES('3f3e3c3b3a3039383736353433a2313e'); 30 | 31 | -- retrieving the inserted data 32 | SELECT guid_field FROM guid1; 33 | 34 | -- ordering test 35 | SELECT guid_field FROM guid1 ORDER BY guid_field ASC; 36 | SELECT guid_field FROM guid1 ORDER BY guid_field DESC; 37 | 38 | -- = operator test 39 | SELECT COUNT(*) FROM guid1 WHERE guid_field = '3f3e3c3b-3a30-3938-3736-353433a2313e'; 40 | 41 | -- <> operator test 42 | SELECT COUNT(*) FROM guid1 WHERE guid_field <> '11111111111111111111111111111111'; 43 | 44 | -- < operator test 45 | SELECT COUNT(*) FROM guid1 WHERE guid_field < '22222222-2222-2222-2222-222222222222'; 46 | 47 | -- <= operator test 48 | SELECT COUNT(*) FROM guid1 WHERE guid_field <= '22222222-2222-2222-2222-222222222222'; 49 | 50 | -- > operator test 51 | SELECT COUNT(*) FROM guid1 WHERE guid_field > '22222222-2222-2222-2222-222222222222'; 52 | 53 | -- >= operator test 54 | SELECT COUNT(*) FROM guid1 WHERE guid_field >= '22222222-2222-2222-2222-222222222222'; 55 | 56 | -- btree and hash index creation test 57 | CREATE INDEX guid1_btree ON guid1 USING BTREE (guid_field); 58 | CREATE INDEX guid1_hash ON guid1 USING HASH (guid_field); 59 | 60 | -- unique index test 61 | CREATE UNIQUE INDEX guid1_unique_BTREE ON guid1 USING BTREE (guid_field); 62 | -- should fail 63 | INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-1111-111111111111'); 64 | 65 | -- check to see whether the new indexes are actually there 66 | SELECT count(*) FROM pg_class WHERE relkind='i' AND relname LIKE 'guid%'; 67 | 68 | -- populating the test tables with additional records 69 | INSERT INTO guid1(guid_field) VALUES('44444444-4444-4444-4444-444444444444'); 70 | INSERT INTO guid2(guid_field) VALUES('11111111-1111-1111-1111-111111111111'); 71 | INSERT INTO guid2(guid_field) VALUES('{22222222-2222-2222-2222-222222222222}'); 72 | INSERT INTO guid2(guid_field) VALUES('3f3e3c3b3a3039383736353433a2313e'); 73 | 74 | -- join test 75 | SELECT COUNT(*) FROM guid1 g1 INNER JOIN guid2 g2 ON g1.guid_field = g2.guid_field; 76 | SELECT COUNT(*) FROM guid1 g1 LEFT JOIN guid2 g2 ON g1.guid_field = g2.guid_field WHERE g2.guid_field IS NULL; 77 | 78 | -- clean up 79 | DROP TABLE guid1, guid2 CASCADE; 80 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/vacuum.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- VACUUM 3 | -- 4 | 5 | CREATE TABLE vactst (i INT); 6 | INSERT INTO vactst VALUES (1); 7 | INSERT INTO vactst SELECT * FROM vactst; 8 | INSERT INTO vactst SELECT * FROM vactst; 9 | INSERT INTO vactst SELECT * FROM vactst; 10 | INSERT INTO vactst SELECT * FROM vactst; 11 | INSERT INTO vactst SELECT * FROM vactst; 12 | INSERT INTO vactst SELECT * FROM vactst; 13 | INSERT INTO vactst SELECT * FROM vactst; 14 | INSERT INTO vactst SELECT * FROM vactst; 15 | INSERT INTO vactst SELECT * FROM vactst; 16 | INSERT INTO vactst SELECT * FROM vactst; 17 | INSERT INTO vactst SELECT * FROM vactst; 18 | INSERT INTO vactst VALUES (0); 19 | SELECT count(*) FROM vactst; 20 | DELETE FROM vactst WHERE i != 0; 21 | SELECT * FROM vactst; 22 | VACUUM FULL vactst; 23 | UPDATE vactst SET i = i + 1; 24 | INSERT INTO vactst SELECT * FROM vactst; 25 | INSERT INTO vactst SELECT * FROM vactst; 26 | INSERT INTO vactst SELECT * FROM vactst; 27 | INSERT INTO vactst SELECT * FROM vactst; 28 | INSERT INTO vactst SELECT * FROM vactst; 29 | INSERT INTO vactst SELECT * FROM vactst; 30 | INSERT INTO vactst SELECT * FROM vactst; 31 | INSERT INTO vactst SELECT * FROM vactst; 32 | INSERT INTO vactst SELECT * FROM vactst; 33 | INSERT INTO vactst SELECT * FROM vactst; 34 | INSERT INTO vactst SELECT * FROM vactst; 35 | INSERT INTO vactst VALUES (0); 36 | SELECT count(*) FROM vactst; 37 | DELETE FROM vactst WHERE i != 0; 38 | VACUUM (FULL) vactst; 39 | DELETE FROM vactst; 40 | SELECT * FROM vactst; 41 | 42 | VACUUM (FULL, FREEZE) vactst; 43 | VACUUM (ANALYZE, FULL) vactst; 44 | 45 | CREATE TABLE vaccluster (i INT PRIMARY KEY); 46 | ALTER TABLE vaccluster CLUSTER ON vaccluster_pkey; 47 | INSERT INTO vaccluster SELECT * FROM vactst; 48 | CLUSTER vaccluster; 49 | 50 | VACUUM FULL pg_am; 51 | VACUUM FULL pg_class; 52 | VACUUM FULL pg_database; 53 | VACUUM FULL vaccluster; 54 | VACUUM FULL vactst; 55 | 56 | DROP TABLE vaccluster; 57 | DROP TABLE vactst; 58 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/varchar.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- VARCHAR 3 | -- 4 | 5 | CREATE TABLE VARCHAR_TBL(f1 varchar(1)); 6 | 7 | INSERT INTO VARCHAR_TBL (f1) VALUES ('a'); 8 | 9 | INSERT INTO VARCHAR_TBL (f1) VALUES ('A'); 10 | 11 | -- any of the following three input formats are acceptable 12 | INSERT INTO VARCHAR_TBL (f1) VALUES ('1'); 13 | 14 | INSERT INTO VARCHAR_TBL (f1) VALUES (2); 15 | 16 | INSERT INTO VARCHAR_TBL (f1) VALUES ('3'); 17 | 18 | -- zero-length char 19 | INSERT INTO VARCHAR_TBL (f1) VALUES (''); 20 | 21 | -- try varchar's of greater than 1 length 22 | INSERT INTO VARCHAR_TBL (f1) VALUES ('cd'); 23 | INSERT INTO VARCHAR_TBL (f1) VALUES ('c '); 24 | 25 | 26 | SELECT '' AS seven, * FROM VARCHAR_TBL; 27 | 28 | SELECT '' AS six, c.* 29 | FROM VARCHAR_TBL c 30 | WHERE c.f1 <> 'a'; 31 | 32 | SELECT '' AS one, c.* 33 | FROM VARCHAR_TBL c 34 | WHERE c.f1 = 'a'; 35 | 36 | SELECT '' AS five, c.* 37 | FROM VARCHAR_TBL c 38 | WHERE c.f1 < 'a'; 39 | 40 | SELECT '' AS six, c.* 41 | FROM VARCHAR_TBL c 42 | WHERE c.f1 <= 'a'; 43 | 44 | SELECT '' AS one, c.* 45 | FROM VARCHAR_TBL c 46 | WHERE c.f1 > 'a'; 47 | 48 | SELECT '' AS two, c.* 49 | FROM VARCHAR_TBL c 50 | WHERE c.f1 >= 'a'; 51 | 52 | DROP TABLE VARCHAR_TBL; 53 | 54 | -- 55 | -- Now test longer arrays of char 56 | -- 57 | 58 | CREATE TABLE VARCHAR_TBL(f1 varchar(4)); 59 | 60 | INSERT INTO VARCHAR_TBL (f1) VALUES ('a'); 61 | INSERT INTO VARCHAR_TBL (f1) VALUES ('ab'); 62 | INSERT INTO VARCHAR_TBL (f1) VALUES ('abcd'); 63 | INSERT INTO VARCHAR_TBL (f1) VALUES ('abcde'); 64 | INSERT INTO VARCHAR_TBL (f1) VALUES ('abcd '); 65 | 66 | SELECT '' AS four, * FROM VARCHAR_TBL; 67 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/with_query.sql: -------------------------------------------------------------------------------- 1 | WITH regional_sales AS ( 2 | SELECT ps_id as test from zcep_data.parcel_service 3 | ), 4 | top_regions AS ( 5 | SELECT ps_id as test from zcep_data.parcel_service 6 | where ps_id > (SELECT SUM(total_sales) / 10 FROM regional_sales) 7 | ) 8 | SELECT * 9 | FROM zcep_data.parcel_service 10 | WHERE ps_id IN (SELECT test FROM regional_sales); -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/without_oid.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- WITHOUT OID 3 | -- 4 | 5 | -- 6 | -- This test tries to verify that WITHOUT OIDS actually saves space. 7 | -- On machines where MAXALIGN is 8, WITHOUT OIDS may or may not save any 8 | -- space, depending on the size of the tuple header + null bitmap. 9 | -- As of 8.3 we need a null bitmap of 8 or less bits for the difference 10 | -- to appear. 11 | -- 12 | CREATE TABLE wi (i INT, 13 | n1 int, n2 int, n3 int, n4 int, 14 | n5 int, n6 int, n7 int) WITH OIDS; 15 | CREATE TABLE wo (i INT, 16 | n1 int, n2 int, n3 int, n4 int, 17 | n5 int, n6 int, n7 int) WITHOUT OIDS; 18 | 19 | INSERT INTO wi VALUES (1); -- 1 20 | INSERT INTO wo SELECT i FROM wi; -- 1 21 | INSERT INTO wo SELECT i+1 FROM wi; -- 1+1=2 22 | INSERT INTO wi SELECT i+1 FROM wo; -- 1+2=3 23 | INSERT INTO wi SELECT i+3 FROM wi; -- 3+3=6 24 | INSERT INTO wo SELECT i+2 FROM wi; -- 2+6=8 25 | INSERT INTO wo SELECT i+8 FROM wo; -- 8+8=16 26 | INSERT INTO wi SELECT i+6 FROM wo; -- 6+16=22 27 | INSERT INTO wi SELECT i+22 FROM wi; -- 22+22=44 28 | INSERT INTO wo SELECT i+16 FROM wi; -- 16+44=60 29 | INSERT INTO wo SELECT i+60 FROM wo; -- 60+60=120 30 | INSERT INTO wi SELECT i+44 FROM wo; -- 44+120=164 31 | INSERT INTO wi SELECT i+164 FROM wi; -- 164+164=328 32 | INSERT INTO wo SELECT i+120 FROM wi; -- 120+328=448 33 | INSERT INTO wo SELECT i+448 FROM wo; -- 448+448=896 34 | INSERT INTO wi SELECT i+328 FROM wo; -- 328+896=1224 35 | INSERT INTO wi SELECT i+1224 FROM wi; -- 1224+1224=2448 36 | INSERT INTO wo SELECT i+896 FROM wi; -- 896+2448=3344 37 | INSERT INTO wo SELECT i+3344 FROM wo; -- 3344+3344=6688 38 | INSERT INTO wi SELECT i+2448 FROM wo; -- 2448+6688=9136 39 | INSERT INTO wo SELECT i+6688 FROM wi WHERE i<=2448; -- 6688+2448=9136 40 | 41 | SELECT count(oid) FROM wi; 42 | -- should fail 43 | SELECT count(oid) FROM wo; 44 | 45 | VACUUM ANALYZE wi; 46 | VACUUM ANALYZE wo; 47 | 48 | SELECT min(relpages) < max(relpages), min(reltuples) - max(reltuples) 49 | FROM pg_class 50 | WHERE relname IN ('wi', 'wo'); 51 | 52 | DROP TABLE wi; 53 | DROP TABLE wo; 54 | 55 | -- 56 | -- WITH / WITHOUT OIDS in CREATE TABLE AS 57 | -- 58 | CREATE TABLE create_table_test ( 59 | a int, 60 | b int 61 | ); 62 | 63 | COPY create_table_test FROM stdin; 64 | 5 10 65 | 10 15 66 | \. 67 | 68 | CREATE TABLE create_table_test2 WITH OIDS AS 69 | SELECT a + b AS c1, a - b AS c2 FROM create_table_test; 70 | 71 | CREATE TABLE create_table_test3 WITHOUT OIDS AS 72 | SELECT a + b AS c1, a - b AS c2 FROM create_table_test; 73 | 74 | SELECT count(oid) FROM create_table_test2; 75 | -- should fail 76 | SELECT count(oid) FROM create_table_test3; 77 | 78 | PREPARE table_source(int) AS 79 | SELECT a + b AS c1, a - b AS c2, $1 AS c3 FROM create_table_test; 80 | 81 | CREATE TABLE execute_with WITH OIDS AS EXECUTE table_source(1); 82 | CREATE TABLE execute_without WITHOUT OIDS AS EXECUTE table_source(2); 83 | 84 | SELECT count(oid) FROM execute_with; 85 | -- should fail 86 | SELECT count(oid) FROM execute_without; 87 | 88 | DROP TABLE create_table_test; 89 | DROP TABLE create_table_test2; 90 | DROP TABLE create_table_test3; 91 | DROP TABLE execute_with; 92 | DROP TABLE execute_without; 93 | -------------------------------------------------------------------------------- /plpgsql-ast/src/test/resources/sql_parse_test/xmlmap.sql: -------------------------------------------------------------------------------- 1 | CREATE SCHEMA testxmlschema; 2 | 3 | CREATE TABLE testxmlschema.test1 (a int, b text); 4 | INSERT INTO testxmlschema.test1 VALUES (1, 'one'), (2, 'two'), (-1, null); 5 | CREATE DOMAIN testxmldomain AS varchar; 6 | CREATE TABLE testxmlschema.test2 (z int, y varchar(500), x char(6), w numeric(9,2), v smallint, u bigint, t real, s time, r timestamp, q date, p xml, o testxmldomain, n bool, m bytea, aaa text); 7 | ALTER TABLE testxmlschema.test2 DROP COLUMN aaa; 8 | INSERT INTO testxmlschema.test2 VALUES (55, 'abc', 'def', 98.6, 2, 999, 0, '21:07', '2009-06-08 21:07:30', '2009-06-08', NULL, 'ABC', true, 'XYZ'); 9 | 10 | SELECT table_to_xml('testxmlschema.test1', false, false, ''); 11 | SELECT table_to_xml('testxmlschema.test1', true, false, 'foo'); 12 | SELECT table_to_xml('testxmlschema.test1', false, true, ''); 13 | SELECT table_to_xml('testxmlschema.test1', true, true, ''); 14 | SELECT table_to_xml('testxmlschema.test2', false, false, ''); 15 | 16 | SELECT table_to_xmlschema('testxmlschema.test1', false, false, ''); 17 | SELECT table_to_xmlschema('testxmlschema.test1', true, false, ''); 18 | SELECT table_to_xmlschema('testxmlschema.test1', false, true, 'foo'); 19 | SELECT table_to_xmlschema('testxmlschema.test1', true, true, ''); 20 | SELECT table_to_xmlschema('testxmlschema.test2', false, false, ''); 21 | 22 | SELECT table_to_xml_and_xmlschema('testxmlschema.test1', false, false, ''); 23 | SELECT table_to_xml_and_xmlschema('testxmlschema.test1', true, false, ''); 24 | SELECT table_to_xml_and_xmlschema('testxmlschema.test1', false, true, ''); 25 | SELECT table_to_xml_and_xmlschema('testxmlschema.test1', true, true, 'foo'); 26 | 27 | SELECT query_to_xml('SELECT * FROM testxmlschema.test1', false, false, ''); 28 | SELECT query_to_xmlschema('SELECT * FROM testxmlschema.test1', false, false, ''); 29 | SELECT query_to_xml_and_xmlschema('SELECT * FROM testxmlschema.test1', true, true, ''); 30 | 31 | DECLARE xc CURSOR WITH HOLD FOR SELECT * FROM testxmlschema.test1 ORDER BY 1, 2; 32 | SELECT cursor_to_xml('xc'::refcursor, 5, false, true, ''); 33 | MOVE FIRST IN xc; 34 | SELECT cursor_to_xml('xc'::refcursor, 5, true, false, ''); 35 | SELECT cursor_to_xmlschema('xc'::refcursor, true, false, ''); 36 | 37 | SELECT schema_to_xml('testxmlschema', false, true, ''); 38 | SELECT schema_to_xml('testxmlschema', true, false, ''); 39 | SELECT schema_to_xmlschema('testxmlschema', false, true, ''); 40 | SELECT schema_to_xmlschema('testxmlschema', true, false, ''); 41 | SELECT schema_to_xml_and_xmlschema('testxmlschema', true, true, 'foo'); 42 | --------------------------------------------------------------------------------