├── .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 |
--------------------------------------------------------------------------------