Skip to content

Commit 68396fe

Browse files
committed
Allow installation in alternate schema w/o search_path hacking. Closes #122
1 parent e8f5d60 commit 68396fe

3 files changed

Lines changed: 72 additions & 27 deletions

File tree

http--1.4.sql

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,32 +63,32 @@ CREATE OR REPLACE FUNCTION http(request http_request)
6363

6464
CREATE OR REPLACE FUNCTION http_get(uri VARCHAR)
6565
RETURNS http_response
66-
AS $$ SELECT http(('GET', $1, NULL, NULL, NULL)::http_request) $$
66+
AS $$ SELECT @extschema@.http(('GET', $1, NULL, NULL, NULL)::@extschema@.http_request) $$
6767
LANGUAGE 'sql';
6868

6969
CREATE OR REPLACE FUNCTION http_post(uri VARCHAR, content VARCHAR, content_type VARCHAR)
7070
RETURNS http_response
71-
AS $$ SELECT http(('POST', $1, NULL, $3, $2)::http_request) $$
71+
AS $$ SELECT @extschema@.http(('POST', $1, NULL, $3, $2)::@extschema@.http_request) $$
7272
LANGUAGE 'sql';
7373

7474
CREATE OR REPLACE FUNCTION http_put(uri VARCHAR, content VARCHAR, content_type VARCHAR)
7575
RETURNS http_response
76-
AS $$ SELECT http(('PUT', $1, NULL, $3, $2)::http_request) $$
76+
AS $$ SELECT @extschema@.http(('PUT', $1, NULL, $3, $2)::@extschema@.http_request) $$
7777
LANGUAGE 'sql';
7878

7979
CREATE OR REPLACE FUNCTION http_patch(uri VARCHAR, content VARCHAR, content_type VARCHAR)
8080
RETURNS http_response
81-
AS $$ SELECT http(('PATCH', $1, NULL, $3, $2)::http_request) $$
81+
AS $$ SELECT @extschema@.http(('PATCH', $1, NULL, $3, $2)::@extschema@.http_request) $$
8282
LANGUAGE 'sql';
8383

8484
CREATE OR REPLACE FUNCTION http_delete(uri VARCHAR)
8585
RETURNS http_response
86-
AS $$ SELECT http(('DELETE', $1, NULL, NULL, NULL)::http_request) $$
86+
AS $$ SELECT @extschema@.http(('DELETE', $1, NULL, NULL, NULL)::@extschema@.http_request) $$
8787
LANGUAGE 'sql';
8888

8989
CREATE OR REPLACE FUNCTION http_head(uri VARCHAR)
9090
RETURNS http_response
91-
AS $$ SELECT http(('HEAD', $1, NULL, NULL, NULL)::http_request) $$
91+
AS $$ SELECT @extschema@.http(('HEAD', $1, NULL, NULL, NULL)::@extschema@.http_request) $$
9292
LANGUAGE 'sql';
9393

9494
CREATE OR REPLACE FUNCTION urlencode(string VARCHAR)
@@ -111,12 +111,16 @@ CREATE OR REPLACE FUNCTION urlencode(data JSONB)
111111

112112
CREATE OR REPLACE FUNCTION http_get(uri VARCHAR, data JSONB)
113113
RETURNS http_response
114-
AS $$ SELECT http(('GET', $1 || '?' || urlencode($2), NULL, NULL, NULL)::http_request) $$
114+
AS $$
115+
SELECT @extschema@.http(('GET', $1 || '?' || urlencode($2), NULL, NULL, NULL)::@extschema@.http_request)
116+
$$
115117
LANGUAGE 'sql';
116118

117119
CREATE OR REPLACE FUNCTION http_post(uri VARCHAR, data JSONB)
118120
RETURNS http_response
119-
AS $$ SELECT http(('POST', $1, NULL, 'application/x-www-form-urlencoded', urlencode($2))::http_request) $$
121+
AS $$
122+
SELECT @extschema@.http(('POST', $1, NULL, 'application/x-www-form-urlencoded', urlencode($2))::@extschema@.http_request)
123+
$$
120124
LANGUAGE 'sql';
121125

122126

http.c

Lines changed: 60 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,12 @@
4343
#include <postgres.h>
4444
#include <fmgr.h>
4545
#include <funcapi.h>
46+
#include <access/genam.h>
4647
#include <access/htup.h>
48+
#include <access/table.h>
4749
#include <catalog/namespace.h>
4850
#include <catalog/pg_type.h>
51+
#include <catalog/pg_extension.h>
4952
#include <catalog/dependency.h>
5053
#include <commands/extension.h>
5154
#include <lib/stringinfo.h>
@@ -58,6 +61,7 @@
5861
#include <utils/lsyscache.h>
5962
#include <utils/syscache.h>
6063
#include <utils/typcache.h>
64+
#include <utils/fmgroids.h>
6165
#include <utils/guc.h>
6266

