Diff for /pgsql/contrib/dblink/dblink.c between versions 1.38.4.8 and 1.38.4.9

version 1.38.4.8, 2010/06/14 20:50:04 version 1.38.4.9, 2010/06/15 16:22:51
Line 77  static HTAB *createConnHash(void); Line 77  static HTAB *createConnHash(void);
 static void createNewConnection(const char *name, remoteConn * con);  static void createNewConnection(const char *name, remoteConn * con);
 static void deleteConnection(const char *name);  static void deleteConnection(const char *name);
 static char **get_pkey_attnames(Relation rel, int16 *numatts);  static char **get_pkey_attnames(Relation rel, int16 *numatts);
 static char *get_sql_insert(Relation rel, int16 *pkattnums, int16 pknumatts, char **src_pkattvals, char **tgt_pkattvals);  static char *get_sql_insert(Relation rel, int *pkattnums, int pknumatts, char **src_pkattvals, char **tgt_pkattvals);
 static char *get_sql_delete(Relation rel, int16 *pkattnums, int16 pknumatts, char **tgt_pkattvals);  static char *get_sql_delete(Relation rel, int *pkattnums, int pknumatts, char **tgt_pkattvals);
 static char *get_sql_update(Relation rel, int16 *pkattnums, int16 pknumatts, char **src_pkattvals, char **tgt_pkattvals);  static char *get_sql_update(Relation rel, int *pkattnums, int pknumatts, char **src_pkattvals, char **tgt_pkattvals);
 static char *quote_literal_cstr(char *rawstr);  static char *quote_literal_cstr(char *rawstr);
 static char *quote_ident_cstr(char *rawstr);  static char *quote_ident_cstr(char *rawstr);
 static int16 get_attnum_pk_pos(int16 *pkattnums, int16 pknumatts, int16 key);  static int      get_attnum_pk_pos(int *pkattnums, int pknumatts, int key);
 static HeapTuple get_tuple_of_interest(Relation rel, int16 *pkattnums, int16 pknumatts, char **src_pkattvals);  static HeapTuple get_tuple_of_interest(Relation rel, int *pkattnums, int pknumatts, char **src_pkattvals);
 static Relation get_rel_from_relname(text *relname_text, LOCKMODE lockmode, AclMode aclmode);  static Relation get_rel_from_relname(text *relname_text, LOCKMODE lockmode, AclMode aclmode);
 static char *generate_relation_name(Relation rel);  static char *generate_relation_name(Relation rel);
 static char *connstr_strip_password(const char *connstr);  static char *connstr_strip_password(const char *connstr);
 static void dblink_security_check(PGconn *conn, remoteConn *rcon, const char *connstr);  static void dblink_security_check(PGconn *conn, remoteConn *rcon, const char *connstr);
 static int get_nondropped_natts(Relation rel);  static void validate_pkattnums(Relation rel,
                                      int16 *pkattnums_arg, int32 pknumatts_arg,
                                      int **pkattnums, int *pknumatts);
   
 /* Global */  /* Global */
 List       *res_id = NIL;  List       *res_id = NIL;
