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)