Thread: small dblink patch

small dblink patch

From
Joe Conway
Date:
Please apply the attached small patch, which fixes a schema related
issue with several dblink functions.

- If the same relation exists in multiple schema, current sources fail
to resolve an unqualified relname.
- Current sources do not allow schema qualified names.

The patch fixes both issues by using the (relatively new) regclassin()
function to resolve the relname to an Oid.

Thanks,

Joe
Index: contrib/dblink//dblink.c
===================================================================
RCS file: /opt/src/cvs/pgsql/contrib/dblink/dblink.c,v
retrieving revision 1.6
diff -c -r1.6 dblink.c
*** contrib/dblink//dblink.c    20 May 2002 23:51:40 -0000    1.6
--- contrib/dblink//dblink.c    27 May 2002 04:30:22 -0000
***************
*** 1346,1352 ****
  #ifdef NamespaceRelationName
      Oid                relid;

!     relid = RelnameGetRelid(relname);
  #else
      Relation        rel;
      Oid                relid;
--- 1346,1352 ----
  #ifdef NamespaceRelationName
      Oid                relid;

!     relid = DatumGetObjectId(DirectFunctionCall1(regclassin, CStringGetDatum(relname)));
  #else
      Relation        rel;
      Oid                relid;

Re: small dblink patch

From
Tom Lane
Date:
Joe Conway <mail@joeconway.com> writes:
> Please apply the attached small patch, which fixes a schema related
> issue with several dblink functions.
> - If the same relation exists in multiple schema, current sources fail
> to resolve an unqualified relname.
> - Current sources do not allow schema qualified names.

This isn't going to fix the problem --- all the functions are still
declared to take type NAME, which will not be long enough for qualified
names.  You need to replace the use of NAME with use of TEXT.

> The patch fixes both issues by using the (relatively new) regclassin()
> function to resolve the relname to an Oid.

I don't particularly care for that answer.  Would instead suggest you
borrow the coding now being used in sequence.c and other places where
text arguments are interpreted as relation names:

    text       *seqin = PG_GETARG_TEXT_P(0);
    RangeVar   *sequence;
    Oid         relid;

    sequence = makeRangeVarFromNameList(textToQualifiedNameList(seqin,
                                                                "nextval"));

    relid = RangeVarGetRelid(sequence, false);
    // or better, do heap_openrv directly

            regards, tom lane

Re: small dblink patch

From
Tom Lane
Date:
Joe Conway <mail@joeconway.com> writes:
> OK - this patch is a bit larger -- followed your advise, and moved
> internal declarations from dblink.h to dblink.c while I was at it.
> Please apply if there are no more objections.

Done.

            regards, tom lane

Re: small dblink patch

From
Joe Conway
Date:
Tom Lane wrote:
 > This isn't going to fix the problem --- all the functions are still
 > declared to take type NAME, which will not be long enough for
 > qualified names.  You need to replace the use of NAME with use of
 > TEXT.

 > I don't particularly care for that answer.  Would instead suggest you
 > borrow the coding now being used in sequence.c and other places where
 > text arguments are interpreted as relation names:

OK - this patch is a bit larger -- followed your advise, and moved
internal declarations from dblink.h to dblink.c while I was at it.

Please apply if there are no more objections.

Thanks,

Joe


Index: contrib/dblink//README.dblink
===================================================================
RCS file: /opt/src/cvs/pgsql/contrib/dblink/README.dblink,v
retrieving revision 1.4
diff -c -r1.4 README.dblink
*** contrib/dblink//README.dblink    24 Apr 2002 02:28:28 -0000    1.4
--- contrib/dblink//README.dblink    27 May 2002 18:56:04 -0000
***************
*** 65,81 ****
         - extracts and returns individual field results
       dblink_strtok(text,text,int) RETURNS text
         - extracts and returns individual token from delimited text
!      dblink_get_pkey(name) RETURNS setof text
         - returns the field names of a relation's primary key fields
       dblink_last_oid(int) RETURNS oid
         - returns the last inserted oid
!      dblink_build_sql_insert(name,int2vector,int2,_text,_text) RETURNS text
         - builds an insert statement using a local tuple, replacing the
           selection key field values with alternate supplied values
!      dblink_build_sql_delete(name,int2vector,int2,_text) RETURNS text
         - builds a delete statement using supplied values for selection
           key field values