Line 1087  dblink_get_pkey(PG_FUNCTION_ARGS) Line 1089  dblink_get_pkey(PG_FUNCTION_ARGS)
 }  }
   
   
 #ifndef SHRT_MAX  
 #define SHRT_MAX (0x7FFF)  
 #endif  
 /*  /*
  * dblink_build_sql_insert   * dblink_build_sql_insert
  *   *
Line 1115  dblink_build_sql_insert(PG_FUNCTION_ARGS Line 1114  dblink_build_sql_insert(PG_FUNCTION_ARGS
 {  {
         Relation        rel;          Relation        rel;
         text       *relname_text;          text       *relname_text;
         int16      *pkattnums;          int16      *pkattnums_arg;
         int                     pknumatts_tmp;          int32           pknumatts_arg;
         int16           pknumatts = 0;          int                *pkattnums;
           int                     pknumatts;
         char      **src_pkattvals;          char      **src_pkattvals;
         char      **tgt_pkattvals;          char      **tgt_pkattvals;
         ArrayType  *src_pkattvals_arry;          ArrayType  *src_pkattvals_arry;
Line 1134  dblink_build_sql_insert(PG_FUNCTION_ARGS Line 1134  dblink_build_sql_insert(PG_FUNCTION_ARGS
         int16           typlen;          int16           typlen;
         bool            typbyval;          bool            typbyval;
         char            typalign;          char            typalign;
         int                     nondropped_natts;  
   
         relname_text = PG_GETARG_TEXT_P(0);          relname_text = PG_GETARG_TEXT_P(0);
   
Line 1143  dblink_build_sql_insert(PG_FUNCTION_ARGS Line 1142  dblink_build_sql_insert(PG_FUNCTION_ARGS
          */           */
         rel = get_rel_from_relname(relname_text, AccessShareLock, ACL_SELECT);          rel = get_rel_from_relname(relname_text, AccessShareLock, ACL_SELECT);
   
         pkattnums = (int16 *) PG_GETARG_POINTER(1);  
         pknumatts_tmp = PG_GETARG_INT32(2);  
         if (pknumatts_tmp <= SHRT_MAX)  
                 pknumatts = pknumatts_tmp;  
         else  
                 ereport(ERROR,  
                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),  
                                  errmsg("input for number of primary key " \  
                                                 "attributes too large")));  
   
         /*          /*
          * There should be at least one key attribute           * Process pkattnums argument.
          */           */
         if (pknumatts == 0)          pkattnums_arg = (int16 *) PG_GETARG_POINTER(1);
                 ereport(ERROR,          pknumatts_arg = PG_GETARG_INT32(2);
                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),          validate_pkattnums(rel, pkattnums_arg, pknumatts_arg,
                                  errmsg("number of key attributes must be > 0")));                                             &pkattnums, &pknumatts);
   
         src_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(3);          src_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(3);
         tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(4);          tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(4);
   
         /*          /*
          * ensure we don't ask for more pk attributes than we have  
          * non-dropped columns  
          */  
         nondropped_natts = get_nondropped_natts(rel);  
         if (pknumatts > nondropped_natts)  
                 ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR),  
                                 errmsg("number of primary key fields exceeds number of specified relation attributes")));  
   
         /*  
          * Source array is made up of key values that will be used to locate           * Source array is made up of key values that will be used to locate
          * the tuple of interest from the local system.           * the tuple of interest from the local system.
          */           */
