Skip to content

Commit da0eb86

Browse files
committed
Add PROCOID, COLLOID, OPEROID translation
1 parent 6e40f6a commit da0eb86

File tree

10 files changed

+364
-23
lines changed

10 files changed

+364
-23
lines changed

contrib/pg_execplan/init.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@ RETURNS VOID AS 'pg_execplan'
1111
LANGUAGE C;
1212

1313
CREATE OR REPLACE FUNCTION @extschema@.pg_exec_query_plan(filename TEXT)
14-
RETURNS VOID AS 'pg_execplan'
14+
RETURNS BOOL AS 'pg_execplan'
1515
LANGUAGE C;

contrib/pg_execplan/pg_execplan.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "commands/extension.h"
1010
#include "commands/prepare.h"
1111
#include "executor/executor.h"
12+
#include "nodes/nodes.h"
1213
#include "nodes/plannodes.h"
1314
#include "tcop/pquery.h"
1415
#include "tcop/utility.h"
@@ -146,7 +147,7 @@ pg_exec_query_plan(PG_FUNCTION_ARGS)
146147
}
147148
PG_CATCH();
148149
{
149-
elog(INFO, "!!!BAD PLAN: %s", plan_string);
150+
elog(INFO, "BAD PLAN: %s", plan_string);
150151
PG_RE_THROW();
151152
}
152153
PG_END_TRY();
@@ -172,6 +173,8 @@ pg_exec_query_plan(PG_FUNCTION_ARGS)
172173
query_string,
173174
cplan->stmt_list,
174175
cplan);
176+
PG_TRY();
177+
{
175178
PortalStart(portal, paramLI, eflags, InvalidSnapshot);
176179
PortalSetResultFormat(portal, 0, &format);
177180
(void) PortalRun(portal,
@@ -180,12 +183,20 @@ pg_exec_query_plan(PG_FUNCTION_ARGS)
180183
receiver,
181184
receiver,
182185
query_string);
186+
}
187+
PG_CATCH();
188+
{
189+
elog(INFO, "BAD QUERY: %s", query_string);
190+
PG_RETURN_BOOL(false);
191+
}
192+
PG_END_TRY();
193+
183194
receiver->rDestroy(receiver);
184195
PortalDrop(portal, false);
185196
DropPreparedStatement(query_string, false);
186197

187198
if (EXPLAN_DEBUG_LEVEL > 0)
188199
elog(INFO, "query execution finished.\n");
189200

190-
PG_RETURN_VOID();
201+
PG_RETURN_BOOL(true);
191202
}

contrib/pg_execplan/tests/create_objects.sql

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
CREATE SCHEMA tests;
2+
SET search_path = 'tests';
3+
4+
CREATE TYPE int42;
15
-- Make dummy I/O routines using the existing internal support for int4, text
26
CREATE FUNCTION int42_in(cstring)
37
RETURNS int42
@@ -17,4 +21,29 @@ CREATE TYPE int42 (
1721
passedbyvalue
1822
);
1923

20-
CREATE TABLE t1 (id int42);
24+
-- RELOID, TYPEOID
25+
CREATE TABLE tests.t1 (id int42);
26+
CREATE TABLE t2 (id int, payload TEXT, par1 INT);
27+
28+
CREATE FUNCTION select1(tid INT) RETURNS VOID AS $$
29+
BEGIN
30+
INSERT INTO tests.t2 (id, payload, par1) VALUES (1, 'qwe', 2);
31+
END;
32+
$$ LANGUAGE plpgsql;
33+
34+
-- COLLOID
35+
CREATE COLLATION test1 (locale = 'en_US.utf8');
36+
CREATE TABLE ttest1 (
37+
id serial,
38+
a text COLLATE test1,
39+
b text COLLATE test1
40+
);
41+
INSERT INTO ttest1 (a, b) VALUES ('one', 'one');
42+
INSERT INTO ttest1 (a, b) VALUES ('one', 'two');
43+
44+
-- OPEROID
45+
CREATE OPERATOR public.### (
46+
leftarg = numeric,
47+
rightarg = numeric,
48+
procedure = numeric_add
49+
);

contrib/pg_execplan/tests/rpl.sh

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#!/bin/bash
22

3-
# Script for the plan passing between separate instances
3+
# This script to pass some plans between separate instances.
44
U=`whoami`
5+
export LC_ALL=C
6+
export LANGUAGE="en_US:en"
57

