summaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
Diffstat (limited to 'contrib')
-rw-r--r--contrib/ltree/expected/ltree.out2
-rw-r--r--contrib/ltree/ltree_op.c14
-rw-r--r--contrib/ltree/sql/ltree.sql1
-rw-r--r--contrib/pg_stat_statements/expected/squashing.out80
-rw-r--r--contrib/pg_stat_statements/pg_stat_statements.c33
-rw-r--r--contrib/pg_stat_statements/sql/squashing.sql26
-rw-r--r--contrib/pg_surgery/heap_surgery.c4
7 files changed, 131 insertions, 29 deletions
diff --git a/contrib/ltree/expected/ltree.out b/contrib/ltree/expected/ltree.out
index c8eac3f6b21..d2a56628475 100644
--- a/contrib/ltree/expected/ltree.out
+++ b/contrib/ltree/expected/ltree.out
@@ -128,6 +128,8 @@ SELECT subpath('Top.Child1.Child2',1);
Child1.Child2
(1 row)
+SELECT subpath('Top.Child1.Child2',-4); -- error
+ERROR: invalid positions
SELECT index('1.2.3.4.5.6','1.2');
index
-------
diff --git a/contrib/ltree/ltree_op.c b/contrib/ltree/ltree_op.c
index ce9f4caad4f..e3a84db37ff 100644
--- a/contrib/ltree/ltree_op.c
+++ b/contrib/ltree/ltree_op.c
@@ -316,23 +316,15 @@ subpath(PG_FUNCTION_ARGS)
int32 end;
ltree *res;
- end = start + len;
-
- if (start < 0)
- {
- start = t->numlevel + start;
- end = start + len;
- }
if (start < 0)
- { /* start > t->numlevel */
start = t->numlevel + start;
- end = start + len;
- }
if (len < 0)
end = t->numlevel + len;
else if (len == 0)
- end = (fcinfo->nargs == 3) ? start : 0xffff;
+ end = (fcinfo->nargs == 3) ? start : LTREE_MAX_LEVELS;
+ else
+ end = start + len;
res = inner_subltree(t, start, end);
diff --git a/contrib/ltree/sql/ltree.sql b/contrib/ltree/sql/ltree.sql
index dd705d9d7ca..77e6958c62a 100644
--- a/contrib/ltree/sql/ltree.sql
+++ b/contrib/ltree/sql/ltree.sql
@@ -34,6 +34,7 @@ SELECT subpath('Top.Child1.Child2',0,0);
SELECT subpath('Top.Child1.Child2',1,0);
SELECT subpath('Top.Child1.Child2',0);
SELECT subpath('Top.Child1.Child2',1);
+SELECT subpath('Top.Child1.Child2',-4); -- error
SELECT index('1.2.3.4.5.6','1.2');
diff --git a/contrib/pg_stat_statements/expected/squashing.out b/contrib/pg_stat_statements/expected/squashing.out
index f952f47ef7b..d5bb67c7222 100644
--- a/contrib/pg_stat_statements/expected/squashing.out
+++ b/contrib/pg_stat_statements/expected/squashing.out
@@ -809,6 +809,84 @@ SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C";
select where $1 IN ($2 /*, ... */) | 2
(2 rows)
+-- composite function with row expansion
+create table test_composite(x integer);
+CREATE FUNCTION composite_f(a integer[], out x integer, out y integer) returns
+record as $$ begin
+ x = a[1];
+ y = a[2];
+ end;
+$$ language plpgsql;
+SELECT pg_stat_statements_reset() IS NOT NULL AS t;
+ t
+---
+ t
+(1 row)
+
+SELECT ((composite_f(array[1, 2]))).* FROM test_composite;
+ x | y
+---+---
+(0 rows)
+
+SELECT ((composite_f(array[1, 2, 3]))).* FROM test_composite;
+ x | y
+---+---
+(0 rows)
+
+SELECT ((composite_f(array[1, 2, 3]))).*, 1, 2, 3, ((composite_f(array[1, 2, 3]))).*, 1, 2
+FROM test_composite
+WHERE x IN (1, 2, 3);
+ x | y | ?column? | ?column? | ?column? | x | y | ?column? | ?column?
+---+---+----------+----------+----------+---+---+----------+----------
+(0 rows)
+
+SELECT ((composite_f(array[1, $1, 3]))).*, 1 FROM test_composite \bind 1
+;
+ x | y | ?column?
+---+---+----------
+(0 rows)
+
+-- ROW() expression with row expansion
+SELECT (ROW(ARRAY[1,2])).*;
+ f1
+-------
+ {1,2}
+(1 row)
+
+SELECT (ROW(ARRAY[1, 2], ARRAY[1, 2, 3])).*;
+ f1 | f2
+-------+---------
+ {1,2} | {1,2,3}
+(1 row)
+
+SELECT 1, 2, (ROW(ARRAY[1, 2], ARRAY[1, 2, 3])).*, 3, 4;
+ ?column? | ?column? | f1 | f2 | ?column? | ?column?
+----------+----------+-------+---------+----------+----------
+ 1 | 2 | {1,2} | {1,2,3} | 3 | 4
+(1 row)
+
+SELECT (ROW(ARRAY[1, 2], ARRAY[1, $1, 3])).*, 1 \bind 1
+;
+ f1 | f2 | ?column?
+-------+---------+----------
+ {1,2} | {1,1,3} | 1
+(1 row)
+
+SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C";
+ query | calls
+-------------------------------------------------------------------------------------------------------------+-------
+ SELECT $1, $2, (ROW(ARRAY[$3 /*, ... */], ARRAY[$4 /*, ... */])).*, $5, $6 | 1
+ SELECT ((composite_f(array[$1 /*, ... */]))).* FROM test_composite | 2
+ SELECT ((composite_f(array[$1 /*, ... */]))).*, $2 FROM test_composite | 1
+ SELECT ((composite_f(array[$1 /*, ... */]))).*, $2, $3, $4, ((composite_f(array[$5 /*, ... */]))).*, $6, $7+| 1
+ FROM test_composite +|
+ WHERE x IN ($8 /*, ... */) |
+ SELECT (ROW(ARRAY[$1 /*, ... */])).* | 1
+ SELECT (ROW(ARRAY[$1 /*, ... */], ARRAY[$2 /*, ... */])).* | 1
+ SELECT (ROW(ARRAY[$1 /*, ... */], ARRAY[$2 /*, ... */])).*, $3 | 1
+ SELECT pg_stat_statements_reset() IS NOT NULL AS t | 1
+(8 rows)
+
--
-- cleanup
--
@@ -818,3 +896,5 @@ DROP TABLE test_squash_numeric;
DROP TABLE test_squash_bigint;
DROP TABLE test_squash_cast CASCADE;
DROP TABLE test_squash_jsonb;
+DROP TABLE test_composite;
+DROP FUNCTION composite_f;
diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c
index f2187167c5c..39208f80b5b 100644
--- a/contrib/pg_stat_statements/pg_stat_statements.c
+++ b/contrib/pg_stat_statements/pg_stat_statements.c
@@ -2954,9 +2954,8 @@ generate_normalized_query(JumbleState *jstate, const char *query,
* have originated from within the authoritative parser, this should not be
* a problem.
*
- * Duplicate constant pointers are possible, and will have their lengths
- * marked as '-1', so that they are later ignored. (Actually, we assume the
- * lengths were initialized as -1 to start with, and don't change them here.)
+ * Multiple constants can have the same location. We reset lengths of those
+ * past the first to -1 so that they can later be ignored.
*
* If query_loc > 0, then "query" has been advanced by that much compared to
* the original string start, so we need to translate the provided locations
@@ -2976,8 +2975,6 @@ fill_in_constant_lengths(JumbleState *jstate, const char *query,
core_yy_extra_type yyextra;
core_YYSTYPE yylval;
YYLTYPE yylloc;
- int last_loc = -1;
- int i;
/*
* Sort the records by location so that we can process them in order while
@@ -2998,23 +2995,29 @@ fill_in_constant_lengths(JumbleState *jstate, const char *query,
yyextra.escape_string_warning = false;
/* Search for each constant, in sequence */
- for (i = 0; i < jstate->clocations_count; i++)
+ for (int i = 0; i < jstate->clocations_count; i++)
{
- int loc = locs[i].location;
+ int loc;
int tok;
- /* Adjust recorded location if we're dealing with partial string */
- loc -= query_loc;
-
- Assert(loc >= 0);
+ /* Ignore constants after the first one in the same location */
+ if (i > 0 && locs[i].location == locs[i - 1].location)
+ {
+ locs[i].length = -1;
+ continue;
+ }
if (locs[i].squashed)
continue; /* squashable list, ignore */
- if (loc <= last_loc)
- continue; /* Duplicate constant, ignore */
+ /* Adjust recorded location if we're dealing with partial string */
+ loc = locs[i].location - query_loc;
+ Assert(loc >= 0);
- /* Lex tokens until we find the desired constant */
+ /*
+ * We have a valid location for a constant that's not a dupe. Lex
+ * tokens until we find the desired constant.
+ */
for (;;)
{
tok = core_yylex(&yylval, &yylloc, yyscanner);
@@ -3060,8 +3063,6 @@ fill_in_constant_lengths(JumbleState *jstate, const char *query,
/* If we hit end-of-string, give up, leaving remaining lengths -1 */
if (tok == 0)
break;
-
- last_loc = loc;
}
scanner_finish(yyscanner);
diff --git a/contrib/pg_stat_statements/sql/squashing.sql b/contrib/pg_stat_statements/sql/squashing.sql
index 53138d125a9..03b0515f872 100644
--- a/contrib/pg_stat_statements/sql/squashing.sql
+++ b/contrib/pg_stat_statements/sql/squashing.sql
@@ -291,6 +291,30 @@ select where '1' IN ('1'::int::text, '2'::int::text);
select where '1' = ANY (array['1'::int::text, '2'::int::text]);
SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C";
+-- composite function with row expansion
+create table test_composite(x integer);
+CREATE FUNCTION composite_f(a integer[], out x integer, out y integer) returns
+record as $$ begin
+ x = a[1];
+ y = a[2];
+ end;
+$$ language plpgsql;
+SELECT pg_stat_statements_reset() IS NOT NULL AS t;
+SELECT ((composite_f(array[1, 2]))).* FROM test_composite;
+SELECT ((composite_f(array[1, 2, 3]))).* FROM test_composite;
+SELECT ((composite_f(array[1, 2, 3]))).*, 1, 2, 3, ((composite_f(array[1, 2, 3]))).*, 1, 2
+FROM test_composite
+WHERE x IN (1, 2, 3);
+SELECT ((composite_f(array[1, $1, 3]))).*, 1 FROM test_composite \bind 1
+;
+-- ROW() expression with row expansion
+SELECT (ROW(ARRAY[1,2])).*;
+SELECT (ROW(ARRAY[1, 2], ARRAY[1, 2, 3])).*;
+SELECT 1, 2, (ROW(ARRAY[1, 2], ARRAY[1, 2, 3])).*, 3, 4;
+SELECT (ROW(ARRAY[1, 2], ARRAY[1, $1, 3])).*, 1 \bind 1
+;
+SELECT query, calls FROM pg_stat_statements ORDER BY query COLLATE "C";
+
--
-- cleanup
--
@@ -300,3 +324,5 @@ DROP TABLE test_squash_numeric;
DROP TABLE test_squash_bigint;
DROP TABLE test_squash_cast CASCADE;
DROP TABLE test_squash_jsonb;
+DROP TABLE test_composite;
+DROP FUNCTION composite_f;
diff --git a/contrib/pg_surgery/heap_surgery.c b/contrib/pg_surgery/heap_surgery.c
index 3e86283beb7..1096b05d782 100644
--- a/contrib/pg_surgery/heap_surgery.c
+++ b/contrib/pg_surgery/heap_surgery.c
@@ -356,8 +356,8 @@ heap_force_common(FunctionCallInfo fcinfo, HeapTupleForceOption heap_force_opt)
static int32
tidcmp(const void *a, const void *b)
{
- ItemPointer iptr1 = ((const ItemPointer) a);
- ItemPointer iptr2 = ((const ItemPointer) b);
+ const ItemPointerData *iptr1 = a;
+ const ItemPointerData *iptr2 = b;
return ItemPointerCompare(iptr1, iptr2);
}