Line 1277  dblink_build_sql_delete(PG_FUNCTION_ARGS Line 1257  dblink_build_sql_delete(PG_FUNCTION_ARGS
 {  {
         Relation        rel;          Relation        rel;
         text       *relname_text;          text       *relname_text;
         int16      *pkattnums;          int16      *pkattnums_arg;
         int                     pknumatts_tmp;          int32           pknumatts_arg;
         int16           pknumatts = 0;          int                *pkattnums;
           int                     pknumatts;
         char      **tgt_pkattvals;          char      **tgt_pkattvals;
         ArrayType  *tgt_pkattvals_arry;          ArrayType  *tgt_pkattvals_arry;
         int                     tgt_ndim;          int                     tgt_ndim;
Line 1291  dblink_build_sql_delete(PG_FUNCTION_ARGS Line 1272  dblink_build_sql_delete(PG_FUNCTION_ARGS
         int16           typlen;          int16           typlen;
         bool            typbyval;          bool            typbyval;
         char            typalign;          char            typalign;
         int                     nondropped_natts;  
   
         relname_text = PG_GETARG_TEXT_P(0);          relname_text = PG_GETARG_TEXT_P(0);
   
Line 1300  dblink_build_sql_delete(PG_FUNCTION_ARGS Line 1280  dblink_build_sql_delete(PG_FUNCTION_ARGS
          */           */
         rel = get_rel_from_relname(relname_text, AccessShareLock, ACL_SELECT);          rel = get_rel_from_relname(relname_text, AccessShareLock, ACL_SELECT);
   
         pkattnums = (int16 *) PG_GETARG_POINTER(1);  
         pknumatts_tmp = PG_GETARG_INT32(2);  
         if (pknumatts_tmp <= SHRT_MAX)  
                 pknumatts = pknumatts_tmp;  
         else  
                 ereport(ERROR,  
                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),  
                                  errmsg("input for number of primary key " \  
                                                 "attributes too large")));  
   
         /*          /*
          * There should be at least one key attribute           * Process pkattnums argument.
          */           */
         if (pknumatts == 0)          pkattnums_arg = (int16 *) PG_GETARG_POINTER(1);
                 ereport(ERROR,          pknumatts_arg = PG_GETARG_INT32(2);
                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),          validate_pkattnums(rel, pkattnums_arg, pknumatts_arg,
                                  errmsg("number of key attributes must be > 0")));                                             &pkattnums, &pknumatts);
   
         tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(3);          tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(3);
   
         /*          /*
          * ensure we don't ask for more pk attributes than we have  
          * non-dropped columns  
          */  
         nondropped_natts = get_nondropped_natts(rel);  
         if (pknumatts > nondropped_natts)  
                 ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR),  
                                 errmsg("number of primary key fields exceeds number of specified relation attributes")));  
   
         /*  
          * Target array is made up of key values that will be used to build           * Target array is made up of key values that will be used to build
          * the SQL string for use on the remote system.           * the SQL string for use on the remote system.
          */           */
Line 1404  dblink_build_sql_update(PG_FUNCTION_ARGS Line 1365  dblink_build_sql_update(PG_FUNCTION_ARGS
 {  {
         Relation        rel;          Relation        rel;
         text       *relname_text;          text       *relname_text;
         int16      *pkattnums;          int16      *pkattnums_arg;
         int                     pknumatts_tmp;          int32           pknumatts_arg;
         int16           pknumatts = 0;          int                *pkattnums;
           int                     pknumatts;
         char      **src_pkattvals;          char      **src_pkattvals;
         char      **tgt_pkattvals;          char      **tgt_pkattvals;
         ArrayType  *src_pkattvals_arry;          ArrayType  *src_pkattvals_arry;
Line 1423  dblink_build_sql_update(PG_FUNCTION_ARGS Line 1385  dblink_build_sql_update(PG_FUNCTION_ARGS
         int16           typlen;          int16           typlen;
         bool            typbyval;          bool            typbyval;
         char            typalign;          char            typalign;
         int                     nondropped_natts;  
   
         relname_text = PG_GETARG_TEXT_P(0);          relname_text = PG_GETARG_TEXT_P(0);
   
Line 1432  dblink_build_sql_update(PG_FUNCTION_ARGS Line 1393  dblink_build_sql_update(PG_FUNCTION_ARGS
          */           */
         rel = get_rel_from_relname(relname_text, AccessShareLock, ACL_SELECT);          rel = get_rel_from_relname(relname_text, AccessShareLock, ACL_SELECT);
   
         pkattnums = (int16 *) PG_GETARG_POINTER(1);  
         pknumatts_tmp = PG_GETARG_INT32(2);  
         if (pknumatts_tmp <= SHRT_MAX)  
                 pknumatts = pknumatts_tmp;  
         else  
                 ereport(ERROR,  
                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),  
                                  errmsg("input for number of primary key " \  
                                                 "attributes too large")));  
   
         /*          /*
          * There should be one source array key values for each key attnum           * Process pkattnums argument.
          */           */
         if (pknumatts == 0)          pkattnums_arg = (int16 *) PG_GETARG_POINTER(1);
                 ereport(ERROR,          pknumatts_arg = PG_GETARG_INT32(2);
                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),          validate_pkattnums(rel, pkattnums_arg, pknumatts_arg,
                                  errmsg("number of key attributes must be > 0")));                                             &pkattnums, &pknumatts);
   
         src_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(3);          src_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(3);
         tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(4);          tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(4);
   
         /*          /*
          * ensure we don't ask for more pk attributes than we have  
          * non-dropped columns  
          */  
         nondropped_natts = get_nondropped_natts(rel);  
         if (pknumatts > nondropped_natts)  
                 ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR),  
                                 errmsg("number of primary key fields exceeds number of specified relation attributes")));  
   
         /*  
          * Source array is made up of key values that will be used to locate           * Source array is made up of key values that will be used to locate
          * the tuple of interest from the local system.           * the tuple of interest from the local system.
          */           */
Line 1621  get_pkey_attnames(Relation rel, int16 *n Line 1563  get_pkey_attnames(Relation rel, int16 *n
 }  }
   
 static char *  static char *
 get_sql_insert(Relation rel, int16 *pkattnums, int16 pknumatts, char **src_pkattvals, char **tgt_pkattvals)  get_sql_insert(Relation rel, int *pkattnums, int pknumatts, char **src_pkattvals, char **tgt_pkattvals)
 {  {
         char       *relname;          char       *relname;
         HeapTuple       tuple;          HeapTuple       tuple;
Line 1630  get_sql_insert(Relation rel, int16 *pkat Line 1572  get_sql_insert(Relation rel, int16 *pkat
         StringInfo      str = makeStringInfo();          StringInfo      str = makeStringInfo();
         char       *sql;          char       *sql;
         char       *val;          char       *val;
         int16           key;          int                     key;
         int                     i;          int                     i;
         bool            needComma;          bool            needComma;
   
Line 1677  get_sql_insert(Relation rel, int16 *pkat Line 1619  get_sql_insert(Relation rel, int16 *pkat
                         appendStringInfo(str, ",");                          appendStringInfo(str, ",");
   
                 if (tgt_pkattvals != NULL)                  if (tgt_pkattvals != NULL)
                         key = get_attnum_pk_pos(pkattnums, pknumatts, i + 1);                          key = get_attnum_pk_pos(pkattnums, pknumatts, i);
                 else                  else
                         key = -1;                          key = -1;
   
Line 1705  get_sql_insert(Relation rel, int16 *pkat Line 1647  get_sql_insert(Relation rel, int16 *pkat
 }  }
   
 static char *  static char *
 get_sql_delete(Relation rel, int16 *pkattnums, int16 pknumatts, char **tgt_pkattvals)  get_sql_delete(Relation rel, int *pkattnums, int pknumatts, char **tgt_pkattvals)
 {  {
         char       *relname;          char       *relname;
         TupleDesc       tupdesc;          TupleDesc       tupdesc;
Line 1724  get_sql_delete(Relation rel, int16 *pkat Line 1666  get_sql_delete(Relation rel, int16 *pkat
         appendStringInfo(str, "DELETE FROM %s WHERE ", relname);          appendStringInfo(str, "DELETE FROM %s WHERE ", relname);
         for (i = 0; i < pknumatts; i++)          for (i = 0; i < pknumatts; i++)
         {          {
                 int16           pkattnum = pkattnums[i];                  int                     pkattnum = pkattnums[i];
   
                 if (i > 0)                  if (i > 0)
                         appendStringInfo(str, " AND ");                          appendStringInfo(str, " AND ");
   
                 appendStringInfo(str, "%s",                  appendStringInfo(str, "%s",
                 quote_ident_cstr(NameStr(tupdesc->attrs[pkattnum - 1]->attname)));                  quote_ident_cstr(NameStr(tupdesc->attrs[pkattnum]->attname)));
   
                 if (tgt_pkattvals != NULL)                  if (tgt_pkattvals != NULL)
                         val = pstrdup(tgt_pkattvals[i]);                          val = pstrdup(tgt_pkattvals[i]);
Line 1755  get_sql_delete(Relation rel, int16 *pkat Line 1697  get_sql_delete(Relation rel, int16 *pkat
 }  }
   
 static char *  static char *
 get_sql_update(Relation rel, int16 *pkattnums, int16 pknumatts, char **src_pkattvals, char **tgt_pkattvals)  get_sql_update(Relation rel, int *pkattnums, int pknumatts, char **src_pkattvals, char **tgt_pkattvals)
 {  {
         char       *relname;          char       *relname;
         HeapTuple       tuple;          HeapTuple       tuple;
Line 1764  get_sql_update(Relation rel, int16 *pkat Line 1706  get_sql_update(Relation rel, int16 *pkat
         StringInfo      str = makeStringInfo();          StringInfo      str = makeStringInfo();
         char       *sql;          char       *sql;
         char       *val;          char       *val;
         int16           key;          int                     key;
         int                     i;          int                     i;
         bool            needComma;          bool            needComma;
   
Line 1795  get_sql_update(Relation rel, int16 *pkat Line 1737  get_sql_update(Relation rel, int16 *pkat
                                   quote_ident_cstr(NameStr(tupdesc->attrs[i]->attname)));                                    quote_ident_cstr(NameStr(tupdesc->attrs[i]->attname)));
   
                 if (tgt_pkattvals != NULL)                  if (tgt_pkattvals != NULL)
                         key = get_attnum_pk_pos(pkattnums, pknumatts, i + 1);                          key = get_attnum_pk_pos(pkattnums, pknumatts, i);
                 else                  else
                         key = -1;                          key = -1;
   
Line 1818  get_sql_update(Relation rel, int16 *pkat Line 1760  get_sql_update(Relation rel, int16 *pkat
   
         for (i = 0; i < pknumatts; i++)          for (i = 0; i < pknumatts; i++)
         {          {
                 int16           pkattnum = pkattnums[i];                  int                     pkattnum = pkattnums[i];
   
                 if (i > 0)                  if (i > 0)
                         appendStringInfo(str, " AND ");                          appendStringInfo(str, " AND ");
   
                 appendStringInfo(str, "%s",                  appendStringInfo(str, "%s",
                 quote_ident_cstr(NameStr(tupdesc->attrs[pkattnum - 1]->attname)));                  quote_ident_cstr(NameStr(tupdesc->attrs[pkattnum]->attname)));
   
                 if (tgt_pkattvals != NULL)                  if (tgt_pkattvals != NULL)
                         val = pstrdup(tgt_pkattvals[i]);                          val = pstrdup(tgt_pkattvals[i]);
                 else                  else
                         val = SPI_getvalue(tuple, tupdesc, pkattnum);                          val = SPI_getvalue(tuple, tupdesc, pkattnum + 1);
   
                 if (val != NULL)                  if (val != NULL)
                 {                  {
Line 1883  quote_ident_cstr(char *rawstr) Line 1825  quote_ident_cstr(char *rawstr)
         return result;          return result;
 }  }
   
 static int16  static int
 get_attnum_pk_pos(int16 *pkattnums, int16 pknumatts, int16 key)  get_attnum_pk_pos(int *pkattnums, int pknumatts, int key)
 {  {
         int                     i;          int                     i;
   
Line 1899  get_attnum_pk_pos(int16 *pkattnums, int1 Line 1841  get_attnum_pk_pos(int16 *pkattnums, int1
 }  }
   
 static HeapTuple  static HeapTuple
 get_tuple_of_interest(Relation rel, int16 *pkattnums, int16 pknumatts, char **src_pkattvals)  get_tuple_of_interest(Relation rel, int *pkattnums, int pknumatts, char **src_pkattvals)
 {  {
         char       *relname;          char       *relname;
         TupleDesc       tupdesc;          TupleDesc       tupdesc;
Line 1930  get_tuple_of_interest(Relation rel, int1 Line 1872  get_tuple_of_interest(Relation rel, int1
   
         for (i = 0; i < pknumatts; i++)          for (i = 0; i < pknumatts; i++)
         {          {
                 int16           pkattnum = pkattnums[i];                  int                     pkattnum = pkattnums[i];
   
                 if (i > 0)                  if (i > 0)
                         appendStringInfo(str, " AND ");                          appendStringInfo(str, " AND ");
   
                 appendStringInfo(str, "%s",                  appendStringInfo(str, "%s",
                 quote_ident_cstr(NameStr(tupdesc->attrs[pkattnum - 1]->attname)));                  quote_ident_cstr(NameStr(tupdesc->attrs[pkattnum]->attname)));
   
                 val = pstrdup(src_pkattvals[i]);                  val = pstrdup(src_pkattvals[i]);
                 if (val != NULL)                  if (val != NULL)
Line 2281  dblink_security_check(PGconn *conn, remo Line 2223  dblink_security_check(PGconn *conn, remo
         }          }
 }  }
   
 static int  /*
 get_nondropped_natts(Relation rel)   * Validate the PK-attnums argument for dblink_build_sql_insert() and related
    * functions, and translate to the internal representation.
    *
    * The user supplies an int2vector of 1-based physical attnums, plus a count
    * argument (the need for the separate count argument is historical, but we
    * still check it).  We check that each attnum corresponds to a valid,
    * non-dropped attribute of the rel.  We do *not* prevent attnums from being
    * listed twice, though the actual use-case for such things is dubious.
    *
    * The internal representation is a palloc'd int array of 0-based physical
    * attnums.
    */
   static void
   validate_pkattnums(Relation rel,
                                      int16 *pkattnums_arg, int32 pknumatts_arg,
                                      int **pkattnums, int *pknumatts)
 {  {
         int                     nondropped_natts = 0;          TupleDesc       tupdesc = rel->rd_att;
         TupleDesc       tupdesc;          int                     natts = tupdesc->natts;
         int                     natts;  
         int                     i;          int                     i;
   
         tupdesc = rel->rd_att;          /* Must have at least one pk attnum selected */
         natts = tupdesc->natts;          if (pknumatts_arg <= 0)
                   ereport(ERROR,
                                   (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                    errmsg("number of key attributes must be > 0")));
   
         for (i = 0; i < natts; i++)          /* Allocate output array */
           *pkattnums = (int *) palloc(pknumatts_arg * sizeof(int));
           *pknumatts = pknumatts_arg;
   
           /* Validate attnums and convert to internal form */
           for (i = 0; i < pknumatts_arg; i++)
         {          {
                 if (tupdesc->attrs[i]->attisdropped)                  int             pkattnum = pkattnums_arg[i];
                         continue;  
                 nondropped_natts++;  
         }  
   
         return nondropped_natts;                  if (pkattnum <= 0 || pkattnum > natts ||
                           tupdesc->attrs[pkattnum - 1]->attisdropped)
                           ereport(ERROR,
                                           (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                            errmsg("invalid attribute number %d", pkattnum)));
                   (*pkattnums)[i] = pkattnum - 1;
           }
 }  }

Removed from v.1.38.4.8  
changed lines
  Added in v.1.38.4.9


PostgreSQL CVSweb <[email protected]>