68
# Paths
79
PGINSTALL=`pwd`/tmp_install/
@@ -25,8 +27,8 @@ make -C contrib install > /dev/null
2527

2628
mkdir PGDATA_Master
2729
mkdir PGDATA_Slave
28-
initdb -D PGDATA_Master
29-
initdb -D PGDATA_Slave
30+
initdb -D PGDATA_Master -E UTF8 --locale=C
31+
initdb -D PGDATA_Slave -E UTF8 --locale=C
3032
echo "shared_preload_libraries = 'postgres_fdw, pg_execplan'" >> PGDATA_Master/postgresql.conf
3133
echo "shared_preload_libraries = 'postgres_fdw, pg_execplan'" >> PGDATA_Slave/postgresql.conf
3234

@@ -47,8 +49,39 @@ psql -p 5433 -c "DROP TABLE t0;"
4749
#create database objects for check of oid switching
4850
psql -p 5432 -f contrib/pg_execplan/tests/create_objects.sql
4951
psql -p 5433 -f contrib/pg_execplan/tests/create_objects.sql
52+
psql -p 5433 -c "SELECT current_schemas(true);"
5053

5154
# TEST ON RELOID and TYPEOID objects.
52-
psql -p 5432 -c "SELECT pg_store_query_plan('../test.txt', 'SELECT * FROM t1;');"
55+
psql -p 5432 -c "SELECT pg_store_query_plan('../test.txt', 'SELECT * FROM tests.t1;');"
56+
psql -p 5433 -c "SELECT pg_exec_query_plan('../test.txt');"
57+
58+
psql -p 5432 -c "SELECT pg_store_query_plan('../test.txt', 'SELECT tests.select1(42);');"
59+
psql -p 5433 -c "SELECT pg_exec_query_plan('../test.txt');"
60+
psql -p 5432 -c "SELECT pg_exec_query_plan('../test.txt');"
61+
62+
psql -p 5432 -c "SELECT * FROM tests.t2;"
63+
psql -p 5433 -c "SELECT * FROM tests.t2;"
64+
65+
# COLLOID ----------------------------------------------------------------------
66+
# Check on different oids
67+
psql -p 5432 -c "SELECT oid, * FROM pg_collation WHERE collname LIKE 'test%';"
68+
psql -p 5433 -c "SELECT oid, * FROM pg_collation WHERE collname LIKE 'test%';"
69+
70+
psql -p 5432 -c "SELECT pg_store_query_plan('../test.txt', 'SELECT max(id) FROM tests.ttest1 WHERE a < b COLLATE tests.test1');"
71+
psql -p 5433 -c "SELECT pg_exec_query_plan('../test.txt');"
72+
73+
# OPEROID ----------------------------------------------------------------------
74+
# Check on different oids
75+
psql -p 5432 -c "SELECT oid, oprname, oprnamespace FROM pg_operator WHERE oprname LIKE '###';"
76+
psql -p 5433 -c "SELECT oid, oprname, oprnamespace FROM pg_operator WHERE oprname LIKE '###';"
77+
78+
# Test
79+
psql -p 5432 -c "SELECT pg_store_query_plan('../test.txt', 'SELECT id ### 1 FROM tests.ttest1;');"
80+
psql -p 5433 -c "SELECT pg_exec_query_plan('../test.txt');"
81+
82+
psql -p 5433 -c "SELECT pg_store_query_plan('../test.txt', 'SELECT collname, nspname
83+
FROM pg_collation JOIN pg_namespace ON (collnamespace = pg_namespace.oid)
84+
WHERE collname LIKE ''test%''
85+
ORDER BY 1;');"
5386
psql -p 5433 -c "SELECT pg_exec_query_plan('../test.txt');"
5487

src/backend/nodes/outfuncs.c

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,9 @@
3434
#include "utils/rel.h"
3535
#include "utils/syscache.h"
3636

37-
#define OID_TYPES_NUM (2)
38-
static const Oid oid_types[OID_TYPES_NUM] = {RELOID, TYPEOID};
37+
#define NSP_NAME(nspoid) (get_namespace_name(nspoid))
38+
#define OID_TYPES_NUM (5)
39+
static const Oid oid_types[OID_TYPES_NUM] = {RELOID, TYPEOID, PROCOID, COLLOID, OPEROID};
3940

