├── .eslintrc.js ├── .gitignore ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── deparse ├── package.json ├── parse ├── src ├── deparser.js ├── index.js └── utils.js ├── test ├── fixtures │ ├── complex.sql │ ├── custom.sql │ ├── param-ref.sql │ ├── query-001.sql │ ├── query-002.sql │ ├── query-003.sql │ ├── simple.sql │ └── upstream │ │ ├── abstime.sql │ │ ├── advisory_lock.sql │ │ ├── aggregates.sql │ │ ├── alter_generic.sql │ │ ├── alter_operator.sql │ │ ├── alter_table.sql │ │ ├── arrays.sql │ │ ├── async.sql │ │ ├── bit.sql │ │ ├── bitmapops.sql │ │ ├── boolean.sql │ │ ├── box.sql │ │ ├── brin.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 │ │ ├── copydml.sql │ │ ├── copyselect.sql │ │ ├── create_aggregate.sql │ │ ├── create_am.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 │ │ ├── dbsize.sql │ │ ├── delete.sql │ │ ├── dependency.sql │ │ ├── domain.sql │ │ ├── drop_if_exists.sql │ │ ├── drop_operator.sql │ │ ├── enum.sql │ │ ├── equivclass.sql │ │ ├── errors.sql │ │ ├── event_trigger.sql │ │ ├── float4.sql │ │ ├── float8.sql │ │ ├── foreign_data.sql │ │ ├── foreign_key.sql │ │ ├── functional_deps.sql │ │ ├── geometry.sql │ │ ├── gin.sql │ │ ├── gist.sql │ │ ├── groupingsets.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 │ │ ├── indirect_toast.sql │ │ ├── inet.sql │ │ ├── inherit.sql │ │ ├── init_privs.sql │ │ ├── insert.sql │ │ ├── insert_conflict.sql │ │ ├── int2.sql │ │ ├── int4.sql │ │ ├── int8.sql │ │ ├── interval.sql │ │ ├── join.sql │ │ ├── json.sql │ │ ├── json_encoding.sql │ │ ├── jsonb.sql │ │ ├── limit.sql │ │ ├── line.sql │ │ ├── lock.sql │ │ ├── lseg.sql │ │ ├── macaddr.sql │ │ ├── matview.sql │ │ ├── misc_functions.sql │ │ ├── money.sql │ │ ├── name.sql │ │ ├── namespace.sql │ │ ├── numeric.sql │ │ ├── numeric_big.sql │ │ ├── numerology.sql │ │ ├── object_address.sql │ │ ├── oid.sql │ │ ├── oidjoins.sql │ │ ├── opr_sanity.sql │ │ ├── path.sql │ │ ├── pg_lsn.sql │ │ ├── plancache.sql │ │ ├── plpgsql.sql │ │ ├── point.sql │ │ ├── polygon.sql │ │ ├── polymorphism.sql │ │ ├── portals.sql │ │ ├── portals_p2.sql │ │ ├── prepare.sql │ │ ├── prepared_xacts.sql │ │ ├── privileges.sql │ │ ├── psql.sql │ │ ├── psql_crosstab.sql │ │ ├── random.sql │ │ ├── rangefuncs.sql │ │ ├── rangetypes.sql │ │ ├── regex.sql │ │ ├── regproc.sql │ │ ├── reltime.sql │ │ ├── replica_identity.sql │ │ ├── returning.sql │ │ ├── roleattributes.sql │ │ ├── rolenames.sql │ │ ├── rowsecurity.sql │ │ ├── rowtypes.sql │ │ ├── rules.sql │ │ ├── sanity_check.sql │ │ ├── security_label.sql │ │ ├── select.sql │ │ ├── select_distinct.sql │ │ ├── select_distinct_on.sql │ │ ├── select_having.sql │ │ ├── select_implicit.sql │ │ ├── select_into.sql │ │ ├── select_views.sql │ │ ├── sequence.sql │ │ ├── spgist.sql │ │ ├── stats.sql │ │ ├── strings.sql │ │ ├── subselect.sql │ │ ├── tablesample.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 │ │ ├── updatable_views.sql │ │ ├── update.sql │ │ ├── uuid.sql │ │ ├── vacuum.sql │ │ ├── varchar.sql │ │ ├── window.sql │ │ ├── with.sql │ │ ├── without_oid.sql │ │ ├── xml.sql │ │ └── xmlmap.sql └── test.js ├── verify └── yarn.lock /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "es2021": true, 4 | "mocha": true, 5 | "node": true 6 | }, 7 | "extends": "eslint:recommended", 8 | "rules": { 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 0.2.0 2 | 3 | * Add support for ParamRef (https://github.com/zhm/pg-query-parser/pull/3) (@olalonde) 4 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) Zac McCormick 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | - Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | - Redistributions in binary form must reproduce the above copyright notice, this 10 | list of conditions and the following disclaimer in the documentation and/or 11 | other materials provided with the distribution. 12 | - Neither the name "pg-query-parser" nor the names of its contributors may be 13 | used to endorse or promote products derived from this software without 14 | specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 23 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pg-query-parser 2 | 3 | The real PostgreSQL parser for nodejs. The primary objective of this module is to provide symmetric parsing 4 | and deparsing of SQL statements. With this module you can modify parts of a SQL query statement and 5 | serialize the query tree back into a formatted SQL statement. It uses the *real* [PostgreSQL parser](https://github.com/lfittl/libpg_query). 6 | 7 | The main functionality provided by this module is deparsing, which PostgreSQL does not have internally. 8 | 9 | ## Installation 10 | 11 | ```sh 12 | npm install pg-query-parser 13 | ``` 14 | 15 | ## Example 16 | 17 | Rewrite part of a SQL query: 18 | 19 | ```js 20 | const parser = require('pg-query-parser'); 21 | 22 | const query = parser.parse('SELECT * FROM test_table').query; 23 | 24 | query[0].SelectStmt.fromClause[0].RangeVar.relname = 'another_table'; 25 | 26 | console.log(parser.deparse(query)); 27 | 28 | // SELECT * FROM "another_table" 29 | ``` 30 | 31 | ### Documentation 32 | 33 | ### `parser.parse(sql)` 34 | 35 | Parses the query and returns a parse object. 36 | 37 | ### Parameters 38 | 39 | | parameter | type | description | 40 | | -------------------- | ------------------ | --------------------------------------------------------- | 41 | | `query` | String | SQL query | 42 | 43 | Returns an object in the format: 44 | 45 | ``` 46 | { query: , 47 | error: { message: , 48 | fileName: , 49 | lineNumber: , 50 | cursorPosition: } 51 | ``` 52 | 53 | ### `parser.deparse(query)` 54 | 55 | Deparses the query tree and returns a formatted SQL statement. This function takes as input a query AST 56 | in the same format as the `query` property of on the result of the `parse` method. This is the primary 57 | functionality of this module. 58 | 59 | ### Parameters 60 | 61 | | parameter | type | description | 62 | | -------------------- | ------------------ | --------------------------------------------------------- | 63 | | `query` | Object | Query tree obtained from `parse` | 64 | 65 | Returns a normalized formatted SQL string. 66 | 67 | ## Related 68 | 69 | * [pg-query-native](https://github.com/zhm/node-pg-query-native) 70 | * [libpg_query](https://github.com/lfittl/libpg_query) 71 | * [pg_query](https://github.com/lfittl/pg_query) 72 | * [pg_query.go](https://github.com/lfittl/pg_query.go) 73 | -------------------------------------------------------------------------------- /deparse: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | require('babel-core/register')(); 4 | 5 | const parser = require('./src'); 6 | 7 | function runQuery(content) { 8 | const result = parser.deparse(parser.parse(content).query); 9 | console.log(result); 10 | } 11 | 12 | if (process.argv[2]) { 13 | runQuery(process.argv[2]); 14 | } else { 15 | var content = ''; 16 | 17 | process.stdin.resume(); 18 | 19 | process.stdin.on('data', (buf) => { 20 | content += buf.toString(); 21 | }); 22 | 23 | process.stdin.on('end', () => { 24 | runQuery(content); 25 | }); 26 | } 27 | 28 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pg-query-parser", 3 | "version": "0.3.0", 4 | "description": "The real PostgreSQL query parser", 5 | "homepage": "http://github.com/zhm/pg-query-parser", 6 | "main": "src/index.js", 7 | "scripts": { 8 | "test": "mocha test/test.js", 9 | "lint": "eslint src", 10 | "check-deps": "ncu", 11 | "update-deps": "ncu -u" 12 | }, 13 | "author": "Zac McCormick (http://github.com/zhm)", 14 | "license": "BSD-3-Clause", 15 | "repository": { 16 | "type": "git", 17 | "url": "git://github.com/zhm/pg-query-parser.git" 18 | }, 19 | "devDependencies": { 20 | "chai": "^4.3.4", 21 | "eslint": "^7.32.0", 22 | "glob": "^7.2.0", 23 | "mocha": "^9.1.2", 24 | "npm-check-updates": "^11.8.5" 25 | }, 26 | "dependencies": { 27 | "lodash": "^4.17.21", 28 | "pg-query-native": "^1.3.1" 29 | }, 30 | "keywords": [ 31 | "sql", 32 | "postgres", 33 | "postgresql", 34 | "pg", 35 | "query", 36 | "database" 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /parse: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const parser = require('pg-query-native'); 4 | 5 | function runQuery(query) { 6 | const result = parser.parse(query).query; 7 | console.log(JSON.stringify(result, null, ' ')); 8 | } 9 | 10 | if (process.argv[2]) { 11 | runQuery(process.argv[2]); 12 | } else { 13 | var content = ''; 14 | 15 | process.stdin.resume(); 16 | 17 | process.stdin.on('data', (buf) => { 18 | content += buf.toString(); 19 | }); 20 | 21 | process.stdin.on('end', () => { 22 | runQuery(content); 23 | }); 24 | } 25 | 26 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | const { parse } = require('pg-query-native'); 2 | const Deparser = require('./deparser'); 3 | const { walk, all, first, tables, byType, clean } = require('./utils'); 4 | 5 | const deparse = Deparser.deparse; 6 | 7 | const verify = (query) => { 8 | const result = deparse(parse(query).query); 9 | 10 | const json1 = clean(parse(query).query); 11 | const json2 = clean(parse(result).query); 12 | 13 | return JSON.stringify(json1) === JSON.stringify(json2); 14 | }; 15 | 16 | module.exports = { parse, deparse, walk, first, all, tables, byType, clean, verify, Deparser }; 17 | -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | const _ = require('lodash'); 2 | 3 | const EXIT = {}; 4 | 5 | function walk(obj, func) { 6 | if (_.isArray(obj)) { 7 | for (const item of obj) { 8 | if (func(obj, item) === EXIT) { 9 | return item; 10 | } 11 | } 12 | 13 | const results = []; 14 | 15 | for (const item of obj) { 16 | results.push(walk(item, func)); 17 | } 18 | 19 | return results; 20 | } else if (_.isObject(obj)) { 21 | for (const key of Object.keys(obj)) { 22 | const value = obj[key]; 23 | 24 | if (func(obj, key, value) === EXIT) { 25 | return obj; 26 | } 27 | } 28 | 29 | const results = []; 30 | 31 | for (const key of Object.keys(obj)) { 32 | const value = obj[key]; 33 | 34 | results.push(walk(value, func)); 35 | } 36 | 37 | return results; 38 | } 39 | 40 | if (func(obj) === EXIT) { 41 | return obj; 42 | } 43 | 44 | return null; 45 | } 46 | 47 | function first(obj, func) { 48 | return walk(obj, (object, key, value) => { 49 | if (func(object, key, value)) { 50 | return EXIT; 51 | } 52 | 53 | return null; 54 | }); 55 | } 56 | 57 | function all(obj, func) { 58 | const results = []; 59 | 60 | walk(obj, (object, key, value) => { 61 | if (func(object, key, value)) { 62 | return results.push(object); 63 | } 64 | 65 | return null; 66 | }); 67 | 68 | return results; 69 | } 70 | 71 | function tables(query) { 72 | return all(query, (obj, key, value) => { 73 | return key === 'RangeVar'; 74 | }); 75 | } 76 | 77 | function byType(query, type) { 78 | return all(query, (object, key, value) => { 79 | return key === type; 80 | }); 81 | } 82 | 83 | function clean(tree) { 84 | walk(tree, (object, key, value) => { 85 | if (_.isArray(object)) { 86 | return; 87 | } 88 | 89 | if (key === 'location') { 90 | delete object.location; 91 | } 92 | }); 93 | 94 | return tree; 95 | } 96 | 97 | module.exports = { 98 | walk, 99 | first, 100 | all, 101 | tables, 102 | byType, 103 | clean 104 | }; 105 | -------------------------------------------------------------------------------- /test/fixtures/complex.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | p1.playerid, 3 | f1.playername, 4 | p2.playerid, 5 | f2.playername 6 | FROM 7 | player f1, 8 | player f2, 9 | plays p1 FULL OUTER JOIN plays p2 ON p1.playerid < p2.playerid AND p1.teamid = p2.teamid 10 | GROUP BY 11 | p1.playerid, 12 | f1.playerid, 13 | p2.playerid, 14 | f2.playerid 15 | HAVING 16 | count(p1.playerid) = count(*) AND count(p2.playerid) = count(*) AND p1.playerid = f1.playerid AND p2.playerid = f2.playerid; 17 | -------------------------------------------------------------------------------- /test/fixtures/custom.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM tab ORDER BY col USING <; 2 | 3 | SELECT * FROM tab ORDER BY col USING >; 4 | 5 | SELECT * FROM tab ORDER BY col USING =; 6 | 7 | SELECT * FROM tab ORDER BY col USING = NULLS FIRST, col2 USING < NULLS LAST; 8 | 9 | SELECT mleast(VARIADIC arr := ARRAY[10, -1, 5, 4.4]); 10 | 11 | SELECT encode(E'''123\\000\\001', 'base64'); 12 | 13 | SELECT U&'\0441\043B\043E\043D'; 14 | 15 | SELECT U&'d\0061t\+000061'; 16 | 17 | SELECT 3 OPERATOR(pg_catalog.+) 4; 18 | 19 | SELECT * FROM ROWS FROM( getfoo6(1) AS (fooid int, foosubid int, fooname text), getfoo7(1) as (fooid int, foosubid int, fooname text) ) AS (fooid int, foosubid int, fooname text); 20 | 21 | select a from b where a < (select 1); 22 | 23 | select a from b where a < all (select 1); 24 | 25 | select a from b where a < any (select 1); 26 | 27 | select a from b where exists (select 1); 28 | 29 | select a from b where a < ARRAY (select distinct (select 1), (select distinct 1 group by 7 having 1 < (select 1))); 30 | 31 | SELECT 1 WHERE 'abc' SIMILAR TO 'abc'; 32 | 33 | SELECT 1 WHERE 'abc' SIMILAR TO test('test'); 34 | 35 | SELECT 1 WHERE 'abc' SIMILAR TO test('test') ESCAPE 't'; 36 | 37 | select 1::bit; 38 | 39 | SET client_encoding='UNICODE'; 40 | 41 | SET client_encoding TO 'UNICODE'; 42 | 43 | SET client_min_messages=notice; 44 | 45 | SHOW client_encoding; 46 | -------------------------------------------------------------------------------- /test/fixtures/param-ref.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | * 3 | FROM 4 | table_name 5 | WHERE 6 | name = ?; 7 | 8 | SELECT 9 | * 10 | FROM 11 | table_name 12 | WHERE 13 | name = $1; 14 | 15 | SELECT 16 | $1::text as name; 17 | -------------------------------------------------------------------------------- /test/fixtures/query-001.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | array_agg(players), 3 | player_teams 4 | FROM 5 | (SELECT DISTINCT 6 | t1.t1player AS players_dist, 7 | t1.player_teams 8 | FROM 9 | (SELECT 10 | p.playerid AS t1id, 11 | concat(p.playerid, ':', p.playername, ' ') AS t1player, 12 | array_agg(pl.teamid ORDER BY pl.teamid) AS player_teams 13 | FROM player p 14 | LEFT JOIN plays pl ON p.playerid = pl.playerid 15 | GROUP BY p.playerid, p.playername 16 | ) t1 17 | INNER JOIN ( 18 | SELECT 19 | p.playerid AS t2id, 20 | array_agg(pl.teamid ORDER BY pl.teamid) AS player_teams 21 | FROM player p 22 | LEFT JOIN plays pl ON p.playerid = pl.playerid 23 | GROUP BY p.playerid, p.playername 24 | ) t2 ON t1.player_teams=t2.player_teams AND t1.t1id <> t2.t2id 25 | ) innerQuery 26 | GROUP BY player_teams; 27 | -------------------------------------------------------------------------------- /test/fixtures/query-002.sql: -------------------------------------------------------------------------------- 1 | SELECT * from "Foo" f1 2 | WHERE f1."FooUID" = ( 3 | SELECT f2."FooUID" FROM "Foo" f2 4 | LEFT JOIN "Bar" b ON f2."BarUID" = b."BarUID" 5 | WHERE f2."BarUID" IS NOT NULL AND b."BarUID" IS NULL 6 | LIMIT 1 7 | ) -------------------------------------------------------------------------------- /test/fixtures/query-003.sql: -------------------------------------------------------------------------------- 1 | SELECT ((SELECT ROW(1,1,1,1)::test)::test).*; -------------------------------------------------------------------------------- /test/fixtures/simple.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | * 3 | FROM 4 | table_name 5 | WHERE 6 | name = 'test' AND num > 7 AND last_name LIKE '%''test''%'; 7 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/alter_operator.sql: -------------------------------------------------------------------------------- 1 | CREATE FUNCTION alter_op_test_fn(boolean, boolean) 2 | RETURNS boolean AS $$ SELECT NULL::BOOLEAN; $$ LANGUAGE sql IMMUTABLE; 3 | 4 | CREATE FUNCTION customcontsel(internal, oid, internal, integer) 5 | RETURNS float8 AS 'contsel' LANGUAGE internal STABLE STRICT; 6 | 7 | CREATE OPERATOR === ( 8 | LEFTARG = boolean, 9 | RIGHTARG = boolean, 10 | PROCEDURE = alter_op_test_fn, 11 | COMMUTATOR = ===, 12 | NEGATOR = !==, 13 | RESTRICT = customcontsel, 14 | JOIN = contjoinsel, 15 | HASHES, MERGES 16 | ); 17 | 18 | SELECT pg_describe_object(refclassid,refobjid,refobjsubid) as ref, deptype 19 | FROM pg_depend 20 | WHERE classid = 'pg_operator'::regclass AND 21 | objid = '===(bool,bool)'::regoperator 22 | ORDER BY 1; 23 | 24 | -- 25 | -- Reset and set params 26 | -- 27 | 28 | ALTER OPERATOR === (boolean, boolean) SET (RESTRICT = NONE); 29 | ALTER OPERATOR === (boolean, boolean) SET (JOIN = NONE); 30 | 31 | SELECT oprrest, oprjoin FROM pg_operator WHERE oprname = '===' 32 | AND oprleft = 'boolean'::regtype AND oprright = 'boolean'::regtype; 33 | 34 | SELECT pg_describe_object(refclassid,refobjid,refobjsubid) as ref, deptype 35 | FROM pg_depend 36 | WHERE classid = 'pg_operator'::regclass AND 37 | objid = '===(bool,bool)'::regoperator 38 | ORDER BY 1; 39 | 40 | ALTER OPERATOR === (boolean, boolean) SET (RESTRICT = contsel); 41 | ALTER OPERATOR === (boolean, boolean) SET (JOIN = contjoinsel); 42 | 43 | SELECT oprrest, oprjoin FROM pg_operator WHERE oprname = '===' 44 | AND oprleft = 'boolean'::regtype AND oprright = 'boolean'::regtype; 45 | 46 | SELECT pg_describe_object(refclassid,refobjid,refobjsubid) as ref, deptype 47 | FROM pg_depend 48 | WHERE classid = 'pg_operator'::regclass AND 49 | objid = '===(bool,bool)'::regoperator 50 | ORDER BY 1; 51 | 52 | ALTER OPERATOR === (boolean, boolean) SET (RESTRICT = NONE, JOIN = NONE); 53 | 54 | SELECT oprrest, oprjoin FROM pg_operator WHERE oprname = '===' 55 | AND oprleft = 'boolean'::regtype AND oprright = 'boolean'::regtype; 56 | 57 | SELECT pg_describe_object(refclassid,refobjid,refobjsubid) as ref, deptype 58 | FROM pg_depend 59 | WHERE classid = 'pg_operator'::regclass AND 60 | objid = '===(bool,bool)'::regoperator 61 | ORDER BY 1; 62 | 63 | ALTER OPERATOR === (boolean, boolean) SET (RESTRICT = customcontsel, JOIN = contjoinsel); 64 | 65 | SELECT oprrest, oprjoin FROM pg_operator WHERE oprname = '===' 66 | AND oprleft = 'boolean'::regtype AND oprright = 'boolean'::regtype; 67 | 68 | SELECT pg_describe_object(refclassid,refobjid,refobjsubid) as ref, deptype 69 | FROM pg_depend 70 | WHERE classid = 'pg_operator'::regclass AND 71 | objid = '===(bool,bool)'::regoperator 72 | ORDER BY 1; 73 | 74 | -- 75 | -- Test invalid options. 76 | -- 77 | ALTER OPERATOR === (boolean, boolean) SET (COMMUTATOR = ====); 78 | ALTER OPERATOR === (boolean, boolean) SET (NEGATOR = ====); 79 | ALTER OPERATOR === (boolean, boolean) SET (RESTRICT = non_existent_func); 80 | ALTER OPERATOR === (boolean, boolean) SET (JOIN = non_existent_func); 81 | ALTER OPERATOR === (boolean, boolean) SET (COMMUTATOR = !==); 82 | ALTER OPERATOR === (boolean, boolean) SET (NEGATOR = !==); 83 | 84 | -- 85 | -- Test permission check. Must be owner to ALTER OPERATOR. 86 | -- 87 | CREATE USER regtest_alter_user; 88 | SET SESSION AUTHORIZATION regtest_alter_user; 89 | 90 | ALTER OPERATOR === (boolean, boolean) SET (RESTRICT = NONE); 91 | 92 | -- Clean up 93 | RESET SESSION AUTHORIZATION; 94 | DROP USER regtest_alter_user; 95 | DROP OPERATOR === (boolean, boolean); 96 | DROP FUNCTION customcontsel(internal, oid, internal, integer); 97 | DROP FUNCTION alter_op_test_fn(boolean, boolean); 98 | -------------------------------------------------------------------------------- /test/fixtures/upstream/async.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- ASYNC 3 | -- 4 | 5 | --Should work. Send a valid message via a valid channel name 6 | SELECT pg_notify('notify_async1','sample message1'); 7 | SELECT pg_notify('notify_async1',''); 8 | SELECT pg_notify('notify_async1',NULL); 9 | 10 | -- Should fail. Send a valid message via an invalid channel name 11 | SELECT pg_notify('','sample message1'); 12 | SELECT pg_notify(NULL,'sample message1'); 13 | SELECT pg_notify('notify_async_channel_name_too_long______________________________','sample_message1'); 14 | 15 | --Should work. Valid NOTIFY/LISTEN/UNLISTEN commands 16 | NOTIFY notify_async2; 17 | LISTEN notify_async2; 18 | UNLISTEN notify_async2; 19 | UNLISTEN *; 20 | 21 | -- Should return zero while there are no pending notifications. 22 | -- src/test/isolation/specs/async-notify.spec tests for actual usage. 23 | SELECT pg_notification_queue_usage(); 24 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | 68 | -- 69 | -- Test B-tree page deletion. In particular, deleting a non-leaf page. 70 | -- 71 | 72 | -- First create a tree that's at least four levels deep. The text inserted 73 | -- is long and poorly compressible. That way only a few index tuples fit on 74 | -- each page, allowing us to get a tall tree with fewer pages. 75 | create table btree_tall_tbl(id int4, t text); 76 | create index btree_tall_idx on btree_tall_tbl (id, t) with (fillfactor = 10); 77 | insert into btree_tall_tbl 78 | select g, g::text || '_' || 79 | (select string_agg(md5(i::text), '_') from generate_series(1, 50) i) 80 | from generate_series(1, 100) g; 81 | 82 | -- Delete most entries, and vacuum. This causes page deletions. 83 | delete from btree_tall_tbl where id < 950; 84 | vacuum btree_tall_tbl; 85 | 86 | -- 87 | -- Test B-tree insertion with a metapage update (XLOG_BTREE_INSERT_META 88 | -- WAL record type). This happens when a "fast root" page is split. 89 | -- 90 | 91 | -- The vacuum above should've turned the leaf page into a fast root. We just 92 | -- need to insert some rows to cause the fast root page to split. 93 | insert into btree_tall_tbl (id, t) 94 | select g, repeat('x', 100) from generate_series(1, 500) g; 95 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 SQL 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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/conversion.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- create user defined conversion 3 | -- 4 | CREATE USER conversion_test_user WITH NOCREATEDB NOCREATEROLE; 5 | SET SESSION AUTHORIZATION conversion_test_user; 6 | CREATE CONVERSION myconv FOR 'LATIN1' TO 'UTF8' FROM iso8859_1_to_utf8; 7 | -- 8 | -- cannot make same name conversion in same schema 9 | -- 10 | CREATE CONVERSION myconv FOR 'LATIN1' TO 'UTF8' FROM iso8859_1_to_utf8; 11 | -- 12 | -- create default conversion with qualified name 13 | -- 14 | CREATE DEFAULT CONVERSION public.mydef FOR 'LATIN1' TO 'UTF8' FROM iso8859_1_to_utf8; 15 | -- 16 | -- cannot make default conversion with same schema/for_encoding/to_encoding 17 | -- 18 | CREATE DEFAULT CONVERSION public.mydef2 FOR 'LATIN1' TO 'UTF8' FROM iso8859_1_to_utf8; 19 | -- test comments 20 | COMMENT ON CONVERSION myconv_bad IS 'foo'; 21 | COMMENT ON CONVERSION myconv IS 'bar'; 22 | COMMENT ON CONVERSION myconv IS NULL; 23 | -- 24 | -- drop user defined conversion 25 | -- 26 | DROP CONVERSION myconv; 27 | DROP CONVERSION mydef; 28 | -- 29 | -- Note: the built-in conversions are exercised in opr_sanity.sql, 30 | -- so there's no need to do that here. 31 | -- 32 | -- 33 | -- return to the super user 34 | -- 35 | RESET SESSION AUTHORIZATION; 36 | DROP USER conversion_test_user; 37 | -------------------------------------------------------------------------------- /test/fixtures/upstream/copydml.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- Test cases for COPY (INSERT/UPDATE/DELETE) TO 3 | -- 4 | create table copydml_test (id serial, t text); 5 | insert into copydml_test (t) values ('a'); 6 | insert into copydml_test (t) values ('b'); 7 | insert into copydml_test (t) values ('c'); 8 | insert into copydml_test (t) values ('d'); 9 | insert into copydml_test (t) values ('e'); 10 | 11 | -- 12 | -- Test COPY (insert/update/delete ...) 13 | -- 14 | copy (insert into copydml_test (t) values ('f') returning id) to stdout; 15 | copy (update copydml_test set t = 'g' where t = 'f' returning id) to stdout; 16 | copy (delete from copydml_test where t = 'g' returning id) to stdout; 17 | 18 | -- 19 | -- Test \copy (insert/update/delete ...) 20 | -- 21 | \copy (insert into copydml_test (t) values ('f') returning id) to stdout; 22 | \copy (update copydml_test set t = 'g' where t = 'f' returning id) to stdout; 23 | \copy (delete from copydml_test where t = 'g' returning id) to stdout; 24 | 25 | -- Error cases 26 | copy (insert into copydml_test default values) to stdout; 27 | copy (update copydml_test set t = 'g') to stdout; 28 | copy (delete from copydml_test) to stdout; 29 | 30 | create rule qqq as on insert to copydml_test do instead nothing; 31 | copy (insert into copydml_test default values) to stdout; 32 | drop rule qqq on copydml_test; 33 | create rule qqq as on insert to copydml_test do also delete from copydml_test; 34 | copy (insert into copydml_test default values) to stdout; 35 | drop rule qqq on copydml_test; 36 | create rule qqq as on insert to copydml_test do instead (delete from copydml_test; delete from copydml_test); 37 | copy (insert into copydml_test default values) to stdout; 38 | drop rule qqq on copydml_test; 39 | create rule qqq as on insert to copydml_test where new.t <> 'f' do instead delete from copydml_test; 40 | copy (insert into copydml_test default values) to stdout; 41 | drop rule qqq on copydml_test; 42 | 43 | create rule qqq as on update to copydml_test do instead nothing; 44 | copy (update copydml_test set t = 'f') to stdout; 45 | drop rule qqq on copydml_test; 46 | create rule qqq as on update to copydml_test do also delete from copydml_test; 47 | copy (update copydml_test set t = 'f') to stdout; 48 | drop rule qqq on copydml_test; 49 | create rule qqq as on update to copydml_test do instead (delete from copydml_test; delete from copydml_test); 50 | copy (update copydml_test set t = 'f') to stdout; 51 | drop rule qqq on copydml_test; 52 | create rule qqq as on update to copydml_test where new.t <> 'f' do instead delete from copydml_test; 53 | copy (update copydml_test set t = 'f') to stdout; 54 | drop rule qqq on copydml_test; 55 | 56 | create rule qqq as on delete to copydml_test do instead nothing; 57 | copy (delete from copydml_test) to stdout; 58 | drop rule qqq on copydml_test; 59 | create rule qqq as on delete to copydml_test do also insert into copydml_test default values; 60 | copy (delete from copydml_test) to stdout; 61 | drop rule qqq on copydml_test; 62 | create rule qqq as on delete to copydml_test do instead (insert into copydml_test default values; insert into copydml_test default values); 63 | copy (delete from copydml_test) to stdout; 64 | drop rule qqq on copydml_test; 65 | create rule qqq as on delete to copydml_test where old.t <> 'f' do instead insert into copydml_test default values; 66 | copy (delete from copydml_test) to stdout; 67 | drop rule qqq on copydml_test; 68 | 69 | -- triggers 70 | create function qqq_trig() returns trigger as $$ 71 | begin 72 | if tg_op in ('INSERT', 'UPDATE') then 73 | raise notice '% %', tg_op, new.id; 74 | return new; 75 | else 76 | raise notice '% %', tg_op, old.id; 77 | return old; 78 | end if; 79 | end 80 | $$ language plpgsql; 81 | create trigger qqqbef before insert or update or delete on copydml_test 82 | for each row execute procedure qqq_trig(); 83 | create trigger qqqaf after insert or update or delete on copydml_test 84 | for each row execute procedure qqq_trig(); 85 | 86 | copy (insert into copydml_test (t) values ('f') returning id) to stdout; 87 | copy (update copydml_test set t = 'g' where t = 'f' returning id) to stdout; 88 | copy (delete from copydml_test where t = 'g' returning id) to stdout; 89 | 90 | drop table copydml_test; 91 | drop function qqq_trig(); 92 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/create_am.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- Create access method tests 3 | -- 4 | 5 | -- Make gist2 over gisthandler. In fact, it would be a synonym to gist. 6 | CREATE ACCESS METHOD gist2 TYPE INDEX HANDLER gisthandler; 7 | 8 | -- Try to create gist2 index on fast_emp4000: fail because opclass doesn't exist 9 | CREATE INDEX grect2ind2 ON fast_emp4000 USING gist2 (home_base); 10 | 11 | -- Make operator class for boxes using gist2 12 | CREATE OPERATOR CLASS box_ops DEFAULT 13 | FOR TYPE box USING gist2 AS 14 | OPERATOR 1 <<, 15 | OPERATOR 2 &<, 16 | OPERATOR 3 &&, 17 | OPERATOR 4 &>, 18 | OPERATOR 5 >>, 19 | OPERATOR 6 ~=, 20 | OPERATOR 7 @>, 21 | OPERATOR 8 <@, 22 | OPERATOR 9 &<|, 23 | OPERATOR 10 <<|, 24 | OPERATOR 11 |>>, 25 | OPERATOR 12 |&>, 26 | OPERATOR 13 ~, 27 | OPERATOR 14 @, 28 | FUNCTION 1 gist_box_consistent(internal, box, smallint, oid, internal), 29 | FUNCTION 2 gist_box_union(internal, internal), 30 | FUNCTION 3 gist_box_compress(internal), 31 | FUNCTION 4 gist_box_decompress(internal), 32 | FUNCTION 5 gist_box_penalty(internal, internal, internal), 33 | FUNCTION 6 gist_box_picksplit(internal, internal), 34 | FUNCTION 7 gist_box_same(box, box, internal), 35 | FUNCTION 9 gist_box_fetch(internal); 36 | 37 | -- Create gist2 index on fast_emp4000 38 | CREATE INDEX grect2ind2 ON fast_emp4000 USING gist2 (home_base); 39 | 40 | -- Now check the results from plain indexscan; temporarily drop existing 41 | -- index grect2ind to ensure it doesn't capture the plan 42 | BEGIN; 43 | DROP INDEX grect2ind; 44 | SET enable_seqscan = OFF; 45 | SET enable_indexscan = ON; 46 | SET enable_bitmapscan = OFF; 47 | 48 | EXPLAIN (COSTS OFF) 49 | SELECT * FROM fast_emp4000 50 | WHERE home_base @ '(200,200),(2000,1000)'::box 51 | ORDER BY (home_base[0])[0]; 52 | SELECT * FROM fast_emp4000 53 | WHERE home_base @ '(200,200),(2000,1000)'::box 54 | ORDER BY (home_base[0])[0]; 55 | 56 | EXPLAIN (COSTS OFF) 57 | SELECT count(*) FROM fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box; 58 | SELECT count(*) FROM fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box; 59 | 60 | EXPLAIN (COSTS OFF) 61 | SELECT count(*) FROM fast_emp4000 WHERE home_base IS NULL; 62 | SELECT count(*) FROM fast_emp4000 WHERE home_base IS NULL; 63 | 64 | ROLLBACK; 65 | 66 | -- Try to drop access method: fail because of dependent objects 67 | DROP ACCESS METHOD gist2; 68 | 69 | -- Drop access method cascade 70 | DROP ACCESS METHOD gist2 CASCADE; 71 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 IMMUTABLE; 12 | CREATE FUNCTION casttesttype_out(casttesttype) 13 | RETURNS cstring 14 | AS 'textout' 15 | LANGUAGE internal STRICT IMMUTABLE; 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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -- also, let's leave one around for purposes of pg_dump testing 35 | CREATE TYPE myshell; 36 | 37 | -- 38 | -- Test type-related default values (broken in releases before PG 7.2) 39 | -- 40 | -- This part of the test also exercises the "new style" approach of making 41 | -- a shell type and then filling it in. 42 | -- 43 | CREATE TYPE int42; 44 | CREATE TYPE text_w_default; 45 | 46 | -- Make dummy I/O routines using the existing internal support for int4, text 47 | CREATE FUNCTION int42_in(cstring) 48 | RETURNS int42 49 | AS 'int4in' 50 | LANGUAGE internal STRICT IMMUTABLE; 51 | CREATE FUNCTION int42_out(int42) 52 | RETURNS cstring 53 | AS 'int4out' 54 | LANGUAGE internal STRICT IMMUTABLE; 55 | CREATE FUNCTION text_w_default_in(cstring) 56 | RETURNS text_w_default 57 | AS 'textin' 58 | LANGUAGE internal STRICT IMMUTABLE; 59 | CREATE FUNCTION text_w_default_out(text_w_default) 60 | RETURNS cstring 61 | AS 'textout' 62 | LANGUAGE internal STRICT IMMUTABLE; 63 | 64 | CREATE TYPE int42 ( 65 | internallength = 4, 66 | input = int42_in, 67 | output = int42_out, 68 | alignment = int4, 69 | default = 42, 70 | passedbyvalue 71 | ); 72 | 73 | CREATE TYPE text_w_default ( 74 | internallength = variable, 75 | input = text_w_default_in, 76 | output = text_w_default_out, 77 | alignment = int4, 78 | default = 'zippo' 79 | ); 80 | 81 | CREATE TABLE default_test (f1 text_w_default, f2 int42); 82 | 83 | INSERT INTO default_test DEFAULT VALUES; 84 | 85 | SELECT * FROM default_test; 86 | 87 | -- Test stand-alone composite type 88 | 89 | CREATE TYPE default_test_row AS (f1 text_w_default, f2 int42); 90 | 91 | CREATE FUNCTION get_default_test() RETURNS SETOF default_test_row AS ' 92 | SELECT * FROM default_test; 93 | ' LANGUAGE SQL; 94 | 95 | SELECT * FROM get_default_test(); 96 | 97 | -- Test comments 98 | COMMENT ON TYPE bad IS 'bad comment'; 99 | COMMENT ON TYPE default_test_row IS 'good comment'; 100 | COMMENT ON TYPE default_test_row IS NULL; 101 | COMMENT ON COLUMN default_test_row.nope IS 'bad comment'; 102 | COMMENT ON COLUMN default_test_row.f1 IS 'good comment'; 103 | COMMENT ON COLUMN default_test_row.f1 IS NULL; 104 | 105 | -- Check shell type create for existing types 106 | CREATE TYPE text_w_default; -- should fail 107 | 108 | DROP TYPE default_test_row CASCADE; 109 | 110 | DROP TABLE default_test; 111 | 112 | -- Check type create with input/output incompatibility 113 | CREATE TYPE not_existing_type (INPUT = array_in, 114 | OUTPUT = array_out, 115 | ELEMENT = int, 116 | INTERNALLENGTH = 32); 117 | 118 | -- Check usage of typmod with a user-defined type 119 | -- (we have borrowed numeric's typmod functions) 120 | 121 | CREATE TEMP TABLE mytab (foo widget(42,13,7)); -- should fail 122 | CREATE TEMP TABLE mytab (foo widget(42,13)); 123 | 124 | SELECT format_type(atttypid,atttypmod) FROM pg_attribute 125 | WHERE attrelid = 'mytab'::regclass AND attnum > 0; 126 | -------------------------------------------------------------------------------- /test/fixtures/upstream/dbsize.sql: -------------------------------------------------------------------------------- 1 | SELECT size, pg_size_pretty(size), pg_size_pretty(-1 * size) FROM 2 | (VALUES (10::bigint), (1000::bigint), (1000000::bigint), 3 | (1000000000::bigint), (1000000000000::bigint), 4 | (1000000000000000::bigint)) x(size); 5 | 6 | SELECT size, pg_size_pretty(size), pg_size_pretty(-1 * size) FROM 7 | (VALUES (10::numeric), (1000::numeric), (1000000::numeric), 8 | (1000000000::numeric), (1000000000000::numeric), 9 | (1000000000000000::numeric), 10 | (10.5::numeric), (1000.5::numeric), (1000000.5::numeric), 11 | (1000000000.5::numeric), (1000000000000.5::numeric), 12 | (1000000000000000.5::numeric)) x(size); 13 | 14 | SELECT size, pg_size_bytes(size) FROM 15 | (VALUES ('1'), ('123bytes'), ('1kB'), ('1MB'), (' 1 GB'), ('1.5 GB '), 16 | ('1TB'), ('3000 TB'), ('1e6 MB')) x(size); 17 | 18 | -- case-insensitive units are supported 19 | SELECT size, pg_size_bytes(size) FROM 20 | (VALUES ('1'), ('123bYteS'), ('1kb'), ('1mb'), (' 1 Gb'), ('1.5 gB '), 21 | ('1tb'), ('3000 tb'), ('1e6 mb')) x(size); 22 | 23 | -- negative numbers are supported 24 | SELECT size, pg_size_bytes(size) FROM 25 | (VALUES ('-1'), ('-123bytes'), ('-1kb'), ('-1mb'), (' -1 Gb'), ('-1.5 gB '), 26 | ('-1tb'), ('-3000 TB'), ('-10e-1 MB')) x(size); 27 | 28 | -- different cases with allowed points 29 | SELECT size, pg_size_bytes(size) FROM 30 | (VALUES ('-1.'), ('-1.kb'), ('-1. kb'), ('-0. gb'), 31 | ('-.1'), ('-.1kb'), ('-.1 kb'), ('-.0 gb')) x(size); 32 | 33 | -- invalid inputs 34 | SELECT pg_size_bytes('1 AB'); 35 | SELECT pg_size_bytes('1 AB A'); 36 | SELECT pg_size_bytes('1 AB A '); 37 | SELECT pg_size_bytes('9223372036854775807.9'); 38 | SELECT pg_size_bytes('1e100'); 39 | SELECT pg_size_bytes('1e1000000000000000000'); 40 | SELECT pg_size_bytes('1 byte'); -- the singular "byte" is not supported 41 | SELECT pg_size_bytes(''); 42 | 43 | SELECT pg_size_bytes('kb'); 44 | SELECT pg_size_bytes('..'); 45 | SELECT pg_size_bytes('-.'); 46 | SELECT pg_size_bytes('-.kb'); 47 | SELECT pg_size_bytes('-. kb'); 48 | 49 | SELECT pg_size_bytes('.+912'); 50 | SELECT pg_size_bytes('+912+ kB'); 51 | SELECT pg_size_bytes('++123 kB'); 52 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | GRANT CREATE ON DATABASE regression TO regression_user1; 78 | 79 | SET SESSION AUTHORIZATION regression_user1; 80 | CREATE SCHEMA deptest; 81 | CREATE TABLE deptest (a serial primary key, b text); 82 | ALTER DEFAULT PRIVILEGES FOR ROLE regression_user1 IN SCHEMA deptest 83 | GRANT ALL ON TABLES TO regression_user2; 84 | CREATE FUNCTION deptest_func() RETURNS void LANGUAGE plpgsql 85 | AS $$ BEGIN END; $$; 86 | CREATE TYPE deptest_enum AS ENUM ('red'); 87 | CREATE TYPE deptest_range AS RANGE (SUBTYPE = int4); 88 | 89 | CREATE TABLE deptest2 (f1 int); 90 | -- make a serial column the hard way 91 | CREATE SEQUENCE ss1; 92 | ALTER TABLE deptest2 ALTER f1 SET DEFAULT nextval('ss1'); 93 | ALTER SEQUENCE ss1 OWNED BY deptest2.f1; 94 | 95 | -- When reassigning ownership of a composite type, its pg_class entry 96 | -- should match 97 | CREATE TYPE deptest_t AS (a int); 98 | SELECT typowner = relowner 99 | FROM pg_type JOIN pg_class c ON typrelid = c.oid WHERE typname = 'deptest_t'; 100 | 101 | RESET SESSION AUTHORIZATION; 102 | REASSIGN OWNED BY regression_user1 TO regression_user2; 103 | \dt deptest 104 | 105 | SELECT typowner = relowner 106 | FROM pg_type JOIN pg_class c ON typrelid = c.oid WHERE typname = 'deptest_t'; 107 | 108 | -- doesn't work: grant still exists 109 | DROP USER regression_user1; 110 | DROP OWNED BY regression_user1; 111 | DROP USER regression_user1; 112 | 113 | \set VERBOSITY terse 114 | DROP USER regression_user2; 115 | DROP OWNED BY regression_user2, regression_user0; 116 | DROP USER regression_user2; 117 | DROP USER regression_user0; 118 | -------------------------------------------------------------------------------- /test/fixtures/upstream/drop_operator.sql: -------------------------------------------------------------------------------- 1 | CREATE OPERATOR === ( 2 | PROCEDURE = int8eq, 3 | LEFTARG = bigint, 4 | RIGHTARG = bigint, 5 | COMMUTATOR = === 6 | ); 7 | 8 | CREATE OPERATOR !== ( 9 | PROCEDURE = int8ne, 10 | LEFTARG = bigint, 11 | RIGHTARG = bigint, 12 | NEGATOR = ===, 13 | COMMUTATOR = !== 14 | ); 15 | 16 | DROP OPERATOR !==(bigint, bigint); 17 | 18 | SELECT ctid, oprcom 19 | FROM pg_catalog.pg_operator fk 20 | WHERE oprcom != 0 AND 21 | NOT EXISTS(SELECT 1 FROM pg_catalog.pg_operator pk WHERE pk.oid = fk.oprcom); 22 | 23 | SELECT ctid, oprnegate 24 | FROM pg_catalog.pg_operator fk 25 | WHERE oprnegate != 0 AND 26 | NOT EXISTS(SELECT 1 FROM pg_catalog.pg_operator pk WHERE pk.oid = fk.oprnegate); 27 | 28 | DROP OPERATOR ===(bigint, bigint); 29 | 30 | CREATE OPERATOR <| ( 31 | PROCEDURE = int8lt, 32 | LEFTARG = bigint, 33 | RIGHTARG = bigint 34 | ); 35 | 36 | CREATE OPERATOR |> ( 37 | PROCEDURE = int8gt, 38 | LEFTARG = bigint, 39 | RIGHTARG = bigint, 40 | NEGATOR = <|, 41 | COMMUTATOR = <| 42 | ); 43 | 44 | DROP OPERATOR |>(bigint, bigint); 45 | 46 | SELECT ctid, oprcom 47 | FROM pg_catalog.pg_operator fk 48 | WHERE oprcom != 0 AND 49 | NOT EXISTS(SELECT 1 FROM pg_catalog.pg_operator pk WHERE pk.oid = fk.oprcom); 50 | 51 | SELECT ctid, oprnegate 52 | FROM pg_catalog.pg_operator fk 53 | WHERE oprnegate != 0 AND 54 | NOT EXISTS(SELECT 1 FROM pg_catalog.pg_operator pk WHERE pk.oid = fk.oprnegate); 55 | 56 | DROP OPERATOR <|(bigint, bigint); 57 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -- Boxes 63 | -- 64 | 65 | SELECT '' as six, box(f1) AS box FROM CIRCLE_TBL; 66 | 67 | -- translation 68 | SELECT '' AS twentyfour, b.f1 + p.f1 AS translation 69 | FROM BOX_TBL b, POINT_TBL p; 70 | 71 | SELECT '' AS twentyfour, b.f1 - p.f1 AS translation 72 | FROM BOX_TBL b, POINT_TBL p; 73 | 74 | -- scaling and rotation 75 | SELECT '' AS twentyfour, b.f1 * p.f1 AS rotation 76 | FROM BOX_TBL b, POINT_TBL p; 77 | 78 | SELECT '' AS twenty, b.f1 / p.f1 AS rotation 79 | FROM BOX_TBL b, POINT_TBL p 80 | WHERE (p.f1 <-> point '(0,0)') >= 1; 81 | 82 | SELECT f1::box 83 | FROM POINT_TBL; 84 | 85 | SELECT bound_box(a.f1, b.f1) 86 | FROM BOX_TBL a, BOX_TBL b; 87 | 88 | -- 89 | -- Paths 90 | -- 91 | 92 | SELECT '' AS eight, npoints(f1) AS npoints, f1 AS path FROM PATH_TBL; 93 | 94 | SELECT '' AS four, path(f1) FROM POLYGON_TBL; 95 | 96 | -- translation 97 | SELECT '' AS eight, p1.f1 + point '(10,10)' AS dist_add 98 | FROM PATH_TBL p1; 99 | 100 | -- scaling and rotation 101 | SELECT '' AS eight, p1.f1 * point '(2,-1)' AS dist_mul 102 | FROM PATH_TBL p1; 103 | 104 | -- 105 | -- Polygons 106 | -- 107 | 108 | -- containment 109 | SELECT '' AS twentyfour, p.f1, poly.f1, poly.f1 @> p.f1 AS contains 110 | FROM POLYGON_TBL poly, POINT_TBL p; 111 | 112 | SELECT '' AS twentyfour, p.f1, poly.f1, p.f1 <@ poly.f1 AS contained 113 | FROM POLYGON_TBL poly, POINT_TBL p; 114 | 115 | SELECT '' AS four, npoints(f1) AS npoints, f1 AS polygon 116 | FROM POLYGON_TBL; 117 | 118 | SELECT '' AS four, polygon(f1) 119 | FROM BOX_TBL; 120 | 121 | SELECT '' AS four, polygon(f1) 122 | FROM PATH_TBL WHERE isclosed(f1); 123 | 124 | SELECT '' AS four, f1 AS open_path, polygon( pclose(f1)) AS polygon 125 | FROM PATH_TBL 126 | WHERE isopen(f1); 127 | 128 | -- convert circles to polygons using the default number of points 129 | SELECT '' AS six, polygon(f1) 130 | FROM CIRCLE_TBL; 131 | 132 | -- convert the circle to an 8-point polygon 133 | SELECT '' AS six, polygon(8, f1) 134 | FROM CIRCLE_TBL; 135 | 136 | -- 137 | -- Circles 138 | -- 139 | 140 | SELECT '' AS six, circle(f1, 50.0) 141 | FROM POINT_TBL; 142 | 143 | SELECT '' AS four, circle(f1) 144 | FROM BOX_TBL; 145 | 146 | SELECT '' AS two, circle(f1) 147 | FROM POLYGON_TBL 148 | WHERE (# f1) >= 3; 149 | 150 | SELECT '' AS twentyfour, c1.f1 AS circle, p1.f1 AS point, (p1.f1 <-> c1.f1) AS distance 151 | FROM CIRCLE_TBL c1, POINT_TBL p1 152 | WHERE (p1.f1 <-> c1.f1) > 0 153 | ORDER BY distance, area(c1.f1), p1.f1[0]; 154 | -------------------------------------------------------------------------------- /test/fixtures/upstream/gin.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- Test GIN indexes. 3 | -- 4 | -- There are other tests to test different GIN opclassed. This is for testing 5 | -- GIN itself. 6 | 7 | -- Create and populate a test table with a GIN index. 8 | create table gin_test_tbl(i int4[]) with (autovacuum_enabled = off); 9 | create index gin_test_idx on gin_test_tbl using gin (i) 10 | with (fastupdate = on, gin_pending_list_limit = 4096); 11 | insert into gin_test_tbl select array[1, 2, g] from generate_series(1, 20000) g; 12 | insert into gin_test_tbl select array[1, 3, g] from generate_series(1, 1000) g; 13 | 14 | select gin_clean_pending_list('gin_test_idx')>10 as many; -- flush the fastupdate buffers 15 | 16 | insert into gin_test_tbl select array[3, 1, g] from generate_series(1, 1000) g; 17 | 18 | vacuum gin_test_tbl; -- flush the fastupdate buffers 19 | 20 | select gin_clean_pending_list('gin_test_idx'); -- nothing to flush 21 | 22 | -- Test vacuuming 23 | delete from gin_test_tbl where i @> array[2]; 24 | vacuum gin_test_tbl; 25 | 26 | -- Disable fastupdate, and do more insertions. With fastupdate enabled, most 27 | -- insertions (by flushing the list pages) cause page splits. Without 28 | -- fastupdate, we get more churn in the GIN data leaf pages, and exercise the 29 | -- recompression codepaths. 30 | alter index gin_test_idx set (fastupdate = off); 31 | 32 | insert into gin_test_tbl select array[1, 2, g] from generate_series(1, 1000) g; 33 | insert into gin_test_tbl select array[1, 3, g] from generate_series(1, 1000) g; 34 | 35 | delete from gin_test_tbl where i @> array[2]; 36 | vacuum gin_test_tbl; 37 | -------------------------------------------------------------------------------- /test/fixtures/upstream/gist.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- Test GiST indexes. 3 | -- 4 | -- There are other tests to test different GiST opclasses. This is for 5 | -- testing GiST code itself. Vacuuming in particular. 6 | 7 | create table gist_point_tbl(id int4, p point); 8 | create index gist_pointidx on gist_point_tbl using gist(p); 9 | 10 | -- Insert enough data to create a tree that's a couple of levels deep. 11 | insert into gist_point_tbl (id, p) 12 | select g, point(g*10, g*10) from generate_series(1, 10000) g; 13 | 14 | insert into gist_point_tbl (id, p) 15 | select g+100000, point(g*10+1, g*10+1) from generate_series(1, 10000) g; 16 | 17 | -- To test vacuum, delete some entries from all over the index. 18 | delete from gist_point_tbl where id % 2 = 1; 19 | 20 | -- And also delete some concentration of values. (GiST doesn't currently 21 | -- attempt to delete pages even when they become empty, but if it did, this 22 | -- would exercise it) 23 | delete from gist_point_tbl where id < 10000; 24 | 25 | vacuum analyze gist_point_tbl; 26 | 27 | 28 | -- 29 | -- Test Index-only plans on GiST indexes 30 | -- 31 | 32 | create table gist_tbl (b box, p point, c circle); 33 | 34 | insert into gist_tbl 35 | select box(point(0.05*i, 0.05*i), point(0.05*i, 0.05*i)), 36 | point(0.05*i, 0.05*i), 37 | circle(point(0.05*i, 0.05*i), 1.0) 38 | from generate_series(0,10000) as i; 39 | 40 | vacuum analyze gist_tbl; 41 | 42 | set enable_seqscan=off; 43 | set enable_bitmapscan=off; 44 | set enable_indexonlyscan=on; 45 | 46 | -- Test index-only scan with point opclass 47 | create index gist_tbl_point_index on gist_tbl using gist (p); 48 | 49 | -- check that the planner chooses an index-only scan 50 | explain (costs off) 51 | select p from gist_tbl where p <@ box(point(0,0), point(0.5, 0.5)); 52 | 53 | -- execute the same 54 | select p from gist_tbl where p <@ box(point(0,0), point(0.5, 0.5)); 55 | 56 | -- Also test an index-only knn-search 57 | explain (costs off) 58 | select p from gist_tbl where p <@ box(point(0,0), point(0.5, 0.5)) 59 | order by p <-> point(0.201, 0.201); 60 | 61 | select p from gist_tbl where p <@ box(point(0,0), point(0.5, 0.5)) 62 | order by p <-> point(0.201, 0.201); 63 | 64 | -- Check commuted case as well 65 | explain (costs off) 66 | select p from gist_tbl where p <@ box(point(0,0), point(0.5, 0.5)) 67 | order by point(0.101, 0.101) <-> p; 68 | 69 | select p from gist_tbl where p <@ box(point(0,0), point(0.5, 0.5)) 70 | order by point(0.101, 0.101) <-> p; 71 | 72 | drop index gist_tbl_point_index; 73 | 74 | -- Test index-only scan with box opclass 75 | create index gist_tbl_box_index on gist_tbl using gist (b); 76 | 77 | -- check that the planner chooses an index-only scan 78 | explain (costs off) 79 | select b from gist_tbl where b <@ box(point(5,5), point(6,6)); 80 | 81 | -- execute the same 82 | select b from gist_tbl where b <@ box(point(5,5), point(6,6)); 83 | 84 | drop index gist_tbl_box_index; 85 | 86 | -- Test that an index-only scan is not chosen, when the query involves the 87 | -- circle column (the circle opclass does not support index-only scans). 88 | create index gist_tbl_multi_index on gist_tbl using gist (p, c); 89 | 90 | explain (costs off) 91 | select p, c from gist_tbl 92 | where p <@ box(point(5,5), point(6, 6)); 93 | 94 | -- execute the same 95 | select b, p from gist_tbl 96 | where b <@ box(point(4.5, 4.5), point(5.5, 5.5)) 97 | and p <@ box(point(5,5), point(6, 6)); 98 | 99 | drop index gist_tbl_multi_index; 100 | 101 | -- Clean up 102 | reset enable_seqscan; 103 | reset enable_bitmapscan; 104 | reset enable_indexonlyscan; 105 | 106 | drop table gist_tbl; 107 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 repeatable read; 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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/indirect_toast.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE toasttest(descr text, cnt int DEFAULT 0, f1 text, f2 text); 2 | 3 | INSERT INTO toasttest(descr, f1, f2) VALUES('two-compressed', repeat('1234567890',1000), repeat('1234567890',1000)); 4 | INSERT INTO toasttest(descr, f1, f2) VALUES('two-toasted', repeat('1234567890',30000), repeat('1234567890',50000)); 5 | INSERT INTO toasttest(descr, f1, f2) VALUES('one-compressed,one-null', NULL, repeat('1234567890',1000)); 6 | INSERT INTO toasttest(descr, f1, f2) VALUES('one-toasted,one-null', NULL, repeat('1234567890',50000)); 7 | 8 | -- check whether indirect tuples works on the most basic level 9 | SELECT descr, substring(make_tuple_indirect(toasttest)::text, 1, 200) FROM toasttest; 10 | 11 | -- modification without changing varlenas 12 | UPDATE toasttest SET cnt = cnt +1 RETURNING substring(toasttest::text, 1, 200); 13 | 14 | -- modification without modifying asigned value 15 | UPDATE toasttest SET cnt = cnt +1, f1 = f1 RETURNING substring(toasttest::text, 1, 200); 16 | 17 | -- modification modifying, but effectively not changing 18 | UPDATE toasttest SET cnt = cnt +1, f1 = f1||'' RETURNING substring(toasttest::text, 1, 200); 19 | 20 | UPDATE toasttest SET cnt = cnt +1, f1 = '-'||f1||'-' RETURNING substring(toasttest::text, 1, 200); 21 | 22 | SELECT substring(toasttest::text, 1, 200) FROM toasttest; 23 | -- check we didn't screw with main/toast tuple visiblity 24 | VACUUM FREEZE toasttest; 25 | SELECT substring(toasttest::text, 1, 200) FROM toasttest; 26 | 27 | -- now create a trigger that forces all Datums to be indirect ones 28 | CREATE FUNCTION update_using_indirect() 29 | RETURNS trigger 30 | LANGUAGE plpgsql AS $$ 31 | BEGIN 32 | NEW := make_tuple_indirect(NEW); 33 | RETURN NEW; 34 | END$$; 35 | 36 | CREATE TRIGGER toasttest_update_indirect 37 | BEFORE INSERT OR UPDATE 38 | ON toasttest 39 | FOR EACH ROW 40 | EXECUTE PROCEDURE update_using_indirect(); 41 | 42 | -- modification without changing varlenas 43 | UPDATE toasttest SET cnt = cnt +1 RETURNING substring(toasttest::text, 1, 200); 44 | 45 | -- modification without modifying asigned value 46 | UPDATE toasttest SET cnt = cnt +1, f1 = f1 RETURNING substring(toasttest::text, 1, 200); 47 | 48 | -- modification modifying, but effectively not changing 49 | UPDATE toasttest SET cnt = cnt +1, f1 = f1||'' RETURNING substring(toasttest::text, 1, 200); 50 | 51 | UPDATE toasttest SET cnt = cnt +1, f1 = '-'||f1||'-' RETURNING substring(toasttest::text, 1, 200); 52 | 53 | INSERT INTO toasttest(descr, f1, f2) VALUES('one-toasted,one-null, via indirect', repeat('1234567890',30000), NULL); 54 | 55 | SELECT substring(toasttest::text, 1, 200) FROM toasttest; 56 | -- check we didn't screw with main/toast tuple visiblity 57 | VACUUM FREEZE toasttest; 58 | SELECT substring(toasttest::text, 1, 200) FROM toasttest; 59 | 60 | DROP TABLE toasttest; 61 | DROP FUNCTION update_using_indirect(); 62 | -------------------------------------------------------------------------------- /test/fixtures/upstream/init_privs.sql: -------------------------------------------------------------------------------- 1 | -- Test iniital privileges 2 | 3 | -- There should always be some initial privileges, set up by initdb 4 | SELECT count(*) > 0 FROM pg_init_privs; 5 | 6 | -- Intentionally include some non-initial privs for pg_dump to dump out 7 | GRANT SELECT ON pg_proc TO CURRENT_USER; 8 | GRANT SELECT (prosrc) ON pg_proc TO CURRENT_USER; 9 | 10 | GRANT SELECT (rolname, rolsuper) ON pg_authid TO CURRENT_USER; 11 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | 91 | -- check sane handling of INT16_MIN overflow cases 92 | SELECT (-32768)::int2 * (-1)::int2; 93 | SELECT (-32768)::int2 / (-1)::int2; 94 | SELECT (-32768)::int2 % (-1)::int2; 95 | 96 | -- check rounding when casting from float 97 | SELECT x, x::int2 AS int2_value 98 | FROM (VALUES (-2.5::float8), 99 | (-1.5::float8), 100 | (-0.5::float8), 101 | (0.0::float8), 102 | (0.5::float8), 103 | (1.5::float8), 104 | (2.5::float8)) t(x); 105 | 106 | -- check rounding when casting from numeric 107 | SELECT x, x::int2 AS int2_value 108 | FROM (VALUES (-2.5::numeric), 109 | (-1.5::numeric), 110 | (-0.5::numeric), 111 | (0.0::numeric), 112 | (0.5::numeric), 113 | (1.5::numeric), 114 | (2.5::numeric)) t(x); 115 | -------------------------------------------------------------------------------- /test/fixtures/upstream/json_encoding.sql: -------------------------------------------------------------------------------- 1 | 2 | -- encoding-sensitive tests for json and jsonb 3 | 4 | -- first json 5 | 6 | -- basic unicode input 7 | SELECT '"\u"'::json; -- ERROR, incomplete escape 8 | SELECT '"\u00"'::json; -- ERROR, incomplete escape 9 | SELECT '"\u000g"'::json; -- ERROR, g is not a hex digit 10 | SELECT '"\u0000"'::json; -- OK, legal escape 11 | SELECT '"\uaBcD"'::json; -- OK, uppercase and lower case both OK 12 | 13 | -- handling of unicode surrogate pairs 14 | 15 | select json '{ "a": "\ud83d\ude04\ud83d\udc36" }' -> 'a' as correct_in_utf8; 16 | select json '{ "a": "\ud83d\ud83d" }' -> 'a'; -- 2 high surrogates in a row 17 | select json '{ "a": "\ude04\ud83d" }' -> 'a'; -- surrogates in wrong order 18 | select json '{ "a": "\ud83dX" }' -> 'a'; -- orphan high surrogate 19 | select json '{ "a": "\ude04X" }' -> 'a'; -- orphan low surrogate 20 | 21 | --handling of simple unicode escapes 22 | 23 | select json '{ "a": "the Copyright \u00a9 sign" }' as correct_in_utf8; 24 | select json '{ "a": "dollar \u0024 character" }' as correct_everywhere; 25 | select json '{ "a": "dollar \\u0024 character" }' as not_an_escape; 26 | select json '{ "a": "null \u0000 escape" }' as not_unescaped; 27 | select json '{ "a": "null \\u0000 escape" }' as not_an_escape; 28 | 29 | select json '{ "a": "the Copyright \u00a9 sign" }' ->> 'a' as correct_in_utf8; 30 | select json '{ "a": "dollar \u0024 character" }' ->> 'a' as correct_everywhere; 31 | select json '{ "a": "dollar \\u0024 character" }' ->> 'a' as not_an_escape; 32 | select json '{ "a": "null \u0000 escape" }' ->> 'a' as fails; 33 | select json '{ "a": "null \\u0000 escape" }' ->> 'a' as not_an_escape; 34 | 35 | -- then jsonb 36 | 37 | -- basic unicode input 38 | SELECT '"\u"'::jsonb; -- ERROR, incomplete escape 39 | SELECT '"\u00"'::jsonb; -- ERROR, incomplete escape 40 | SELECT '"\u000g"'::jsonb; -- ERROR, g is not a hex digit 41 | SELECT '"\u0045"'::jsonb; -- OK, legal escape 42 | SELECT '"\u0000"'::jsonb; -- ERROR, we don't support U+0000 43 | -- use octet_length here so we don't get an odd unicode char in the 44 | -- output 45 | SELECT octet_length('"\uaBcD"'::jsonb::text); -- OK, uppercase and lower case both OK 46 | 47 | -- handling of unicode surrogate pairs 48 | 49 | SELECT octet_length((jsonb '{ "a": "\ud83d\ude04\ud83d\udc36" }' -> 'a')::text) AS correct_in_utf8; 50 | SELECT jsonb '{ "a": "\ud83d\ud83d" }' -> 'a'; -- 2 high surrogates in a row 51 | SELECT jsonb '{ "a": "\ude04\ud83d" }' -> 'a'; -- surrogates in wrong order 52 | SELECT jsonb '{ "a": "\ud83dX" }' -> 'a'; -- orphan high surrogate 53 | SELECT jsonb '{ "a": "\ude04X" }' -> 'a'; -- orphan low surrogate 54 | 55 | -- handling of simple unicode escapes 56 | 57 | SELECT jsonb '{ "a": "the Copyright \u00a9 sign" }' as correct_in_utf8; 58 | SELECT jsonb '{ "a": "dollar \u0024 character" }' as correct_everywhere; 59 | SELECT jsonb '{ "a": "dollar \\u0024 character" }' as not_an_escape; 60 | SELECT jsonb '{ "a": "null \u0000 escape" }' as fails; 61 | SELECT jsonb '{ "a": "null \\u0000 escape" }' as not_an_escape; 62 | 63 | SELECT jsonb '{ "a": "the Copyright \u00a9 sign" }' ->> 'a' as correct_in_utf8; 64 | SELECT jsonb '{ "a": "dollar \u0024 character" }' ->> 'a' as correct_everywhere; 65 | SELECT jsonb '{ "a": "dollar \\u0024 character" }' ->> 'a' as not_an_escape; 66 | SELECT jsonb '{ "a": "null \u0000 escape" }' ->> 'a' as fails; 67 | SELECT jsonb '{ "a": "null \\u0000 escape" }' ->> 'a' as not_an_escape; 68 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | 43 | -- 44 | -- Test behavior of volatile and set-returning functions in conjunction 45 | -- with ORDER BY and LIMIT. 46 | -- 47 | 48 | create temp sequence testseq; 49 | 50 | explain (verbose, costs off) 51 | select unique1, unique2, nextval('testseq') 52 | from tenk1 order by unique2 limit 10; 53 | 54 | select unique1, unique2, nextval('testseq') 55 | from tenk1 order by unique2 limit 10; 56 | 57 | select currval('testseq'); 58 | 59 | explain (verbose, costs off) 60 | select unique1, unique2, nextval('testseq') 61 | from tenk1 order by tenthous limit 10; 62 | 63 | select unique1, unique2, nextval('testseq') 64 | from tenk1 order by tenthous limit 10; 65 | 66 | select currval('testseq'); 67 | 68 | explain (verbose, costs off) 69 | select unique1, unique2, generate_series(1,10) 70 | from tenk1 order by unique2 limit 7; 71 | 72 | select unique1, unique2, generate_series(1,10) 73 | from tenk1 order by unique2 limit 7; 74 | 75 | explain (verbose, costs off) 76 | select unique1, unique2, generate_series(1,10) 77 | from tenk1 order by tenthous limit 7; 78 | 79 | select unique1, unique2, generate_series(1,10) 80 | from tenk1 order by tenthous limit 7; 81 | 82 | -- use of random() is to keep planner from folding the expressions together 83 | explain (verbose, costs off) 84 | select generate_series(0,2) as s1, generate_series((random()*.1)::int,2) as s2; 85 | 86 | select generate_series(0,2) as s1, generate_series((random()*.1)::int,2) as s2; 87 | 88 | explain (verbose, costs off) 89 | select generate_series(0,2) as s1, generate_series((random()*.1)::int,2) as s2 90 | order by s2 desc; 91 | 92 | select generate_series(0,2) as s1, generate_series((random()*.1)::int,2) as s2 93 | order by s2 desc; 94 | -------------------------------------------------------------------------------- /test/fixtures/upstream/line.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- LINE 3 | -- Infinite lines 4 | -- 5 | 6 | --DROP TABLE LINE_TBL; 7 | CREATE TABLE LINE_TBL (s line); 8 | 9 | INSERT INTO LINE_TBL VALUES ('{1,-1,1}'); 10 | INSERT INTO LINE_TBL VALUES ('(0,0),(6,6)'); 11 | INSERT INTO LINE_TBL VALUES ('10,-10 ,-5,-4'); 12 | INSERT INTO LINE_TBL VALUES ('[-1e6,2e2,3e5, -4e1]'); 13 | INSERT INTO LINE_TBL VALUES ('(11,22,33,44)'); 14 | 15 | INSERT INTO LINE_TBL VALUES ('[(1,0),(1,0)]'); 16 | 17 | -- horizontal 18 | INSERT INTO LINE_TBL VALUES ('[(1,3),(2,3)]'); 19 | -- vertical 20 | INSERT INTO LINE_TBL VALUES ('[(3,1),(3,2)]'); 21 | 22 | -- bad values for parser testing 23 | INSERT INTO LINE_TBL VALUES ('{0,0,1}'); 24 | INSERT INTO LINE_TBL VALUES ('(3asdf,2 ,3,4r2)'); 25 | INSERT INTO LINE_TBL VALUES ('[1,2,3, 4'); 26 | INSERT INTO LINE_TBL VALUES ('[(,2),(3,4)]'); 27 | INSERT INTO LINE_TBL VALUES ('[(1,2),(3,4)'); 28 | 29 | select * from LINE_TBL; 30 | 31 | 32 | -- functions and operators 33 | 34 | SELECT * FROM LINE_TBL WHERE (s <-> line '[(1,2),(3,4)]') < 10; 35 | 36 | SELECT * FROM LINE_TBL WHERE (point '(0.1,0.1)' <-> s) < 1; 37 | 38 | SELECT * FROM LINE_TBL WHERE (lseg '[(0.1,0.1),(0.2,0.2)]' <-> s) < 1; 39 | 40 | SELECT line '[(1,1),(2,1)]' <-> line '[(-1,-1),(-2,-1)]'; 41 | SELECT lseg '[(1,1),(2,1)]' <-> line '[(-1,-1),(-2,-1)]'; 42 | SELECT point '(-1,1)' <-> line '[(-3,0),(-4,0)]'; 43 | 44 | SELECT lseg '[(1,1),(5,5)]' ?# line '[(2,0),(0,2)]'; -- true 45 | SELECT lseg '[(1,1),(5,5)]' ?# line '[(0,0),(1,0)]'; -- false 46 | 47 | SELECT line '[(0,0),(1,1)]' ?# box '(0,0,2,2)'; -- true 48 | SELECT line '[(3,0),(4,1)]' ?# box '(0,0,2,2)'; -- false 49 | 50 | SELECT point '(1,1)' <@ line '[(0,0),(2,2)]'; -- true 51 | SELECT point '(1,1)' <@ line '[(0,0),(1,0)]'; -- false 52 | 53 | SELECT point '(1,1)' @ line '[(0,0),(2,2)]'; -- true 54 | SELECT point '(1,1)' @ line '[(0,0),(1,0)]'; -- false 55 | 56 | SELECT lseg '[(1,1),(2,2)]' <@ line '[(0,0),(2,2)]'; -- true 57 | SELECT lseg '[(1,1),(2,1)]' <@ line '[(0,0),(1,0)]'; -- false 58 | 59 | SELECT lseg '[(1,1),(2,2)]' @ line '[(0,0),(2,2)]'; -- true 60 | SELECT lseg '[(1,1),(2,1)]' @ line '[(0,0),(1,0)]'; -- false 61 | 62 | SELECT point '(0,1)' ## line '[(0,0),(1,1)]'; 63 | 64 | SELECT line '[(0,0),(1,1)]' ## lseg '[(1,0),(2,0)]'; 65 | 66 | SELECT line '[(0,0),(1,1)]' ?# line '[(1,0),(2,1)]'; -- false 67 | SELECT line '[(0,0),(1,1)]' ?# line '[(1,0),(1,1)]'; -- true 68 | 69 | SELECT line '[(0,0),(1,1)]' # line '[(1,0),(2,1)]'; 70 | SELECT line '[(0,0),(1,1)]' # line '[(1,0),(1,1)]'; 71 | 72 | SELECT line '[(0,0),(1,1)]' ?|| line '[(1,0),(2,1)]'; -- true 73 | SELECT line '[(0,0),(1,1)]' ?|| line '[(1,0),(1,1)]'; -- false 74 | 75 | SELECT line '[(0,0),(1,0)]' ?-| line '[(0,0),(0,1)]'; -- true 76 | SELECT line '[(0,0),(1,1)]' ?-| line '[(1,0),(1,1)]'; -- false 77 | 78 | SELECT ?- line '[(0,0),(1,0)]'; -- true 79 | SELECT ?- line '[(0,0),(1,1)]'; -- false 80 | 81 | SELECT ?| line '[(0,0),(0,1)]'; -- true 82 | SELECT ?| line '[(0,0),(1,1)]'; -- false 83 | 84 | SELECT line(point '(1,2)', point '(3,4)'); 85 | 86 | SELECT line '[(1,2),(3,4)]' = line '[(3,4),(4,5)]'; -- true 87 | SELECT line '[(1,2),(3,4)]' = line '[(3,4),(4,4)]'; -- false 88 | -------------------------------------------------------------------------------- /test/fixtures/upstream/lock.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- Test the LOCK statement 3 | -- 4 | 5 | -- Setup 6 | CREATE SCHEMA lock_schema1; 7 | SET search_path = lock_schema1; 8 | CREATE TABLE lock_tbl1 (a BIGINT); 9 | CREATE VIEW lock_view1 AS SELECT 1; 10 | CREATE ROLE regress_rol_lock1; 11 | ALTER ROLE regress_rol_lock1 SET search_path = lock_schema1; 12 | GRANT USAGE ON SCHEMA lock_schema1 TO regress_rol_lock1; 13 | 14 | -- Try all valid lock options; also try omitting the optional TABLE keyword. 15 | BEGIN TRANSACTION; 16 | LOCK TABLE lock_tbl1 IN ACCESS SHARE MODE; 17 | LOCK lock_tbl1 IN ROW SHARE MODE; 18 | LOCK TABLE lock_tbl1 IN ROW EXCLUSIVE MODE; 19 | LOCK TABLE lock_tbl1 IN SHARE UPDATE EXCLUSIVE MODE; 20 | LOCK TABLE lock_tbl1 IN SHARE MODE; 21 | LOCK lock_tbl1 IN SHARE ROW EXCLUSIVE MODE; 22 | LOCK TABLE lock_tbl1 IN EXCLUSIVE MODE; 23 | LOCK TABLE lock_tbl1 IN ACCESS EXCLUSIVE MODE; 24 | ROLLBACK; 25 | 26 | -- Try using NOWAIT along with valid options. 27 | BEGIN TRANSACTION; 28 | LOCK TABLE lock_tbl1 IN ACCESS SHARE MODE NOWAIT; 29 | LOCK TABLE lock_tbl1 IN ROW SHARE MODE NOWAIT; 30 | LOCK TABLE lock_tbl1 IN ROW EXCLUSIVE MODE NOWAIT; 31 | LOCK TABLE lock_tbl1 IN SHARE UPDATE EXCLUSIVE MODE NOWAIT; 32 | LOCK TABLE lock_tbl1 IN SHARE MODE NOWAIT; 33 | LOCK TABLE lock_tbl1 IN SHARE ROW EXCLUSIVE MODE NOWAIT; 34 | LOCK TABLE lock_tbl1 IN EXCLUSIVE MODE NOWAIT; 35 | LOCK TABLE lock_tbl1 IN ACCESS EXCLUSIVE MODE NOWAIT; 36 | LOCK TABLE lock_view1 IN EXCLUSIVE MODE; -- Will fail; can't lock a non-table 37 | ROLLBACK; 38 | 39 | -- Verify that we can lock a table with inheritance children. 40 | CREATE TABLE lock_tbl2 (b BIGINT) INHERITS (lock_tbl1); 41 | CREATE TABLE lock_tbl3 () INHERITS (lock_tbl2); 42 | BEGIN TRANSACTION; 43 | LOCK TABLE lock_tbl1 * IN ACCESS EXCLUSIVE MODE; 44 | ROLLBACK; 45 | 46 | -- Verify that we can't lock a child table just because we have permission 47 | -- on the parent, but that we can lock the parent only. 48 | GRANT UPDATE ON TABLE lock_tbl1 TO regress_rol_lock1; 49 | SET ROLE regress_rol_lock1; 50 | BEGIN; 51 | LOCK TABLE lock_tbl1 * IN ACCESS EXCLUSIVE MODE; 52 | ROLLBACK; 53 | BEGIN; 54 | LOCK TABLE ONLY lock_tbl1; 55 | ROLLBACK; 56 | RESET ROLE; 57 | 58 | -- 59 | -- Clean up 60 | -- 61 | DROP VIEW lock_view1; 62 | DROP TABLE lock_tbl3; 63 | DROP TABLE lock_tbl2; 64 | DROP TABLE lock_tbl1; 65 | DROP SCHEMA lock_schema1 CASCADE; 66 | DROP ROLE regress_rol_lock1; 67 | 68 | 69 | -- atomic ops tests 70 | RESET search_path; 71 | SELECT test_atomic_ops(); 72 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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, '0800-2b01-0203'); 13 | INSERT INTO macaddr_data VALUES (7, '08002b010203'); 14 | INSERT INTO macaddr_data VALUES (8, '0800:2b01:0203'); -- invalid 15 | INSERT INTO macaddr_data VALUES (9, 'not even close'); -- invalid 16 | 17 | INSERT INTO macaddr_data VALUES (10, '08:00:2b:01:02:04'); 18 | INSERT INTO macaddr_data VALUES (11, '08:00:2b:01:02:02'); 19 | INSERT INTO macaddr_data VALUES (12, '08:00:2a:01:02:03'); 20 | INSERT INTO macaddr_data VALUES (13, '08:00:2c:01:02:03'); 21 | INSERT INTO macaddr_data VALUES (14, '08:00:2a:01:02:04'); 22 | 23 | SELECT * FROM macaddr_data; 24 | 25 | CREATE INDEX macaddr_data_btree ON macaddr_data USING btree (b); 26 | CREATE INDEX macaddr_data_hash ON macaddr_data USING hash (b); 27 | 28 | SELECT a, b, trunc(b) FROM macaddr_data ORDER BY 2, 1; 29 | 30 | SELECT b < '08:00:2b:01:02:04' FROM macaddr_data WHERE a = 1; -- true 31 | SELECT b > '08:00:2b:01:02:04' FROM macaddr_data WHERE a = 1; -- false 32 | SELECT b > '08:00:2b:01:02:03' FROM macaddr_data WHERE a = 1; -- false 33 | SELECT b <= '08:00:2b:01:02:04' FROM macaddr_data WHERE a = 1; -- true 34 | SELECT b >= '08:00:2b:01:02:04' FROM macaddr_data WHERE a = 1; -- false 35 | SELECT b = '08:00:2b:01:02:03' FROM macaddr_data WHERE a = 1; -- true 36 | SELECT b <> '08:00:2b:01:02:04' FROM macaddr_data WHERE a = 1; -- true 37 | SELECT b <> '08:00:2b:01:02:03' FROM macaddr_data WHERE a = 1; -- false 38 | 39 | SELECT ~b FROM macaddr_data; 40 | SELECT b & '00:00:00:ff:ff:ff' FROM macaddr_data; 41 | SELECT b | '01:02:03:04:05:06' FROM macaddr_data; 42 | 43 | DROP TABLE macaddr_data; 44 | -------------------------------------------------------------------------------- /test/fixtures/upstream/misc_functions.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- num_nulls() 3 | -- 4 | 5 | SELECT num_nonnulls(NULL); 6 | SELECT num_nonnulls('1'); 7 | SELECT num_nonnulls(NULL::text); 8 | SELECT num_nonnulls(NULL::text, NULL::int); 9 | SELECT num_nonnulls(1, 2, NULL::text, NULL::point, '', int8 '9', 1.0 / NULL); 10 | SELECT num_nonnulls(VARIADIC '{1,2,NULL,3}'::int[]); 11 | SELECT num_nonnulls(VARIADIC '{"1","2","3","4"}'::text[]); 12 | SELECT num_nonnulls(VARIADIC ARRAY(SELECT CASE WHEN i <> 40 THEN i END FROM generate_series(1, 100) i)); 13 | 14 | SELECT num_nulls(NULL); 15 | SELECT num_nulls('1'); 16 | SELECT num_nulls(NULL::text); 17 | SELECT num_nulls(NULL::text, NULL::int); 18 | SELECT num_nulls(1, 2, NULL::text, NULL::point, '', int8 '9', 1.0 / NULL); 19 | SELECT num_nulls(VARIADIC '{1,2,NULL,3}'::int[]); 20 | SELECT num_nulls(VARIADIC '{"1","2","3","4"}'::text[]); 21 | SELECT num_nulls(VARIADIC ARRAY(SELECT CASE WHEN i <> 40 THEN i END FROM generate_series(1, 100) i)); 22 | 23 | -- special cases 24 | SELECT num_nonnulls(VARIADIC NULL::text[]); 25 | SELECT num_nonnulls(VARIADIC '{}'::int[]); 26 | SELECT num_nulls(VARIADIC NULL::text[]); 27 | SELECT num_nulls(VARIADIC '{}'::int[]); 28 | 29 | -- should fail, one or more arguments is required 30 | SELECT num_nonnulls(); 31 | SELECT num_nulls(); 32 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | 56 | DO $$ 57 | DECLARE r text[]; 58 | BEGIN 59 | r := parse_ident('Schemax.Tabley'); 60 | RAISE NOTICE '%', format('%I.%I', r[1], r[2]); 61 | r := parse_ident('"SchemaX"."TableY"'); 62 | RAISE NOTICE '%', format('%I.%I', r[1], r[2]); 63 | END; 64 | $$; 65 | 66 | SELECT parse_ident('foo.boo'); 67 | SELECT parse_ident('foo.boo[]'); -- should fail 68 | SELECT parse_ident('foo.boo[]', strict => false); -- ok 69 | 70 | -- should fail 71 | SELECT parse_ident(' '); 72 | SELECT parse_ident(' .aaa'); 73 | SELECT parse_ident(' aaa . '); 74 | SELECT parse_ident('aaa.a%b'); 75 | SELECT parse_ident(E'X\rXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'); 76 | 77 | SELECT length(a[1]), length(a[2]) from parse_ident('"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy') as a ; 78 | 79 | SELECT parse_ident(' first . " second " ." third ". " ' || repeat('x',66) || '"'); 80 | SELECT parse_ident(' first . " second " ." third ". " ' || repeat('x',66) || '"')::name[]; 81 | 82 | SELECT parse_ident(E'"c".X XXXX\002XXXXXX'); 83 | SELECT parse_ident('1020'); 84 | SELECT parse_ident('10.20'); 85 | SELECT parse_ident('.'); 86 | SELECT parse_ident('.1020'); 87 | SELECT parse_ident('xxx.1020'); 88 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | ALTER SCHEMA test_schema_1 RENAME TO test_schema_renamed; 28 | SELECT COUNT(*) FROM pg_class WHERE relnamespace = 29 | (SELECT oid FROM pg_namespace WHERE nspname = 'test_schema_1'); 30 | 31 | -- test IF NOT EXISTS cases 32 | CREATE SCHEMA test_schema_renamed; -- fail, already exists 33 | CREATE SCHEMA IF NOT EXISTS test_schema_renamed; -- ok with notice 34 | CREATE SCHEMA IF NOT EXISTS test_schema_renamed -- fail, disallowed 35 | CREATE TABLE abc ( 36 | a serial, 37 | b int UNIQUE 38 | ); 39 | 40 | DROP SCHEMA test_schema_renamed CASCADE; 41 | 42 | -- verify that the objects were dropped 43 | SELECT COUNT(*) FROM pg_class WHERE relnamespace = 44 | (SELECT oid FROM pg_namespace WHERE nspname = 'test_schema_renamed'); 45 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/pg_lsn.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- PG_LSN 3 | -- 4 | 5 | CREATE TABLE PG_LSN_TBL (f1 pg_lsn); 6 | 7 | -- Largest and smallest input 8 | INSERT INTO PG_LSN_TBL VALUES ('0/0'); 9 | INSERT INTO PG_LSN_TBL VALUES ('FFFFFFFF/FFFFFFFF'); 10 | 11 | -- Incorrect input 12 | INSERT INTO PG_LSN_TBL VALUES ('G/0'); 13 | INSERT INTO PG_LSN_TBL VALUES ('-1/0'); 14 | INSERT INTO PG_LSN_TBL VALUES (' 0/12345678'); 15 | INSERT INTO PG_LSN_TBL VALUES ('ABCD/'); 16 | INSERT INTO PG_LSN_TBL VALUES ('/ABCD'); 17 | DROP TABLE PG_LSN_TBL; 18 | 19 | -- Operators 20 | SELECT '0/16AE7F8' = '0/16AE7F8'::pg_lsn; 21 | SELECT '0/16AE7F8'::pg_lsn != '0/16AE7F7'; 22 | SELECT '0/16AE7F7' < '0/16AE7F8'::pg_lsn; 23 | SELECT '0/16AE7F8' > pg_lsn '0/16AE7F7'; 24 | SELECT '0/16AE7F7'::pg_lsn - '0/16AE7F8'::pg_lsn; 25 | SELECT '0/16AE7F8'::pg_lsn - '0/16AE7F7'::pg_lsn; 26 | 27 | -- Check btree and hash opclasses 28 | EXPLAIN (COSTS OFF) 29 | SELECT DISTINCT (i || '/' || j)::pg_lsn f 30 | FROM generate_series(1, 10) i, 31 | generate_series(1, 10) j, 32 | generate_series(1, 5) k 33 | WHERE i <= 10 AND j > 0 AND j <= 10 34 | ORDER BY f; 35 | 36 | SELECT DISTINCT (i || '/' || j)::pg_lsn f 37 | FROM generate_series(1, 10) i, 38 | generate_series(1, 10) j, 39 | generate_series(1, 5) k 40 | WHERE i <= 10 AND j > 0 AND j <= 10 41 | ORDER BY f; 42 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 honored when re-using cached plan 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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | 84 | -- Test that GiST indexes provide same behavior as sequential scan 85 | CREATE TEMP TABLE point_gist_tbl(f1 point); 86 | INSERT INTO point_gist_tbl SELECT '(0,0)' FROM generate_series(0,1000); 87 | CREATE INDEX point_gist_tbl_index ON point_gist_tbl USING gist (f1); 88 | INSERT INTO point_gist_tbl VALUES ('(0.0000009,0.0000009)'); 89 | SET enable_seqscan TO true; 90 | SET enable_indexscan TO false; 91 | SET enable_bitmapscan TO false; 92 | SELECT COUNT(*) FROM point_gist_tbl WHERE f1 ~= '(0.0000009,0.0000009)'::point; 93 | SELECT COUNT(*) FROM point_gist_tbl WHERE f1 <@ '(0.0000009,0.0000009),(0.0000009,0.0000009)'::box; 94 | SELECT COUNT(*) FROM point_gist_tbl WHERE f1 ~= '(0.0000018,0.0000018)'::point; 95 | SET enable_seqscan TO false; 96 | SET enable_indexscan TO true; 97 | SET enable_bitmapscan TO true; 98 | SELECT COUNT(*) FROM point_gist_tbl WHERE f1 ~= '(0.0000009,0.0000009)'::point; 99 | SELECT COUNT(*) FROM point_gist_tbl WHERE f1 <@ '(0.0000009,0.0000009),(0.0000009,0.0000009)'::box; 100 | SELECT COUNT(*) FROM point_gist_tbl WHERE f1 ~= '(0.0000018,0.0000018)'::point; 101 | RESET enable_seqscan; 102 | RESET enable_indexscan; 103 | RESET enable_bitmapscan; 104 | -------------------------------------------------------------------------------- /test/fixtures/upstream/polygon.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- POLYGON 3 | -- 4 | -- polygon logic 5 | -- 6 | 7 | CREATE TABLE POLYGON_TBL(f1 polygon); 8 | 9 | 10 | INSERT INTO POLYGON_TBL(f1) VALUES ('(2.0,0.0),(2.0,4.0),(0.0,0.0)'); 11 | 12 | INSERT INTO POLYGON_TBL(f1) VALUES ('(3.0,1.0),(3.0,3.0),(1.0,0.0)'); 13 | 14 | -- degenerate polygons 15 | INSERT INTO POLYGON_TBL(f1) VALUES ('(0.0,0.0)'); 16 | 17 | INSERT INTO POLYGON_TBL(f1) VALUES ('(0.0,1.0),(0.0,1.0)'); 18 | 19 | -- bad polygon input strings 20 | INSERT INTO POLYGON_TBL(f1) VALUES ('0.0'); 21 | 22 | INSERT INTO POLYGON_TBL(f1) VALUES ('(0.0 0.0'); 23 | 24 | INSERT INTO POLYGON_TBL(f1) VALUES ('(0,1,2)'); 25 | 26 | INSERT INTO POLYGON_TBL(f1) VALUES ('(0,1,2,3'); 27 | 28 | INSERT INTO POLYGON_TBL(f1) VALUES ('asdf'); 29 | 30 | 31 | SELECT '' AS four, * FROM POLYGON_TBL; 32 | 33 | -- overlap 34 | SELECT '' AS three, p.* 35 | FROM POLYGON_TBL p 36 | WHERE p.f1 && '(3.0,1.0),(3.0,3.0),(1.0,0.0)'; 37 | 38 | -- left overlap 39 | SELECT '' AS four, p.* 40 | FROM POLYGON_TBL p 41 | WHERE p.f1 &< '(3.0,1.0),(3.0,3.0),(1.0,0.0)'; 42 | 43 | -- right overlap 44 | SELECT '' AS two, p.* 45 | FROM POLYGON_TBL p 46 | WHERE p.f1 &> '(3.0,1.0),(3.0,3.0),(1.0,0.0)'; 47 | 48 | -- left of 49 | SELECT '' AS one, p.* 50 | FROM POLYGON_TBL p 51 | WHERE p.f1 << '(3.0,1.0),(3.0,3.0),(1.0,0.0)'; 52 | 53 | -- right of 54 | SELECT '' AS zero, p.* 55 | FROM POLYGON_TBL p 56 | WHERE p.f1 >> '(3.0,1.0),(3.0,3.0),(1.0,0.0)'; 57 | 58 | -- contained 59 | SELECT '' AS one, p.* 60 | FROM POLYGON_TBL p 61 | WHERE p.f1 <@ polygon '(3.0,1.0),(3.0,3.0),(1.0,0.0)'; 62 | 63 | -- same 64 | SELECT '' AS one, p.* 65 | FROM POLYGON_TBL p 66 | WHERE p.f1 ~= polygon '(3.0,1.0),(3.0,3.0),(1.0,0.0)'; 67 | 68 | -- contains 69 | SELECT '' AS one, p.* 70 | FROM POLYGON_TBL p 71 | WHERE p.f1 @> polygon '(3.0,1.0),(3.0,3.0),(1.0,0.0)'; 72 | 73 | -- 74 | -- polygon logic 75 | -- 76 | -- left of 77 | SELECT polygon '(2.0,0.0),(2.0,4.0),(0.0,0.0)' << polygon '(3.0,1.0),(3.0,3.0),(1.0,0.0)' AS false; 78 | 79 | -- left overlap 80 | SELECT polygon '(2.0,0.0),(2.0,4.0),(0.0,0.0)' << polygon '(3.0,1.0),(3.0,3.0),(1.0,0.0)' AS true; 81 | 82 | -- right overlap 83 | SELECT polygon '(2.0,0.0),(2.0,4.0),(0.0,0.0)' &> polygon '(3.0,1.0),(3.0,3.0),(1.0,0.0)' AS false; 84 | 85 | -- right of 86 | SELECT polygon '(2.0,0.0),(2.0,4.0),(0.0,0.0)' >> polygon '(3.0,1.0),(3.0,3.0),(1.0,0.0)' AS false; 87 | 88 | -- contained in 89 | SELECT polygon '(2.0,0.0),(2.0,4.0),(0.0,0.0)' <@ polygon '(3.0,1.0),(3.0,3.0),(1.0,0.0)' AS false; 90 | 91 | -- contains 92 | SELECT polygon '(2.0,0.0),(2.0,4.0),(0.0,0.0)' @> polygon '(3.0,1.0),(3.0,3.0),(1.0,0.0)' AS false; 93 | 94 | SELECT '((0,4),(6,4),(1,2),(6,0),(0,0))'::polygon @> '((2,1),(2,3),(3,3),(3,1))'::polygon AS "false"; 95 | 96 | SELECT '((0,4),(6,4),(3,2),(6,0),(0,0))'::polygon @> '((2,1),(2,3),(3,3),(3,1))'::polygon AS "true"; 97 | 98 | SELECT '((1,1),(1,4),(5,4),(5,3),(2,3),(2,2),(5,2),(5,1))'::polygon @> '((3,2),(3,3),(4,3),(4,2))'::polygon AS "false"; 99 | 100 | SELECT '((0,0),(0,3),(3,3),(3,0))'::polygon @> '((2,1),(2,2),(3,2),(3,1))'::polygon AS "true"; 101 | 102 | -- same 103 | SELECT polygon '(2.0,0.0),(2.0,4.0),(0.0,0.0)' ~= polygon '(3.0,1.0),(3.0,3.0),(1.0,0.0)' AS false; 104 | 105 | -- overlap 106 | SELECT polygon '(2.0,0.0),(2.0,4.0),(0.0,0.0)' && polygon '(3.0,1.0),(3.0,3.0),(1.0,0.0)' AS true; 107 | 108 | SELECT '((0,4),(6,4),(1,2),(6,0),(0,0))'::polygon && '((2,1),(2,3),(3,3),(3,1))'::polygon AS "true"; 109 | 110 | SELECT '((1,4),(1,1),(4,1),(4,2),(2,2),(2,4),(1,4))'::polygon && '((3,3),(4,3),(4,4),(3,4),(3,3))'::polygon AS "false"; 111 | SELECT '((200,800),(800,800),(800,200),(200,200))' && '(1000,1000,0,0)'::polygon AS "true"; 112 | 113 | -- distance from a point 114 | SELECT '(0,0)'::point <-> '((0,0),(1,2),(2,1))'::polygon as on_corner, 115 | '(1,1)'::point <-> '((0,0),(2,2),(1,3))'::polygon as on_segment, 116 | '(2,2)'::point <-> '((0,0),(1,4),(3,1))'::polygon as inside, 117 | '(3,3)'::point <-> '((0,2),(2,0),(2,2))'::polygon as near_corner, 118 | '(4,4)'::point <-> '((0,0),(0,3),(4,0))'::polygon as near_segment; 119 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | begin; 126 | set statement_timeout to 2000; 127 | SELECT * FROM pxtest3; 128 | rollback; 129 | 130 | -- Disconnect, we will continue testing in a different backend 131 | \c - 132 | 133 | -- There should still be two prepared transactions 134 | SELECT gid FROM pg_prepared_xacts; 135 | 136 | -- pxtest3 should still be locked because of the pending DROP 137 | begin; 138 | set statement_timeout to 2000; 139 | SELECT * FROM pxtest3; 140 | rollback; 141 | 142 | -- Commit table creation 143 | COMMIT PREPARED 'regress-one'; 144 | \d pxtest2 145 | SELECT * FROM pxtest2; 146 | 147 | -- There should be one prepared transaction 148 | SELECT gid FROM pg_prepared_xacts; 149 | 150 | -- Commit table drop 151 | COMMIT PREPARED 'regress-two'; 152 | SELECT * FROM pxtest3; 153 | 154 | -- There should be no prepared transactions 155 | SELECT gid FROM pg_prepared_xacts; 156 | 157 | -- Clean up 158 | DROP TABLE pxtest2; 159 | DROP TABLE pxtest3; -- will still be there if prepared xacts are disabled 160 | DROP TABLE pxtest4; 161 | -------------------------------------------------------------------------------- /test/fixtures/upstream/psql_crosstab.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- \crosstabview 3 | -- 4 | 5 | CREATE TABLE ctv_data (v, h, c, i, d) AS 6 | VALUES 7 | ('v1','h2','foo', 3, '2015-04-01'::date), 8 | ('v2','h1','bar', 3, '2015-01-02'), 9 | ('v1','h0','baz', NULL, '2015-07-12'), 10 | ('v0','h4','qux', 4, '2015-07-15'), 11 | ('v0','h4','dbl', -3, '2014-12-15'), 12 | ('v0',NULL,'qux', 5, '2014-07-15'), 13 | ('v1','h2','quux',7, '2015-04-04'); 14 | 15 | -- running \crosstabview after query uses query in buffer 16 | SELECT v, EXTRACT(year FROM d), count(*) 17 | FROM ctv_data 18 | GROUP BY 1, 2 19 | ORDER BY 1, 2; 20 | -- basic usage with 3 columns 21 | \crosstabview 22 | 23 | -- ordered months in horizontal header, quoted column name 24 | SELECT v, to_char(d, 'Mon') AS "month name", EXTRACT(month FROM d) AS num, 25 | count(*) FROM ctv_data GROUP BY 1,2,3 ORDER BY 1 26 | \crosstabview v "month name" 4 num 27 | 28 | -- ordered months in vertical header, ordered years in horizontal header 29 | SELECT EXTRACT(year FROM d) AS year, to_char(d,'Mon') AS "month name", 30 | EXTRACT(month FROM d) AS month, 31 | format('sum=%s avg=%s', sum(i), avg(i)::numeric(2,1)) 32 | FROM ctv_data 33 | GROUP BY EXTRACT(year FROM d), to_char(d,'Mon'), EXTRACT(month FROM d) 34 | ORDER BY month 35 | \crosstabview "month name" year format year 36 | 37 | -- combine contents vertically into the same cell (V/H duplicates) 38 | SELECT v, h, string_agg(c, E'\n') FROM ctv_data GROUP BY v, h ORDER BY 1,2,3 39 | \crosstabview 1 2 3 40 | 41 | -- horizontal ASC order from window function 42 | SELECT v,h, string_agg(c, E'\n') AS c, row_number() OVER(ORDER BY h) AS r 43 | FROM ctv_data GROUP BY v, h ORDER BY 1,3,2 44 | \crosstabview v h c r 45 | 46 | -- horizontal DESC order from window function 47 | SELECT v, h, string_agg(c, E'\n') AS c, row_number() OVER(ORDER BY h DESC) AS r 48 | FROM ctv_data GROUP BY v, h ORDER BY 1,3,2 49 | \crosstabview v h c r 50 | 51 | -- horizontal ASC order from window function, NULLs pushed rightmost 52 | SELECT v,h, string_agg(c, E'\n') AS c, row_number() OVER(ORDER BY h NULLS LAST) AS r 53 | FROM ctv_data GROUP BY v, h ORDER BY 1,3,2 54 | \crosstabview v h c r 55 | 56 | -- only null, no column name, 2 columns: error 57 | SELECT null,null \crosstabview 58 | 59 | -- only null, no column name, 3 columns: works 60 | SELECT null,null,null \crosstabview 61 | 62 | -- null display 63 | \pset null '#null#' 64 | SELECT v,h, string_agg(i::text, E'\n') AS i FROM ctv_data 65 | GROUP BY v, h ORDER BY h,v 66 | \crosstabview v h i 67 | \pset null '' 68 | 69 | -- refer to columns by position 70 | SELECT v,h,string_agg(i::text, E'\n'), string_agg(c, E'\n') 71 | FROM ctv_data GROUP BY v, h ORDER BY h,v 72 | \crosstabview 2 1 4 73 | 74 | -- refer to columns by positions and names mixed 75 | SELECT v,h, string_agg(i::text, E'\n') AS i, string_agg(c, E'\n') AS c 76 | FROM ctv_data GROUP BY v, h ORDER BY h,v 77 | \crosstabview 1 "h" 4 78 | 79 | -- refer to columns by quoted names, check downcasing of unquoted name 80 | SELECT 1 as "22", 2 as b, 3 as "Foo" 81 | \crosstabview "22" B "Foo" 82 | 83 | -- error: bad column name 84 | SELECT v,h,c,i FROM ctv_data 85 | \crosstabview v h j 86 | 87 | -- error: need to quote name 88 | SELECT 1 as "22", 2 as b, 3 as "Foo" 89 | \crosstabview 1 2 Foo 90 | 91 | -- error: need to not quote name 92 | SELECT 1 as "22", 2 as b, 3 as "Foo" 93 | \crosstabview 1 "B" "Foo" 94 | 95 | -- error: bad column number 96 | SELECT v,h,i,c FROM ctv_data 97 | \crosstabview 2 1 5 98 | 99 | -- error: same H and V columns 100 | SELECT v,h,i,c FROM ctv_data 101 | \crosstabview 2 h 4 102 | 103 | -- error: too many columns 104 | SELECT a,a,1 FROM generate_series(1,3000) AS a 105 | \crosstabview 106 | 107 | -- error: only one column 108 | SELECT 1 \crosstabview 109 | 110 | DROP TABLE ctv_data; 111 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/regproc.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- regproc 3 | -- 4 | 5 | /* If objects exist, return oids */ 6 | 7 | CREATE ROLE regtestrole; 8 | 9 | -- without schemaname 10 | 11 | SELECT regoper('||/'); 12 | SELECT regoperator('+(int4,int4)'); 13 | SELECT regproc('now'); 14 | SELECT regprocedure('abs(numeric)'); 15 | SELECT regclass('pg_class'); 16 | SELECT regtype('int4'); 17 | 18 | SELECT to_regoper('||/'); 19 | SELECT to_regoperator('+(int4,int4)'); 20 | SELECT to_regproc('now'); 21 | SELECT to_regprocedure('abs(numeric)'); 22 | SELECT to_regclass('pg_class'); 23 | SELECT to_regtype('int4'); 24 | 25 | -- with schemaname 26 | 27 | SELECT regoper('pg_catalog.||/'); 28 | SELECT regoperator('pg_catalog.+(int4,int4)'); 29 | SELECT regproc('pg_catalog.now'); 30 | SELECT regprocedure('pg_catalog.abs(numeric)'); 31 | SELECT regclass('pg_catalog.pg_class'); 32 | SELECT regtype('pg_catalog.int4'); 33 | 34 | SELECT to_regoper('pg_catalog.||/'); 35 | SELECT to_regproc('pg_catalog.now'); 36 | SELECT to_regprocedure('pg_catalog.abs(numeric)'); 37 | SELECT to_regclass('pg_catalog.pg_class'); 38 | SELECT to_regtype('pg_catalog.int4'); 39 | 40 | -- schemaname not applicable 41 | 42 | SELECT regrole('regtestrole'); 43 | SELECT regrole('"regtestrole"'); 44 | SELECT regnamespace('pg_catalog'); 45 | SELECT regnamespace('"pg_catalog"'); 46 | 47 | SELECT to_regrole('regtestrole'); 48 | SELECT to_regrole('"regtestrole"'); 49 | SELECT to_regnamespace('pg_catalog'); 50 | SELECT to_regnamespace('"pg_catalog"'); 51 | 52 | /* If objects don't exist, raise errors. */ 53 | 54 | DROP ROLE regtestrole; 55 | 56 | -- without schemaname 57 | 58 | SELECT regoper('||//'); 59 | SELECT regoperator('++(int4,int4)'); 60 | SELECT regproc('know'); 61 | SELECT regprocedure('absinthe(numeric)'); 62 | SELECT regclass('pg_classes'); 63 | SELECT regtype('int3'); 64 | 65 | -- with schemaname 66 | 67 | SELECT regoper('ng_catalog.||/'); 68 | SELECT regoperator('ng_catalog.+(int4,int4)'); 69 | SELECT regproc('ng_catalog.now'); 70 | SELECT regprocedure('ng_catalog.abs(numeric)'); 71 | SELECT regclass('ng_catalog.pg_class'); 72 | SELECT regtype('ng_catalog.int4'); 73 | 74 | -- schemaname not applicable 75 | 76 | SELECT regrole('regtestrole'); 77 | SELECT regrole('"regtestrole"'); 78 | SELECT regrole('Nonexistent'); 79 | SELECT regrole('"Nonexistent"'); 80 | SELECT regrole('foo.bar'); 81 | SELECT regnamespace('Nonexistent'); 82 | SELECT regnamespace('"Nonexistent"'); 83 | SELECT regnamespace('foo.bar'); 84 | 85 | /* If objects don't exist, return NULL with no error. */ 86 | 87 | -- without schemaname 88 | 89 | SELECT to_regoper('||//'); 90 | SELECT to_regoperator('++(int4,int4)'); 91 | SELECT to_regproc('know'); 92 | SELECT to_regprocedure('absinthe(numeric)'); 93 | SELECT to_regclass('pg_classes'); 94 | SELECT to_regtype('int3'); 95 | 96 | -- with schemaname 97 | 98 | SELECT to_regoper('ng_catalog.||/'); 99 | SELECT to_regoperator('ng_catalog.+(int4,int4)'); 100 | SELECT to_regproc('ng_catalog.now'); 101 | SELECT to_regprocedure('ng_catalog.abs(numeric)'); 102 | SELECT to_regclass('ng_catalog.pg_class'); 103 | SELECT to_regtype('ng_catalog.int4'); 104 | 105 | -- schemaname not applicable 106 | 107 | SELECT to_regrole('regtestrole'); 108 | SELECT to_regrole('"regtestrole"'); 109 | SELECT to_regrole('foo.bar'); 110 | SELECT to_regrole('Nonexistent'); 111 | SELECT to_regrole('"Nonexistent"'); 112 | SELECT to_regrole('foo.bar'); 113 | SELECT to_regnamespace('Nonexistent'); 114 | SELECT to_regnamespace('"Nonexistent"'); 115 | SELECT to_regnamespace('foo.bar'); 116 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/replica_identity.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE test_replica_identity ( 2 | id serial primary key, 3 | keya text not null, 4 | keyb text not null, 5 | nonkey text, 6 | CONSTRAINT test_replica_identity_unique_defer UNIQUE (keya, keyb) DEFERRABLE, 7 | CONSTRAINT test_replica_identity_unique_nondefer UNIQUE (keya, keyb) 8 | ) WITH OIDS; 9 | 10 | CREATE TABLE test_replica_identity_othertable (id serial primary key); 11 | 12 | CREATE INDEX test_replica_identity_keyab ON test_replica_identity (keya, keyb); 13 | CREATE UNIQUE INDEX test_replica_identity_keyab_key ON test_replica_identity (keya, keyb); 14 | CREATE UNIQUE INDEX test_replica_identity_oid_idx ON test_replica_identity (oid); 15 | CREATE UNIQUE INDEX test_replica_identity_nonkey ON test_replica_identity (keya, nonkey); 16 | CREATE INDEX test_replica_identity_hash ON test_replica_identity USING hash (nonkey); 17 | CREATE UNIQUE INDEX test_replica_identity_expr ON test_replica_identity (keya, keyb, (3)); 18 | CREATE UNIQUE INDEX test_replica_identity_partial ON test_replica_identity (keya, keyb) WHERE keyb != '3'; 19 | 20 | -- default is 'd'/DEFAULT for user created tables 21 | SELECT relreplident FROM pg_class WHERE oid = 'test_replica_identity'::regclass; 22 | -- but 'none' for system tables 23 | SELECT relreplident FROM pg_class WHERE oid = 'pg_class'::regclass; 24 | SELECT relreplident FROM pg_class WHERE oid = 'pg_constraint'::regclass; 25 | 26 | ---- 27 | -- Make sure we detect ineligible indexes 28 | ---- 29 | 30 | -- fail, not unique 31 | ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_keyab; 32 | -- fail, not a candidate key, nullable column 33 | ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_nonkey; 34 | -- fail, hash indexes cannot do uniqueness 35 | ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_hash; 36 | -- fail, expression index 37 | ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_expr; 38 | -- fail, partial index 39 | ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_partial; 40 | -- fail, not our index 41 | ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_othertable_pkey; 42 | -- fail, deferrable 43 | ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_unique_defer; 44 | 45 | SELECT relreplident FROM pg_class WHERE oid = 'test_replica_identity'::regclass; 46 | 47 | ---- 48 | -- Make sure index cases succeed 49 | ---- 50 | 51 | -- succeed, primary key 52 | ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_pkey; 53 | SELECT relreplident FROM pg_class WHERE oid = 'test_replica_identity'::regclass; 54 | \d test_replica_identity 55 | 56 | -- succeed, oid unique index 57 | ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_oid_idx; 58 | 59 | -- succeed, nondeferrable unique constraint over nonullable cols 60 | ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_unique_nondefer; 61 | 62 | -- succeed unique index over nonnullable cols 63 | ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_keyab_key; 64 | ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_keyab_key; 65 | SELECT relreplident FROM pg_class WHERE oid = 'test_replica_identity'::regclass; 66 | \d test_replica_identity 67 | SELECT count(*) FROM pg_index WHERE indrelid = 'test_replica_identity'::regclass AND indisreplident; 68 | 69 | ---- 70 | -- Make sure non index cases work 71 | ---- 72 | ALTER TABLE test_replica_identity REPLICA IDENTITY DEFAULT; 73 | SELECT relreplident FROM pg_class WHERE oid = 'test_replica_identity'::regclass; 74 | SELECT count(*) FROM pg_index WHERE indrelid = 'test_replica_identity'::regclass AND indisreplident; 75 | 76 | ALTER TABLE test_replica_identity REPLICA IDENTITY FULL; 77 | SELECT relreplident FROM pg_class WHERE oid = 'test_replica_identity'::regclass; 78 | \d+ test_replica_identity 79 | ALTER TABLE test_replica_identity REPLICA IDENTITY NOTHING; 80 | SELECT relreplident FROM pg_class WHERE oid = 'test_replica_identity'::regclass; 81 | 82 | DROP TABLE test_replica_identity; 83 | DROP TABLE test_replica_identity_othertable; 84 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | 158 | -- Check aliased target relation 159 | INSERT INTO foo AS bar DEFAULT VALUES RETURNING *; -- ok 160 | INSERT INTO foo AS bar DEFAULT VALUES RETURNING foo.*; -- fails, wrong name 161 | INSERT INTO foo AS bar DEFAULT VALUES RETURNING bar.*; -- ok 162 | INSERT INTO foo AS bar DEFAULT VALUES RETURNING bar.f3; -- ok 163 | -------------------------------------------------------------------------------- /test/fixtures/upstream/roleattributes.sql: -------------------------------------------------------------------------------- 1 | -- default for superuser is false 2 | CREATE ROLE test_def_superuser; 3 | SELECT * FROM pg_authid WHERE rolname = 'test_def_superuser'; 4 | CREATE ROLE test_superuser WITH SUPERUSER; 5 | SELECT * FROM pg_authid WHERE rolname = 'test_superuser'; 6 | ALTER ROLE test_superuser WITH NOSUPERUSER; 7 | SELECT * FROM pg_authid WHERE rolname = 'test_superuser'; 8 | ALTER ROLE test_superuser WITH SUPERUSER; 9 | SELECT * FROM pg_authid WHERE rolname = 'test_superuser'; 10 | 11 | -- default for inherit is true 12 | CREATE ROLE test_def_inherit; 13 | SELECT * FROM pg_authid WHERE rolname = 'test_def_inherit'; 14 | CREATE ROLE test_inherit WITH NOINHERIT; 15 | SELECT * FROM pg_authid WHERE rolname = 'test_inherit'; 16 | ALTER ROLE test_inherit WITH INHERIT; 17 | SELECT * FROM pg_authid WHERE rolname = 'test_inherit'; 18 | ALTER ROLE test_inherit WITH NOINHERIT; 19 | SELECT * FROM pg_authid WHERE rolname = 'test_inherit'; 20 | 21 | -- default for create role is false 22 | CREATE ROLE test_def_createrole; 23 | SELECT * FROM pg_authid WHERE rolname = 'test_def_createrole'; 24 | CREATE ROLE test_createrole WITH CREATEROLE; 25 | SELECT * FROM pg_authid WHERE rolname = 'test_createrole'; 26 | ALTER ROLE test_createrole WITH NOCREATEROLE; 27 | SELECT * FROM pg_authid WHERE rolname = 'test_createrole'; 28 | ALTER ROLE test_createrole WITH CREATEROLE; 29 | SELECT * FROM pg_authid WHERE rolname = 'test_createrole'; 30 | 31 | -- default for create database is false 32 | CREATE ROLE test_def_createdb; 33 | SELECT * FROM pg_authid WHERE rolname = 'test_def_createdb'; 34 | CREATE ROLE test_createdb WITH CREATEDB; 35 | SELECT * FROM pg_authid WHERE rolname = 'test_createdb'; 36 | ALTER ROLE test_createdb WITH NOCREATEDB; 37 | SELECT * FROM pg_authid WHERE rolname = 'test_createdb'; 38 | ALTER ROLE test_createdb WITH CREATEDB; 39 | SELECT * FROM pg_authid WHERE rolname = 'test_createdb'; 40 | 41 | -- default for can login is false for role 42 | CREATE ROLE test_def_role_canlogin; 43 | SELECT * FROM pg_authid WHERE rolname = 'test_def_role_canlogin'; 44 | CREATE ROLE test_role_canlogin WITH LOGIN; 45 | SELECT * FROM pg_authid WHERE rolname = 'test_role_canlogin'; 46 | ALTER ROLE test_role_canlogin WITH NOLOGIN; 47 | SELECT * FROM pg_authid WHERE rolname = 'test_role_canlogin'; 48 | ALTER ROLE test_role_canlogin WITH LOGIN; 49 | SELECT * FROM pg_authid WHERE rolname = 'test_role_canlogin'; 50 | 51 | -- default for can login is true for user 52 | CREATE USER test_def_user_canlogin; 53 | SELECT * FROM pg_authid WHERE rolname = 'test_def_user_canlogin'; 54 | CREATE USER test_user_canlogin WITH NOLOGIN; 55 | SELECT * FROM pg_authid WHERE rolname = 'test_user_canlogin'; 56 | ALTER USER test_user_canlogin WITH LOGIN; 57 | SELECT * FROM pg_authid WHERE rolname = 'test_user_canlogin'; 58 | ALTER USER test_user_canlogin WITH NOLOGIN; 59 | SELECT * FROM pg_authid WHERE rolname = 'test_user_canlogin'; 60 | 61 | -- default for replication is false 62 | CREATE ROLE test_def_replication; 63 | SELECT * FROM pg_authid WHERE rolname = 'test_def_replication'; 64 | CREATE ROLE test_replication WITH REPLICATION; 65 | SELECT * FROM pg_authid WHERE rolname = 'test_replication'; 66 | ALTER ROLE test_replication WITH NOREPLICATION; 67 | SELECT * FROM pg_authid WHERE rolname = 'test_replication'; 68 | ALTER ROLE test_replication WITH REPLICATION; 69 | SELECT * FROM pg_authid WHERE rolname = 'test_replication'; 70 | 71 | -- default for bypassrls is false 72 | CREATE ROLE test_def_bypassrls; 73 | SELECT * FROM pg_authid WHERE rolname = 'test_def_bypassrls'; 74 | CREATE ROLE test_bypassrls WITH BYPASSRLS; 75 | SELECT * FROM pg_authid WHERE rolname = 'test_bypassrls'; 76 | ALTER ROLE test_bypassrls WITH NOBYPASSRLS; 77 | SELECT * FROM pg_authid WHERE rolname = 'test_bypassrls'; 78 | ALTER ROLE test_bypassrls WITH BYPASSRLS; 79 | SELECT * FROM pg_authid WHERE rolname = 'test_bypassrls'; 80 | 81 | -- clean up roles 82 | DROP ROLE test_def_superuser; 83 | DROP ROLE test_superuser; 84 | DROP ROLE test_def_inherit; 85 | DROP ROLE test_inherit; 86 | DROP ROLE test_def_createrole; 87 | DROP ROLE test_createrole; 88 | DROP ROLE test_def_createdb; 89 | DROP ROLE test_createdb; 90 | DROP ROLE test_def_role_canlogin; 91 | DROP ROLE test_role_canlogin; 92 | DROP USER test_def_user_canlogin; 93 | DROP USER test_user_canlogin; 94 | DROP ROLE test_def_replication; 95 | DROP ROLE test_replication; 96 | DROP ROLE test_def_bypassrls; 97 | DROP ROLE test_bypassrls; 98 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | 10 | -- temporarily disable fancy output, so catalog changes create less diff noise 11 | \a\t 12 | 13 | SELECT relname, relhasindex 14 | FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = relnamespace 15 | WHERE relkind = 'r' AND (nspname ~ '^pg_temp_') IS NOT TRUE 16 | ORDER BY relname; 17 | 18 | -- restore normal output mode 19 | \a\t 20 | 21 | -- 22 | -- another sanity check: every system catalog that has OIDs should have 23 | -- a unique index on OID. This ensures that the OIDs will be unique, 24 | -- even after the OID counter wraps around. 25 | -- We exclude non-system tables from the check by looking at nspname. 26 | -- 27 | SELECT relname, nspname 28 | FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = relnamespace 29 | WHERE relhasoids 30 | AND ((nspname ~ '^pg_') IS NOT FALSE) 31 | AND NOT EXISTS (SELECT 1 FROM pg_index i WHERE indrelid = c.oid 32 | AND indkey[0] = -2 AND indnatts = 1 33 | AND indisunique AND indimmediate); 34 | -------------------------------------------------------------------------------- /test/fixtures/upstream/security_label.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- Test for facilities of security label 3 | -- 4 | 5 | -- initial setups 6 | SET client_min_messages TO 'warning'; 7 | 8 | DROP ROLE IF EXISTS seclabel_user1; 9 | DROP ROLE IF EXISTS seclabel_user2; 10 | 11 | DROP TABLE IF EXISTS seclabel_tbl1; 12 | DROP TABLE IF EXISTS seclabel_tbl2; 13 | DROP TABLE IF EXISTS seclabel_tbl3; 14 | 15 | CREATE USER seclabel_user1 WITH CREATEROLE; 16 | CREATE USER seclabel_user2; 17 | 18 | CREATE TABLE seclabel_tbl1 (a int, b text); 19 | CREATE TABLE seclabel_tbl2 (x int, y text); 20 | CREATE VIEW seclabel_view1 AS SELECT * FROM seclabel_tbl2; 21 | CREATE FUNCTION seclabel_four() RETURNS integer AS $$SELECT 4$$ language sql; 22 | CREATE DOMAIN seclabel_domain AS text; 23 | 24 | ALTER TABLE seclabel_tbl1 OWNER TO seclabel_user1; 25 | ALTER TABLE seclabel_tbl2 OWNER TO seclabel_user2; 26 | 27 | RESET client_min_messages; 28 | 29 | -- 30 | -- Test of SECURITY LABEL statement without a plugin 31 | -- 32 | SECURITY LABEL ON TABLE seclabel_tbl1 IS 'classified'; -- fail 33 | SECURITY LABEL FOR 'dummy' ON TABLE seclabel_tbl1 IS 'classified'; -- fail 34 | SECURITY LABEL ON TABLE seclabel_tbl1 IS '...invalid label...'; -- fail 35 | SECURITY LABEL ON TABLE seclabel_tbl3 IS 'unclassified'; -- fail 36 | 37 | SECURITY LABEL ON ROLE seclabel_user1 IS 'classified'; -- fail 38 | SECURITY LABEL FOR 'dummy' ON ROLE seclabel_user1 IS 'classified'; -- fail 39 | SECURITY LABEL ON ROLE seclabel_user1 IS '...invalid label...'; -- fail 40 | SECURITY LABEL ON ROLE seclabel_user3 IS 'unclassified'; -- fail 41 | 42 | -- clean up objects 43 | DROP FUNCTION seclabel_four(); 44 | DROP DOMAIN seclabel_domain; 45 | DROP VIEW seclabel_view1; 46 | DROP TABLE seclabel_tbl1; 47 | DROP TABLE seclabel_tbl2; 48 | DROP USER seclabel_user1; 49 | DROP USER seclabel_user2; 50 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -- Try EXPLAIN ANALYZE SELECT INTO, but hide the output since it won't 70 | -- be stable. 71 | DO $$ 72 | BEGIN 73 | EXECUTE 'EXPLAIN ANALYZE SELECT * INTO TABLE easi FROM int8_tbl'; 74 | END$$; 75 | 76 | DROP TABLE created_table; 77 | DROP TABLE easi; 78 | 79 | -- 80 | -- Disallowed uses of SELECT ... INTO. All should fail 81 | -- 82 | DECLARE foo CURSOR FOR SELECT 1 INTO b; 83 | COPY (SELECT 1 INTO frak UNION SELECT 2) TO 'blob'; 84 | SELECT * FROM (SELECT 1 INTO f) bar; 85 | CREATE VIEW foo AS SELECT 1 INTO b; 86 | INSERT INTO b SELECT 1 INTO f; 87 | -------------------------------------------------------------------------------- /test/fixtures/upstream/spgist.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- Test SP-GiST indexes. 3 | -- 4 | -- There are other tests to test different SP-GiST opclasses. This is for 5 | -- testing SP-GiST code itself. 6 | 7 | create table spgist_point_tbl(id int4, p point); 8 | create index spgist_point_idx on spgist_point_tbl using spgist(p); 9 | 10 | -- Test vacuum-root operation. It gets invoked when the root is also a leaf, 11 | -- i.e. the index is very small. 12 | insert into spgist_point_tbl (id, p) 13 | select g, point(g*10, g*10) from generate_series(1, 10) g; 14 | delete from spgist_point_tbl where id < 5; 15 | vacuum spgist_point_tbl; 16 | 17 | -- Insert more data, to make the index a few levels deep. 18 | insert into spgist_point_tbl (id, p) 19 | select g, point(g*10, g*10) from generate_series(1, 10000) g; 20 | insert into spgist_point_tbl (id, p) 21 | select g+100000, point(g*10+1, g*10+1) from generate_series(1, 10000) g; 22 | 23 | -- To test vacuum, delete some entries from all over the index. 24 | delete from spgist_point_tbl where id % 2 = 1; 25 | 26 | -- And also delete some concentration of values. (SP-GiST doesn't currently 27 | -- attempt to delete pages even when they become empty, but if it did, this 28 | -- would exercise it) 29 | delete from spgist_point_tbl where id < 10000; 30 | 31 | vacuum spgist_point_tbl; 32 | 33 | 34 | -- The point opclass's choose method only uses the spgMatchNode action, 35 | -- so the other actions are not tested by the above. Create an index using 36 | -- text opclass, which uses the others actions. 37 | 38 | create table spgist_text_tbl(id int4, t text); 39 | create index spgist_text_idx on spgist_text_tbl using spgist(t); 40 | 41 | insert into spgist_text_tbl (id, t) 42 | select g, 'f' || repeat('o', 100) || g from generate_series(1, 10000) g 43 | union all 44 | select g, 'baaaaaaaaaaaaaar' || g from generate_series(1, 1000) g; 45 | 46 | -- Do a lot of insertions that have to split an existing node. Hopefully 47 | -- one of these will cause the page to run out of space, causing the inner 48 | -- tuple to be moved to another page. 49 | insert into spgist_text_tbl (id, t) 50 | select -g, 'f' || repeat('o', 100-g) || 'surprise' from generate_series(1, 100) g; 51 | -------------------------------------------------------------------------------- /test/fixtures/upstream/tablesample.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE test_tablesample (id int, name text) WITH (fillfactor=10); 2 | -- use fillfactor so we don't have to load too much data to get multiple pages 3 | 4 | INSERT INTO test_tablesample 5 | SELECT i, repeat(i::text, 200) FROM generate_series(0, 9) s(i); 6 | 7 | SELECT t.id FROM test_tablesample AS t TABLESAMPLE SYSTEM (50) REPEATABLE (0); 8 | SELECT id FROM test_tablesample TABLESAMPLE SYSTEM (100.0/11) REPEATABLE (0); 9 | SELECT id FROM test_tablesample TABLESAMPLE SYSTEM (50) REPEATABLE (0); 10 | SELECT id FROM test_tablesample TABLESAMPLE BERNOULLI (50) REPEATABLE (0); 11 | SELECT id FROM test_tablesample TABLESAMPLE BERNOULLI (5.5) REPEATABLE (0); 12 | 13 | -- 100% should give repeatable count results (ie, all rows) in any case 14 | SELECT count(*) FROM test_tablesample TABLESAMPLE SYSTEM (100); 15 | SELECT count(*) FROM test_tablesample TABLESAMPLE SYSTEM (100) REPEATABLE (1+2); 16 | SELECT count(*) FROM test_tablesample TABLESAMPLE SYSTEM (100) REPEATABLE (0.4); 17 | 18 | CREATE VIEW test_tablesample_v1 AS 19 | SELECT id FROM test_tablesample TABLESAMPLE SYSTEM (10*2) REPEATABLE (2); 20 | CREATE VIEW test_tablesample_v2 AS 21 | SELECT id FROM test_tablesample TABLESAMPLE SYSTEM (99); 22 | \d+ test_tablesample_v1 23 | \d+ test_tablesample_v2 24 | 25 | -- check a sampled query doesn't affect cursor in progress 26 | BEGIN; 27 | DECLARE tablesample_cur CURSOR FOR 28 | SELECT id FROM test_tablesample TABLESAMPLE SYSTEM (50) REPEATABLE (0); 29 | 30 | FETCH FIRST FROM tablesample_cur; 31 | FETCH NEXT FROM tablesample_cur; 32 | FETCH NEXT FROM tablesample_cur; 33 | 34 | SELECT id FROM test_tablesample TABLESAMPLE SYSTEM (50) REPEATABLE (0); 35 | 36 | FETCH NEXT FROM tablesample_cur; 37 | FETCH NEXT FROM tablesample_cur; 38 | FETCH NEXT FROM tablesample_cur; 39 | 40 | FETCH FIRST FROM tablesample_cur; 41 | FETCH NEXT FROM tablesample_cur; 42 | FETCH NEXT FROM tablesample_cur; 43 | FETCH NEXT FROM tablesample_cur; 44 | FETCH NEXT FROM tablesample_cur; 45 | FETCH NEXT FROM tablesample_cur; 46 | 47 | CLOSE tablesample_cur; 48 | END; 49 | 50 | EXPLAIN (COSTS OFF) 51 | SELECT id FROM test_tablesample TABLESAMPLE SYSTEM (50) REPEATABLE (2); 52 | EXPLAIN (COSTS OFF) 53 | SELECT * FROM test_tablesample_v1; 54 | 55 | -- check inheritance behavior 56 | explain (costs off) 57 | select count(*) from person tablesample bernoulli (100); 58 | select count(*) from person tablesample bernoulli (100); 59 | select count(*) from person; 60 | 61 | -- check that collations get assigned within the tablesample arguments 62 | SELECT count(*) FROM test_tablesample TABLESAMPLE bernoulli (('1'::text < '0'::text)::int); 63 | 64 | -- check behavior during rescans, as well as correct handling of min/max pct 65 | select * from 66 | (values (0),(100)) v(pct), 67 | lateral (select count(*) from tenk1 tablesample bernoulli (pct)) ss; 68 | select * from 69 | (values (0),(100)) v(pct), 70 | lateral (select count(*) from tenk1 tablesample system (pct)) ss; 71 | explain (costs off) 72 | select pct, count(unique1) from 73 | (values (0),(100)) v(pct), 74 | lateral (select * from tenk1 tablesample bernoulli (pct)) ss 75 | group by pct; 76 | select pct, count(unique1) from 77 | (values (0),(100)) v(pct), 78 | lateral (select * from tenk1 tablesample bernoulli (pct)) ss 79 | group by pct; 80 | select pct, count(unique1) from 81 | (values (0),(100)) v(pct), 82 | lateral (select * from tenk1 tablesample system (pct)) ss 83 | group by pct; 84 | 85 | -- errors 86 | SELECT id FROM test_tablesample TABLESAMPLE FOOBAR (1); 87 | 88 | SELECT id FROM test_tablesample TABLESAMPLE SYSTEM (NULL); 89 | SELECT id FROM test_tablesample TABLESAMPLE SYSTEM (50) REPEATABLE (NULL); 90 | 91 | SELECT id FROM test_tablesample TABLESAMPLE BERNOULLI (-1); 92 | SELECT id FROM test_tablesample TABLESAMPLE BERNOULLI (200); 93 | SELECT id FROM test_tablesample TABLESAMPLE SYSTEM (-1); 94 | SELECT id FROM test_tablesample TABLESAMPLE SYSTEM (200); 95 | 96 | SELECT id FROM test_tablesample_v1 TABLESAMPLE BERNOULLI (1); 97 | INSERT INTO test_tablesample_v1 VALUES(1); 98 | 99 | WITH query_select AS (SELECT * FROM test_tablesample) 100 | SELECT * FROM query_select TABLESAMPLE BERNOULLI (5.5) REPEATABLE (1); 101 | 102 | SELECT q.* FROM (SELECT * FROM test_tablesample) as q TABLESAMPLE BERNOULLI (5); 103 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | select '12:16:14,14'::txid_snapshot; 7 | 8 | -- errors 9 | select '31:12:'::txid_snapshot; 10 | select '0:1:'::txid_snapshot; 11 | select '12:13:0'::txid_snapshot; 12 | select '12:16:14,13'::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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | CREATE TABLE upsert_test ( 12 | a INT PRIMARY KEY, 13 | b TEXT 14 | ); 15 | 16 | INSERT INTO update_test VALUES (5, 10, 'foo'); 17 | INSERT INTO update_test(b, a) VALUES (15, 10); 18 | 19 | SELECT * FROM update_test; 20 | 21 | UPDATE update_test SET a = DEFAULT, b = DEFAULT; 22 | 23 | SELECT * FROM update_test; 24 | 25 | -- aliases for the UPDATE target table 26 | UPDATE update_test AS t SET b = 10 WHERE t.a = 10; 27 | 28 | SELECT * FROM update_test; 29 | 30 | UPDATE update_test t SET b = t.b + 10 WHERE t.a = 10; 31 | 32 | SELECT * FROM update_test; 33 | 34 | -- 35 | -- Test VALUES in FROM 36 | -- 37 | 38 | UPDATE update_test SET a=v.i FROM (VALUES(100, 20)) AS v(i, j) 39 | WHERE update_test.b = v.j; 40 | 41 | SELECT * FROM update_test; 42 | 43 | -- 44 | -- Test multiple-set-clause syntax 45 | -- 46 | 47 | INSERT INTO update_test SELECT a,b+1,c FROM update_test; 48 | SELECT * FROM update_test; 49 | 50 | UPDATE update_test SET (c,b,a) = ('bugle', b+11, DEFAULT) WHERE c = 'foo'; 51 | SELECT * FROM update_test; 52 | UPDATE update_test SET (c,b) = ('car', a+b), a = a + 1 WHERE a = 10; 53 | SELECT * FROM update_test; 54 | -- fail, multi assignment to same column: 55 | UPDATE update_test SET (c,b) = ('car', a+b), b = a + 1 WHERE a = 10; 56 | 57 | -- uncorrelated sub-select: 58 | UPDATE update_test 59 | SET (b,a) = (select a,b from update_test where b = 41 and c = 'car') 60 | WHERE a = 100 AND b = 20; 61 | SELECT * FROM update_test; 62 | -- correlated sub-select: 63 | UPDATE update_test o 64 | SET (b,a) = (select a+1,b from update_test i 65 | where i.a=o.a and i.b=o.b and i.c is not distinct from o.c); 66 | SELECT * FROM update_test; 67 | -- fail, multiple rows supplied: 68 | UPDATE update_test SET (b,a) = (select a+1,b from update_test); 69 | -- set to null if no rows supplied: 70 | UPDATE update_test SET (b,a) = (select a+1,b from update_test where a = 1000) 71 | WHERE a = 11; 72 | SELECT * FROM update_test; 73 | 74 | -- if an alias for the target table is specified, don't allow references 75 | -- to the original table name 76 | UPDATE update_test AS t SET b = update_test.b + 10 WHERE t.a = 10; 77 | 78 | -- Make sure that we can update to a TOASTed value. 79 | UPDATE update_test SET c = repeat('x', 10000) WHERE c = 'car'; 80 | SELECT a, b, char_length(c) FROM update_test; 81 | 82 | -- Test ON CONFLICT DO UPDATE 83 | INSERT INTO upsert_test VALUES(1, 'Boo'); 84 | -- uncorrelated sub-select: 85 | WITH aaa AS (SELECT 1 AS a, 'Foo' AS b) INSERT INTO upsert_test 86 | VALUES (1, 'Bar') ON CONFLICT(a) 87 | DO UPDATE SET (b, a) = (SELECT b, a FROM aaa) RETURNING *; 88 | -- correlated sub-select: 89 | INSERT INTO upsert_test VALUES (1, 'Baz') ON CONFLICT(a) 90 | DO UPDATE SET (b, a) = (SELECT b || ', Correlated', a from upsert_test i WHERE i.a = upsert_test.a) 91 | RETURNING *; 92 | -- correlated sub-select (EXCLUDED.* alias): 93 | INSERT INTO upsert_test VALUES (1, 'Bat') ON CONFLICT(a) 94 | DO UPDATE SET (b, a) = (SELECT b || ', Excluded', a from upsert_test i WHERE i.a = excluded.a) 95 | RETURNING *; 96 | 97 | DROP TABLE update_test; 98 | DROP TABLE upsert_test; 99 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | CLUSTER vaccluster; 48 | 49 | CREATE FUNCTION do_analyze() RETURNS VOID VOLATILE LANGUAGE SQL 50 | AS 'ANALYZE pg_am'; 51 | CREATE FUNCTION wrap_do_analyze(c INT) RETURNS INT IMMUTABLE LANGUAGE SQL 52 | AS 'SELECT $1 FROM do_analyze()'; 53 | CREATE INDEX ON vaccluster(wrap_do_analyze(i)); 54 | INSERT INTO vaccluster VALUES (1), (2); 55 | ANALYZE vaccluster; 56 | 57 | VACUUM FULL pg_am; 58 | VACUUM FULL pg_class; 59 | VACUUM FULL pg_database; 60 | VACUUM FULL vaccluster; 61 | VACUUM FULL vactst; 62 | 63 | DROP TABLE vaccluster; 64 | DROP TABLE vactst; 65 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | -------------------------------------------------------------------------------- /test/fixtures/upstream/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 | 43 | 44 | -- test that domains are transformed like their base types 45 | 46 | CREATE DOMAIN testboolxmldomain AS bool; 47 | CREATE DOMAIN testdatexmldomain AS date; 48 | 49 | CREATE TABLE testxmlschema.test3 50 | AS SELECT true c1, 51 | true::testboolxmldomain c2, 52 | '2013-02-21'::date c3, 53 | '2013-02-21'::testdatexmldomain c4; 54 | 55 | SELECT xmlforest(c1, c2, c3, c4) FROM testxmlschema.test3; 56 | SELECT table_to_xml('testxmlschema.test3', true, true, ''); 57 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | const chai = require('chai'); 2 | const fs = require('fs'); 3 | const glob = require('glob'); 4 | 5 | chai.should(); 6 | 7 | const { deparse, parse, clean, byType } = require('../src'); 8 | 9 | const pattern = process.env.FILTER ? `*${process.env.FILTER}*.sql` : '*.sql'; 10 | 11 | let files = glob.sync(`./test/fixtures/${pattern}`); 12 | files = files.concat(glob.sync(`./test/fixtures/upstream/${pattern}`)); 13 | 14 | const log = (msg) => { 15 | fs.writeSync(1, `${msg}\n`); 16 | return fs.fsyncSync(1); 17 | }; 18 | 19 | const check = (text) => { 20 | const reference = parse(text).query; 21 | 22 | const parsed = parse(deparse(reference)); 23 | 24 | if (parsed.error) { 25 | throw new Error(parsed.error + ':\n' + deparse(reference)); 26 | } 27 | 28 | const result = deparse(parse(text).query); 29 | 30 | const json1 = JSON.stringify(clean(parse(text).query)); 31 | const json2 = JSON.stringify(clean(parse(result).query)); 32 | 33 | return json1.should.eq(json2); 34 | }; 35 | 36 | const defineQueryTest = (sqlQuery, file) => { 37 | it(`should parse ${sqlQuery.trim()} from ${file}`, () => { 38 | let parsed = null; 39 | 40 | try { 41 | parsed = parse(sqlQuery); 42 | 43 | const validTypes = [ 44 | 'SelectStmt', 45 | 'VariableSetStmt', 46 | 'VariableShowStmt' 47 | ]; 48 | 49 | if (parsed.query.length) { 50 | const key = Object.keys(parsed.query[0])[0]; 51 | 52 | // Only SelectStmt's for now 53 | if (parsed.query && parsed.query[0] && validTypes.indexOf(key) !== -1) { 54 | check(sqlQuery); 55 | } 56 | } 57 | } catch (ex) { 58 | let unsupported = false; 59 | 60 | const unsupportedTypes = [ 61 | 'InsertStmt', 62 | 'UpdateStmt', 63 | 'DeleteStmt', 64 | 'XmlExpr', 65 | 'XmlSerialize' 66 | ]; 67 | 68 | for (const type of unsupportedTypes) { 69 | if (byType(parsed.query, type).length) { 70 | unsupported = true; 71 | } 72 | } 73 | 74 | if (!unsupported) { 75 | log(file); 76 | log(sqlQuery); 77 | log('------------------------------------------'); 78 | log(JSON.stringify(parsed)); 79 | log(ex.stack); 80 | 81 | /* eslint-disable no-process-exit */ 82 | process.exit(1); 83 | /* eslint-enable no-process-exit */ 84 | } 85 | } 86 | }); 87 | }; 88 | 89 | const defineFileTest = (file) => { 90 | return () => { 91 | const content = fs.readFileSync(file).toString().trim(); 92 | 93 | for (const sql of content.split(';')) { 94 | if (sql.trim().length > 0) { 95 | defineQueryTest(sql, file); 96 | } 97 | } 98 | }; 99 | }; 100 | 101 | if (process.env.QUERY != null) { 102 | describe('parser', () => 103 | it(`should parse ${process.env.QUERY}`, () => check(process.env.QUERY)) 104 | ); 105 | } else { 106 | for (const file of files) { 107 | describe('parser: ' + file, defineFileTest(file)); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /verify: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | require('coffee-script/register'); 4 | require('babel-core/register')(); 5 | 6 | const parser = require('./src'); 7 | 8 | const exec = require('child_process').exec; 9 | const fs = require('fs'); 10 | 11 | function runQuery(content) { 12 | const result = parser.deparse(parser.parse(content).query); 13 | 14 | const json1 = parser.clean(parser.parse(content).query); 15 | const json2 = parser.clean(parser.parse(result).query); 16 | 17 | const same = parser.verify(content); 18 | 19 | if (same) { 20 | console.log('OK'); 21 | } else { 22 | console.log('NOT OK'); 23 | 24 | fs.writeFileSync('a.json', JSON.stringify(json1, null, ' ')); 25 | fs.writeFileSync('b.json', JSON.stringify(json2, null, ' ')); 26 | 27 | exec('diff -C10 a.json b.json', (error, stdout, stderr) => { 28 | if (error) { 29 | console.log(error); 30 | } 31 | console.log(stdout); 32 | }); 33 | } 34 | } 35 | 36 | if (process.argv[2]) { 37 | runQuery(process.argv[2]); 38 | } else { 39 | var content = ''; 40 | 41 | process.stdin.resume(); 42 | 43 | process.stdin.on('data', (buf) => { 44 | content += buf.toString(); 45 | }); 46 | 47 | process.stdin.on('end', () => { 48 | runQuery(content); 49 | }); 50 | } 51 | --------------------------------------------------------------------------------