!      dblink_build_sql_update(name,int2vector,int2,_text,_text) RETURNS text
         - builds an update statement using a local tuple, replacing the
           selection key field values with alternate supplied values
       dblink_current_query() RETURNS text
--- 65,81 ----
         - extracts and returns individual field results
       dblink_strtok(text,text,int) RETURNS text
         - extracts and returns individual token from delimited text
!      dblink_get_pkey(text) RETURNS setof text
         - returns the field names of a relation's primary key fields
       dblink_last_oid(int) RETURNS oid
         - returns the last inserted oid
!      dblink_build_sql_insert(text,int2vector,int2,_text,_text) RETURNS text
         - builds an insert statement using a local tuple, replacing the
           selection key field values with alternate supplied values
!      dblink_build_sql_delete(text,int2vector,int2,_text) RETURNS text
         - builds a delete statement using supplied values for selection
           key field values
!      dblink_build_sql_update(text,int2vector,int2,_text,_text) RETURNS text
         - builds an update statement using a local tuple, replacing the
           selection key field values with alternate supplied values
       dblink_current_query() RETURNS text
***************
*** 206,212 ****

  Synopsis

! dblink_get_pkey(name relname) RETURNS setof text

  Inputs

--- 206,212 ----

  Synopsis

! dblink_get_pkey(text relname) RETURNS setof text

  Inputs

***************
*** 278,293 ****

  Synopsis

! dblink_build_sql_insert(name relname
                           ,int2vector primary_key_attnums
                           ,int2 num_primary_key_atts
                           ,_text src_pk_att_vals_array
                           ,_text tgt_pk_att_vals_array) RETURNS text
! dblink_build_sql_delete(name relname
                           ,int2vector primary_key_attnums
                           ,int2 num_primary_key_atts
                           ,_text tgt_pk_att_vals_array) RETURNS text