4041
static bool portable_output = false;
4142
void
@@ -60,7 +61,6 @@ write_oid_field(StringInfo str, Oid oid)
6061
if (!OidIsValid(oid))
6162
{
6263
/* Special case for invalid oid fields. For example, checkAsUser. */
63-
elog(INFO, "oid %d is INVALID OID!", oid);
6464
appendStringInfo(str, "%u %u)", 0, oid);
6565
return;
6666
}
@@ -79,27 +79,69 @@ write_oid_field(StringInfo str, Oid oid)
7979
switch (oid_types[i])
8080
{
8181
case RELOID:
82-
elog(INFO, "(RELOID %d): (%s, %s)", oid,
83-
get_namespace_name((get_rel_namespace((oid)))),
84-
get_rel_name((oid))
85-
);
8682
appendStringInfo(str, "%u %s %s", RELOID,
8783
get_namespace_name((get_rel_namespace((oid)))),
8884
get_rel_name((oid)));
8985
break;
9086

9187
case TYPEOID:
92-
elog(INFO, "(TYPEOID %d): %s %s", oid,
93-
get_namespace_name(get_typ_namespace(oid)),
94-
get_typ_name(oid));
9588
appendStringInfo(str, "%u %s %s", TYPEOID,
9689
get_namespace_name(get_typ_namespace(oid)),
9790
get_typ_name(oid));
9891

9992
break;
10093

94+
case PROCOID:
95+
{
96+
Oid *argtypes;
97+
int i, nargs;
98+
99+
get_func_signature(oid, &argtypes, &nargs);
100+
appendStringInfo(str, "%u %s", PROCOID, NSP_NAME(get_func_namespace(oid)));
101+
appendStringInfo(str, " %s", get_func_name(oid));
102+
appendStringInfo(str, " %d", nargs);
103+
104+
for (i = 0; i < nargs; i++)
105+
{
106+
appendStringInfoChar(str, ' ');
107+
outToken(str, NSP_NAME(get_typ_namespace(argtypes[i])));
108+
appendStringInfoChar(str, ' ');
109+
outToken(str, get_typ_name(argtypes[i]));
110+
}
111+
}
112+
break;
113+
case COLLOID:
114+
appendStringInfo(str, "%u ", COLLOID);
115+
outToken(str, NSP_NAME(get_collation_namespace(oid)));
116+
appendStringInfoChar(str, ' ');
117+
outToken(str, get_collation_name(oid));
118+
appendStringInfo(str, " %d", get_collation_encoding(oid));
119+
break;
120+
121+
case OPEROID:
122+
{
123+
Oid oprleft, oprright;
124+
125+
appendStringInfo(str, "%u ", OPEROID);
126+
outToken(str, NSP_NAME(get_opnamespace(oid)));
127+
appendStringInfoChar(str, ' ');
128+
outToken(str, get_opname(oid));
129+
appendStringInfoChar(str, ' ');
130+
op_input_types(oid, &oprleft, &oprright);
131+
outToken(str, OidIsValid(oprleft) ?
132+
NSP_NAME(get_typ_namespace(oprleft)) : NULL);
133+
appendStringInfoChar(str, ' ');
134+
outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL);
135+
appendStringInfoChar(str, ' ');
136+
outToken(str, OidIsValid(oprright) ?
137+
NSP_NAME(get_typ_namespace(oprright)) : NULL);
138+
appendStringInfoChar(str, ' ');
139+
outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL);
140+
}
141+
break;
142+
101143
default:
102-
elog(ERROR, "oid %d type is %d (NOT DEFINED)!", oid, oid_types[i]);
144+
Assert(0);
103145
break;
104146
}
105147
appendStringInfo(str, ")");

src/backend/nodes/readfuncs.c

Lines changed: 99 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,12 @@
3535
#include "nodes/readfuncs.h"
3636

3737
/* Portable-related dependencies */
38-
#include "utils/lsyscache.h"
3938
#include "catalog/namespace.h"
39+
#include "utils/builtins.h"
40+
#include "utils/lsyscache.h"
4041
#include "utils/syscache.h"
4142

43+
#define NSP_OID(nspname) LookupNamespaceNoError(nspname)
4244
static Oid read_oid_field(char **token, int *length);
4345