6367
#if PG_VERSION_NUM >= 100000
@@ -574,6 +578,43 @@ header_array_to_slist(ArrayType *array, struct curl_slist *headers)
574578
return headers;
575579
}
576580

581+
/**
582+
* Look up the namespace the extension is installed in
583+
*/
584+
static Oid
585+
get_extension_schema(Oid ext_oid)
586+
{
587+
Oid result;
588+
Relation rel;
589+
SysScanDesc scandesc;
590+
HeapTuple tuple;
591+
ScanKeyData entry[1];
592+
593+
rel = table_open(ExtensionRelationId, AccessShareLock);
594+
595+
ScanKeyInit(&entry[0],
596+
Anum_pg_extension_oid,
597+
BTEqualStrategyNumber, F_OIDEQ,
598+
ObjectIdGetDatum(ext_oid));
599+
600+
scandesc = systable_beginscan(rel, ExtensionOidIndexId, true,
601+
NULL, 1, entry);
602+
603+
tuple = systable_getnext(scandesc);
604+
605+
/* We assume that there can be at most one matching tuple */
606+
if (HeapTupleIsValid(tuple))
607+
result = ((Form_pg_extension) GETSTRUCT(tuple))->extnamespace;
608+
else
609+
result = InvalidOid;
610+
611+
systable_endscan(scandesc);
612+
613+
table_close(rel, AccessShareLock);
614+
615+
return result;
616+
}
617+
577618
/**
578619
* Look up the tuple description for a extension-defined type,
579620
* avoiding the pitfalls of using relations that are not part
@@ -584,33 +625,30 @@ static TupleDesc
584625
typname_get_tupledesc(const char *extname, const char *typname)
585626
{
586627
Oid extoid = get_extension_oid(extname, true);
587-
ListCell *l;
628+
Oid extschemaoid;
588629

589630
if ( ! OidIsValid(extoid) )
590631
elog(ERROR, "could not lookup '%s' extension oid", extname);
591632

592-
foreach(l, fetch_search_path(true))
593-
{
594-
Oid typnamespace = lfirst_oid(l);
633+
extschemaoid = get_extension_schema(extoid);
595634

596635
#if PG_VERSION_NUM >= 120000
597-
Oid typoid = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid,
598-
PointerGetDatum(typname),
599-
ObjectIdGetDatum(typnamespace));
636+
Oid typoid = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid,
637+
PointerGetDatum(typname),
638+
ObjectIdGetDatum(extschemaoid));
600639
#else
601-
Oid typoid = GetSysCacheOid2(TYPENAMENSP,
602-
PointerGetDatum(typname),
603-
ObjectIdGetDatum(typnamespace));
640+
Oid typoid = GetSysCacheOid2(TYPENAMENSP,
641+
PointerGetDatum(typname),
642+
ObjectIdGetDatum(extschemaoid));
604643
#endif
605644

606-
if ( OidIsValid(typoid) )
645+
if ( OidIsValid(typoid) )
646+
{
647+
// Oid typ_oid = get_typ_typrelid(rel_oid);
648+
Oid relextoid = getExtensionOfObject(TypeRelationId, typoid);
649+
if ( relextoid == extoid )
607650
{
608-
// Oid typ_oid = get_typ_typrelid(rel_oid);
609-
Oid relextoid = getExtensionOfObject(TypeRelationId, typoid);
610-
if ( relextoid == extoid )
611-
{
612-
return TypeGetTupleDesc(typoid, NIL);
613-
}
651+
return TypeGetTupleDesc(typoid, NIL);
614652
}
615653
}
616654

@@ -1206,7 +1244,11 @@ Datum http_request(PG_FUNCTION_ARGS)
12061244
}
12071245

12081246
/* Prepare our return object */
1209-
tup_desc = RelationNameGetTupleDesc("http_response");
1247+
if (get_call_result_type(fcinfo, 0, &tup_desc) != TYPEFUNC_COMPOSITE) {
1248+
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1249+
errmsg("%s called with incompatible return type", __func__)));
1250+
}
1251+
12101252
ncolumns = tup_desc->natts;
12111253
values = palloc0(sizeof(Datum)*ncolumns);
12121254
nulls = palloc0(sizeof(bool)*ncolumns);

http.control

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
default_version = '1.4'
22
module_pathname = '$libdir/http'
3-
relocatable = true
43
comment = 'HTTP client for PostgreSQL, allows web page retrieval inside the database.'

0 commit comments

Comments
 (0)