! dblink_build_sql_update(name relname
                           ,int2vector primary_key_attnums
                           ,int2 num_primary_key_atts
                           ,_text src_pk_att_vals_array
--- 278,293 ----

  Synopsis

! dblink_build_sql_insert(text relname
                           ,int2vector primary_key_attnums
                           ,int2 num_primary_key_atts
                           ,_text src_pk_att_vals_array
                           ,_text tgt_pk_att_vals_array) RETURNS text
! dblink_build_sql_delete(text relname
                           ,int2vector primary_key_attnums
                           ,int2 num_primary_key_atts
                           ,_text tgt_pk_att_vals_array) RETURNS text
! dblink_build_sql_update(text relname
                           ,int2vector primary_key_attnums
                           ,int2 num_primary_key_atts
                           ,_text src_pk_att_vals_array
Index: contrib/dblink//dblink.c
===================================================================
RCS file: /opt/src/cvs/pgsql/contrib/dblink/dblink.c,v
retrieving revision 1.6
diff -c -r1.6 dblink.c
*** contrib/dblink//dblink.c    20 May 2002 23:51:40 -0000    1.6
--- contrib/dblink//dblink.c    27 May 2002 21:19:44 -0000
***************
*** 27,32 ****
--- 27,52 ----

  #include "dblink.h"

+
+ /*
+  * Internal declarations
+  */
+ static dblink_results *init_dblink_results(MemoryContext fn_mcxt);
+ static dblink_array_results *init_dblink_array_results(MemoryContext fn_mcxt);
+ static char **get_pkey_attnames(Oid relid, int16 *numatts);
+ static char *get_strtok(char *fldtext, char *fldsep, int fldnum);
+ static char *get_sql_insert(Oid relid, int16 *pkattnums, int16 pknumatts, char **src_pkattvals, char
**tgt_pkattvals);
+ static char *get_sql_delete(Oid relid, int16 *pkattnums, int16 pknumatts, char **tgt_pkattvals);
+ static char *get_sql_update(Oid relid, int16 *pkattnums, int16 pknumatts, char **src_pkattvals, char
**tgt_pkattvals);
+ static char *quote_literal_cstr(char *rawstr);
+ static char *quote_ident_cstr(char *rawstr);
+ static int16 get_attnum_pk_pos(int16 *pkattnums, int16 pknumatts, int16 key);
+ static HeapTuple get_tuple_of_interest(Oid relid, int16 *pkattnums, int16 pknumatts, char **src_pkattvals);
+ static Oid get_relid_from_relname(text *relname_text);
+ static dblink_results    *get_res_ptr(int32 res_id_index);
+ static void append_res_ptr(dblink_results *results);
+ static void remove_res_ptr(dblink_results *results);
+
  /* Global */
  List    *res_id = NIL;
  int        res_id_index = 0;
***************
*** 281,287 ****
  Datum
  dblink_get_pkey(PG_FUNCTION_ARGS)
  {
!     char                    *relname;
      Oid                        relid;
      char                    **result;
      text                    *result_text;
--- 301,307 ----
  Datum
  dblink_get_pkey(PG_FUNCTION_ARGS)
  {
!     text                    *relname_text;
      Oid                        relid;
      char                    **result;
      text                    *result_text;
***************
*** 294,308 ****

      if (fcinfo->flinfo->fn_extra == NULL)
      {
!         relname = NameStr(*PG_GETARG_NAME(0));

          /*
           * Convert relname to rel OID.
           */
!         relid = get_relid_from_relname(relname);
          if (!OidIsValid(relid))
!             elog(ERROR, "dblink_get_pkey: relation \"%s\" does not exist",
!                  relname);

          /*
           * get an array of attnums.
--- 314,327 ----

      if (fcinfo->flinfo->fn_extra == NULL)
      {
!         relname_text = PG_GETARG_TEXT_P(0);

          /*
           * Convert relname to rel OID.
           */
!         relid = get_relid_from_relname(relname_text);
          if (!OidIsValid(relid))
!             elog(ERROR, "dblink_get_pkey: relation does not exist");

          /*
           * get an array of attnums.
***************
*** 428,434 ****
  dblink_build_sql_insert(PG_FUNCTION_ARGS)
  {
      Oid            relid;
!     char        *relname;
      int16        *pkattnums;
      int16        pknumatts;
      char        **src_pkattvals;
--- 447,453 ----
  dblink_build_sql_insert(PG_FUNCTION_ARGS)
  {
      Oid            relid;
!     text        *relname_text;
      int16        *pkattnums;
      int16        pknumatts;
      char        **src_pkattvals;
***************
*** 446,460 ****
      char        *sql;
      text        *sql_text;

!     relname = NameStr(*PG_GETARG_NAME(0));

      /*
       * Convert relname to rel OID.
       */
!     relid = get_relid_from_relname(relname);
      if (!OidIsValid(relid))
!         elog(ERROR, "dblink_get_pkey: relation \"%s\" does not exist",
!              relname);

      pkattnums = (int16 *) PG_GETARG_POINTER(1);
      pknumatts = PG_GETARG_INT16(2);
--- 465,478 ----
      char        *sql;
      text        *sql_text;

!     relname_text = PG_GETARG_TEXT_P(0);

      /*
       * Convert relname to rel OID.
       */
!     relid = get_relid_from_relname(relname_text);
      if (!OidIsValid(relid))
!         elog(ERROR, "dblink_build_sql_insert: relation does not exist");

      pkattnums = (int16 *) PG_GETARG_POINTER(1);
      pknumatts = PG_GETARG_INT16(2);
***************
*** 554,560 ****
  dblink_build_sql_delete(PG_FUNCTION_ARGS)
  {
      Oid            relid;
!     char        *relname;
      int16        *pkattnums;
      int16        pknumatts;
      char        **tgt_pkattvals;
--- 572,578 ----
  dblink_build_sql_delete(PG_FUNCTION_ARGS)
  {
      Oid            relid;
!     text        *relname_text;
      int16        *pkattnums;
      int16        pknumatts;
      char        **tgt_pkattvals;
***************
*** 567,581 ****
      char        *sql;
      text        *sql_text;

!     relname = NameStr(*PG_GETARG_NAME(0));

      /*
       * Convert relname to rel OID.
       */
!     relid = get_relid_from_relname(relname);
      if (!OidIsValid(relid))
!         elog(ERROR, "dblink_get_pkey: relation \"%s\" does not exist",
!              relname);

      pkattnums = (int16 *) PG_GETARG_POINTER(1);
      pknumatts = PG_GETARG_INT16(2);
--- 585,598 ----
      char        *sql;
      text        *sql_text;

!     relname_text = PG_GETARG_TEXT_P(0);

      /*
       * Convert relname to rel OID.
       */
!     relid = get_relid_from_relname(relname_text);
      if (!OidIsValid(relid))
!         elog(ERROR, "dblink_build_sql_delete: relation does not exist");

      pkattnums = (int16 *) PG_GETARG_POINTER(1);
      pknumatts = PG_GETARG_INT16(2);
***************
*** 653,659 ****
  dblink_build_sql_update(PG_FUNCTION_ARGS)
  {
      Oid            relid;
!     char        *relname;
      int16        *pkattnums;
      int16        pknumatts;
      char        **src_pkattvals;
--- 670,676 ----
  dblink_build_sql_update(PG_FUNCTION_ARGS)
  {
      Oid            relid;
!     text        *relname_text;
      int16        *pkattnums;
      int16        pknumatts;
      char        **src_pkattvals;
***************
*** 671,685 ****
      char        *sql;
      text        *sql_text;

!     relname = NameStr(*PG_GETARG_NAME(0));

      /*
       * Convert relname to rel OID.
       */
!     relid = get_relid_from_relname(relname);
      if (!OidIsValid(relid))
!         elog(ERROR, "dblink_get_pkey: relation \"%s\" does not exist",
!              relname);

      pkattnums = (int16 *) PG_GETARG_POINTER(1);
      pknumatts = PG_GETARG_INT16(2);
--- 688,701 ----
      char        *sql;
      text        *sql_text;

!     relname_text = PG_GETARG_TEXT_P(0);

      /*
       * Convert relname to rel OID.
       */
!     relid = get_relid_from_relname(relname_text);
      if (!OidIsValid(relid))
!         elog(ERROR, "dblink_build_sql_update: relation does not exist");

      pkattnums = (int16 *) PG_GETARG_POINTER(1);
      pknumatts = PG_GETARG_INT16(2);
***************
*** 841,847 ****
   * init_dblink_results
   *     - create an empty dblink_results data structure
   */
! dblink_results *
  init_dblink_results(MemoryContext fn_mcxt)
  {
      MemoryContext oldcontext;
--- 857,863 ----
   * init_dblink_results
   *     - create an empty dblink_results data structure
   */
! static dblink_results *
  init_dblink_results(MemoryContext fn_mcxt)
  {
      MemoryContext oldcontext;
***************
*** 866,872 ****
   * init_dblink_array_results
   *     - create an empty dblink_array_results data structure
   */
! dblink_array_results *
  init_dblink_array_results(MemoryContext fn_mcxt)
  {
      MemoryContext oldcontext;
--- 882,888 ----
   * init_dblink_array_results
   *     - create an empty dblink_array_results data structure
   */
! static dblink_array_results *
  init_dblink_array_results(MemoryContext fn_mcxt)
  {
      MemoryContext oldcontext;
***************
*** 892,898 ****
   * Get the primary key attnames for the given relation.
   * Return NULL, and set numatts = 0, if no primary key exists.
   */
! char **
  get_pkey_attnames(Oid relid, int16 *numatts)
  {
      Relation        indexRelation;
--- 908,914 ----
   * Get the primary key attnames for the given relation.
   * Return NULL, and set numatts = 0, if no primary key exists.
   */
! static char **
  get_pkey_attnames(Oid relid, int16 *numatts)
  {
      Relation        indexRelation;
***************
*** 961,967 ****
   * return ord item (0 based)
   * based on provided field separator
   */
! char *
  get_strtok(char *fldtext, char *fldsep, int fldnum)
  {
      int            j = 0;
--- 977,983 ----
   * return ord item (0 based)
   * based on provided field separator
   */
! static char *
  get_strtok(char *fldtext, char *fldsep, int fldnum)
  {
      int            j = 0;
***************
*** 988,994 ****
      return pstrdup(result);
  }

! char *
  get_sql_insert(Oid relid, int16 *pkattnums, int16 pknumatts, char **src_pkattvals, char **tgt_pkattvals)
  {
      Relation        rel;
--- 1004,1010 ----
      return pstrdup(result);
  }

! static char *
  get_sql_insert(Oid relid, int16 *pkattnums, int16 pknumatts, char **src_pkattvals, char **tgt_pkattvals)
  {
      Relation        rel;
***************
*** 1059,1065 ****
      return (sql);
  }

! char *
  get_sql_delete(Oid relid, int16 *pkattnums, int16 pknumatts, char **tgt_pkattvals)
  {
      Relation        rel;
--- 1075,1081 ----
      return (sql);
  }

! static char *
  get_sql_delete(Oid relid, int16 *pkattnums, int16 pknumatts, char **tgt_pkattvals)
  {
      Relation        rel;
***************
*** 1112,1118 ****
      return (sql);
  }

! char *
  get_sql_update(Oid relid, int16 *pkattnums, int16 pknumatts, char **src_pkattvals, char **tgt_pkattvals)
  {
      Relation        rel;
--- 1128,1134 ----
      return (sql);
  }

! static char *
  get_sql_update(Oid relid, int16 *pkattnums, int16 pknumatts, char **src_pkattvals, char **tgt_pkattvals)
  {
      Relation        rel;
***************
*** 1235,1241 ****
      return result;
  }

! int16
  get_attnum_pk_pos(int16 *pkattnums, int16 pknumatts, int16 key)
  {
      int        i;
--- 1251,1257 ----
      return result;
  }

! static int16
  get_attnum_pk_pos(int16 *pkattnums, int16 pknumatts, int16 key)
  {
      int        i;
***************
*** 1251,1257 ****
      return -1;
  }

! HeapTuple
  get_tuple_of_interest(Oid relid, int16 *pkattnums, int16 pknumatts, char **src_pkattvals)
  {
      Relation        rel;
--- 1267,1273 ----
      return -1;
  }

! static HeapTuple
  get_tuple_of_interest(Oid relid, int16 *pkattnums, int16 pknumatts, char **src_pkattvals)
  {
      Relation        rel;
***************
*** 1340,1356 ****
      return NULL;
  }

! Oid
! get_relid_from_relname(char *relname)
  {
  #ifdef NamespaceRelationName
!     Oid                relid;

!     relid = RelnameGetRelid(relname);
  #else
!     Relation        rel;
!     Oid                relid;

      rel = relation_openr(relname, AccessShareLock);
      relid = RelationGetRelid(rel);
      relation_close(rel, AccessShareLock);
--- 1356,1379 ----
      return NULL;
  }

! static Oid
! get_relid_from_relname(text *relname_text)
  {
  #ifdef NamespaceRelationName
!     RangeVar   *relvar;
!     Relation    rel;
!     Oid            relid;

!     relvar = makeRangeVarFromNameList(textToQualifiedNameList(relname_text, "get_relid_from_relname"));
!     rel = heap_openrv(relvar, AccessShareLock);
!     relid = RelationGetRelid(rel);
!     relation_close(rel, AccessShareLock);
  #else
!     char       *relname;
!     Relation    rel;
!     Oid            relid;

+     relname = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(relname_text)));
      rel = relation_openr(relname, AccessShareLock);
      relid = RelationGetRelid(rel);
      relation_close(rel, AccessShareLock);
***************
*** 1359,1365 ****
      return relid;
  }

! dblink_results    *
  get_res_ptr(int32 res_id_index)
  {
      List    *ptr;
--- 1382,1388 ----
      return relid;
  }

! static dblink_results    *
  get_res_ptr(int32 res_id_index)
  {
      List    *ptr;
***************
*** 1385,1391 ****
  /*
   * Add node to global List res_id
   */
! void
  append_res_ptr(dblink_results *results)
  {
      res_id = lappend(res_id, results);
--- 1408,1414 ----
  /*
   * Add node to global List res_id
   */
! static void
  append_res_ptr(dblink_results *results)
  {
      res_id = lappend(res_id, results);
***************
*** 1395,1401 ****
   * Remove node from global List
   * using res_id_index
   */
! void
  remove_res_ptr(dblink_results *results)
  {
      res_id = lremove(results, res_id);
--- 1418,1424 ----
   * Remove node from global List
   * using res_id_index
   */
! static void
  remove_res_ptr(dblink_results *results)
  {
      res_id = lremove(results, res_id);
***************
*** 1403,1407 ****
      if (res_id == NIL)
          res_id_index = 0;
  }
-

--- 1426,1429 ----
Index: contrib/dblink//dblink.h
===================================================================
RCS file: /opt/src/cvs/pgsql/contrib/dblink/dblink.h,v
retrieving revision 1.5
diff -c -r1.5 dblink.h
*** contrib/dblink//dblink.h    24 Apr 2002 02:28:28 -0000    1.5
--- contrib/dblink//dblink.h    27 May 2002 18:39:31 -0000
***************
*** 120,145 ****
  extern Datum dblink_current_query(PG_FUNCTION_ARGS);
  extern Datum dblink_replace_text(PG_FUNCTION_ARGS);

- /*
-  * Internal declarations
-  */
- dblink_results *init_dblink_results(MemoryContext fn_mcxt);
- dblink_array_results *init_dblink_array_results(MemoryContext fn_mcxt);
- char **get_pkey_attnames(Oid relid, int16 *numatts);
- char *get_strtok(char *fldtext, char *fldsep, int fldnum);
- char *getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber);
- char *get_sql_insert(Oid relid, int16 *pkattnums, int16 pknumatts, char **src_pkattvals, char **tgt_pkattvals);
- char *get_sql_delete(Oid relid, int16 *pkattnums, int16 pknumatts, char **tgt_pkattvals);
- char *get_sql_update(Oid relid, int16 *pkattnums, int16 pknumatts, char **src_pkattvals, char **tgt_pkattvals);
- static char *quote_literal_cstr(char *rawstr);
- static char *quote_ident_cstr(char *rawstr);
- int16 get_attnum_pk_pos(int16 *pkattnums, int16 pknumatts, int16 key);
- HeapTuple get_tuple_of_interest(Oid relid, int16 *pkattnums, int16 pknumatts, char **src_pkattvals);
- Oid get_relid_from_relname(char *relname);
- dblink_results    *get_res_ptr(int32 res_id_index);
- void append_res_ptr(dblink_results *results);
- void remove_res_ptr(dblink_results *results);
-
  extern char    *debug_query_string;

  #endif   /* DBLINK_H */
--- 120,125 ----
Index: contrib/dblink//dblink.sql.in
===================================================================
RCS file: /opt/src/cvs/pgsql/contrib/dblink/dblink.sql.in,v
retrieving revision 1.2
diff -c -r1.2 dblink.sql.in
*** contrib/dblink//dblink.sql.in    24 Apr 2002 02:28:28 -0000    1.2
--- contrib/dblink//dblink.sql.in    27 May 2002 17:53:43 -0000
***************
*** 10,16 ****
    AS 'MODULE_PATHNAME','dblink_strtok' LANGUAGE 'c'
    WITH (iscachable, isstrict);

! CREATE OR REPLACE FUNCTION dblink_get_pkey (name) RETURNS setof text
    AS 'MODULE_PATHNAME','dblink_get_pkey' LANGUAGE 'c'
    WITH (isstrict);

--- 10,16 ----
    AS 'MODULE_PATHNAME','dblink_strtok' LANGUAGE 'c'
    WITH (iscachable, isstrict);

! CREATE OR REPLACE FUNCTION dblink_get_pkey (text) RETURNS setof text
    AS 'MODULE_PATHNAME','dblink_get_pkey' LANGUAGE 'c'
    WITH (isstrict);

***************
*** 18,32 ****
    AS 'MODULE_PATHNAME','dblink_last_oid' LANGUAGE 'c'
    WITH (isstrict);

! CREATE OR REPLACE FUNCTION dblink_build_sql_insert (name, int2vector, int2, _text, _text) RETURNS text
    AS 'MODULE_PATHNAME','dblink_build_sql_insert' LANGUAGE 'c'
    WITH (isstrict);

! CREATE OR REPLACE FUNCTION dblink_build_sql_delete (name, int2vector, int2, _text) RETURNS text
    AS 'MODULE_PATHNAME','dblink_build_sql_delete' LANGUAGE 'c'
    WITH (isstrict);

! CREATE OR REPLACE FUNCTION dblink_build_sql_update (name, int2vector, int2, _text, _text) RETURNS text
    AS 'MODULE_PATHNAME','dblink_build_sql_update' LANGUAGE 'c'
    WITH (isstrict);

--- 18,32 ----
    AS 'MODULE_PATHNAME','dblink_last_oid' LANGUAGE 'c'
    WITH (isstrict);

! CREATE OR REPLACE FUNCTION dblink_build_sql_insert (text, int2vector, int2, _text, _text) RETURNS text
    AS 'MODULE_PATHNAME','dblink_build_sql_insert' LANGUAGE 'c'
    WITH (isstrict);

! CREATE OR REPLACE FUNCTION dblink_build_sql_delete (text, int2vector, int2, _text) RETURNS text
    AS 'MODULE_PATHNAME','dblink_build_sql_delete' LANGUAGE 'c'
    WITH (isstrict);

! CREATE OR REPLACE FUNCTION dblink_build_sql_update (text, int2vector, int2, _text, _text) RETURNS text
    AS 'MODULE_PATHNAME','dblink_build_sql_update' LANGUAGE 'c'
    WITH (isstrict);