4446
static bool portable_input = false;
@@ -2775,7 +2777,6 @@ read_oid_field(char **token, int *length)
27752777
*token = pg_strtok(length); /* Switch to relname */
27762778
relname = nullable_string(*token, *length);
27772779
oid = get_relname_relid(relname, rel_nsp_oid);
2778-
elog(INFO, "reloid=%d", oid);
27792780
break;
27802781
}
27812782
case TYPEOID:
@@ -2796,7 +2797,102 @@ read_oid_field(char **token, int *length)
27962797
}
27972798
else
27982799
oid = InvalidOid;
2799-
elog(INFO, "typeoid=%d", oid);
2800+
}
2801+
break;
2802+
2803+
case PROCOID:
2804+
{
2805+
char *nspname; /* namespace name */
2806+
char *funcname; /* function name */
2807+
int nargs; /* number of arguments */
2808+
Oid *argtypes; /* argument types */
2809+
2810+
*token = pg_strtok(length); /* get nspname */
2811+
nspname = nullable_string(*token, *length);
2812+
*token = pg_strtok(length); /* get funcname */
2813+
funcname = nullable_string(*token, *length);
2814+
*token = pg_strtok(length); /* get nargs */
2815+
nargs = atoi(*token);
2816+
2817+
if (funcname)
2818+
{
2819+
int i;
2820+
argtypes = palloc(nargs * sizeof(Oid));
2821+
for (i = 0; i < nargs; i++)
2822+
{
2823+
char *typnspname; /* argument type namespace */
2824+
char *typname; /* argument type name */
2825+
2826+
*token = pg_strtok(length); /* get type nspname */
2827+
typnspname = nullable_string(*token, *length);
2828+
*token = pg_strtok(length); /* get type name */
2829+
typname = nullable_string(*token, *length);
2830+
argtypes[i] = get_typname_typid(typname,
2831+
NSP_OID(typnspname));
2832+
}
2833+
oid = get_funcid(funcname, buildoidvector(argtypes, nargs), NSP_OID(nspname));
2834+
}
2835+
else
2836+
oid = InvalidOid;
2837+
}
2838+
break;
2839+
2840+
case COLLOID:
2841+
{
2842+
char *nspname; /* namespace name */
2843+
char *collname; /* collation name */
2844+
int collencoding; /* collation encoding */
2845+
2846+
*token = pg_strtok(length); /* get nspname */
2847+
nspname = nullable_string(*token, *length);
2848+
*token = pg_strtok(length); /* get collname */
2849+
collname = nullable_string(*token, *length);
2850+
*token = pg_strtok(length); /* get collencoding */
2851+
collencoding = atoi(*token);
2852+
if (collname)
2853+
oid = get_collid(collname, collencoding, NSP_OID(nspname));
2854+
else
2855+
oid = InvalidOid;
2856+
}
2857+
break;
2858+
2859+
case OPEROID:
2860+
{
2861+
char *nspname; /* namespace name */
2862+
char *oprname; /* operator name */
2863+
char *leftnspname; /* left type namespace */
2864+
char *leftname; /* left type name */
2865+
Oid oprleft; /* left type */
2866+
char *rightnspname; /* right type namespace */
2867+
char *rightname; /* right type name */
2868+
Oid oprright; /* right type */
2869+
2870+
*token = pg_strtok(length); /* get nspname */
2871+
nspname = nullable_string(*token, *length);
2872+
*token = pg_strtok(length); /* get operator name */
2873+
oprname = nullable_string(*token, *length);
2874+
*token = pg_strtok(length); /* left type namespace */
2875+
leftnspname = nullable_string(*token, *length);
2876+
*token = pg_strtok(length); /* left type name */
2877+
leftname = nullable_string(*token, *length);
2878+
*token = pg_strtok(length); /* right type namespace */
2879+
rightnspname = nullable_string(*token, *length);
2880+
*token = pg_strtok(length); /* right type name */
2881+
rightname =nullable_string(*token, *length);
2882+
if (oprname)
2883+
{
2884+
if (leftname)
2885+
oprleft = get_typname_typid(leftname, NSP_OID(leftnspname));
2886+
else
2887+
oprleft = InvalidOid;
2888+
if (rightname)
2889+
oprright = get_typname_typid(rightname, NSP_OID(rightnspname));
2890+
else
2891+
oprright = InvalidOid;
2892+
oid = get_operid(oprname, oprleft, oprright, NSP_OID(nspname));
2893+
}
2894+
else
2895+
oid = InvalidOid;
28002896
}
28012897
break;
28022898

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy