Diff for /pgsql/contrib/dblink/dblink.c between versions 1.82.2.6 and 1.82.2.7

version 1.82.2.6, 2010/06/14 20:49:39 version 1.82.2.7, 2010/06/15 16:22:26
Line 8 Line 8
  * Darko Prenosil <[email protected]>   * Darko Prenosil <[email protected]>
  * Shridhar Daithankar <[email protected]>   * Shridhar Daithankar <[email protected]>
  *   *
  * $PostgreSQL: pgsql/contrib/dblink/dblink.c,v 1.82.2.5 2010/06/09 03:40:16 itagaki Exp $   * $PostgreSQL: pgsql/contrib/dblink/dblink.c,v 1.82.2.6 2010/06/14 20:49:39 tgl Exp $
  * Copyright (c) 2001-2009, PostgreSQL Global Development Group   * Copyright (c) 2001-2009, PostgreSQL Global Development Group
  * ALL RIGHTS RESERVED;   * ALL RIGHTS RESERVED;
  *   *
Line 87  static void createNewConnection(const ch Line 87  static void createNewConnection(const ch
 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_text_array_contents(ArrayType *array, int *numitems);  static char **get_text_array_contents(ArrayType *array, int *numitems);
 static char *get_sql_insert(Relation rel, int2vector *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, int2vector *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, int2vector *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(int2vector *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, int2vector *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 void dblink_connstr_check(const char *connstr);  static void dblink_connstr_check(const char *connstr);
Line 101  static void dblink_security_check(PGconn Line 101  static void dblink_security_check(PGconn
 static void dblink_res_error(const char *conname, PGresult *res, const char *dblink_context_msg, bool fail);  static void dblink_res_error(const char *conname, PGresult *res, const char *dblink_context_msg, bool fail);
 static char *get_connect_string(const char *servername);  static char *get_connect_string(const char *servername);
 static char *escape_param_str(const char *from);  static char *escape_param_str(const char *from);
 static int get_nondropped_natts(Relation rel);  static void validate_pkattnums(Relation rel,
                                      int2vector *pkattnums_arg, int32 pknumatts_arg,
                                      int **pkattnums, int *pknumatts);
   
 /* Global */  /* Global */
 static remoteConn *pconn = NULL;  static remoteConn *pconn = NULL;
Line 1355  Datum Line 1357  Datum
 dblink_build_sql_insert(PG_FUNCTION_ARGS)  dblink_build_sql_insert(PG_FUNCTION_ARGS)
 {  {
         text       *relname_text = PG_GETARG_TEXT_P(0);          text       *relname_text = PG_GETARG_TEXT_P(0);
         int2vector *pkattnums = (int2vector *) PG_GETARG_POINTER(1);          int2vector *pkattnums_arg = (int2vector *) PG_GETARG_POINTER(1);
         int32           pknumatts_tmp = PG_GETARG_INT32(2);          int32           pknumatts_arg = PG_GETARG_INT32(2);
         ArrayType  *src_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(3);          ArrayType  *src_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(3);
         ArrayType  *tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(4);          ArrayType  *tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(4);
         Relation        rel;          Relation        rel;
         int16           pknumatts = 0;          int                *pkattnums;
           int                     pknumatts;
         char      **src_pkattvals;          char      **src_pkattvals;
         char      **tgt_pkattvals;          char      **tgt_pkattvals;
         int                     src_nitems;          int                     src_nitems;
         int                     tgt_nitems;          int                     tgt_nitems;
         char       *sql;          char       *sql;
         int                     nondropped_natts;  
   
         /*          /*
          * Open target relation.           * Open target relation.
Line 1374  dblink_build_sql_insert(PG_FUNCTION_ARGS Line 1376  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);
   
         /*          /*
          * There should be at least one key attribute           * Process pkattnums argument.
          */           */
         if (pknumatts_tmp <= 0)          validate_pkattnums(rel, pkattnums_arg, pknumatts_arg,
                 ereport(ERROR,                                             &pkattnums, &pknumatts);
                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),  
                                  errmsg("number of key attributes must be > 0")));  
   
         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")));  
   
         /*  
          * 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 the           * Source array is made up of key values that will be used to locate the
Line 1465  Datum Line 1448  Datum
 dblink_build_sql_delete(PG_FUNCTION_ARGS)  dblink_build_sql_delete(PG_FUNCTION_ARGS)
 {  {
         text       *relname_text = PG_GETARG_TEXT_P(0);          text       *relname_text = PG_GETARG_TEXT_P(0);
         int2vector *pkattnums = (int2vector *) PG_GETARG_POINTER(1);          int2vector *pkattnums_arg = (int2vector *) PG_GETARG_POINTER(1);
         int32           pknumatts_tmp = PG_GETARG_INT32(2);          int32           pknumatts_arg = PG_GETARG_INT32(2);
         ArrayType  *tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(3);          ArrayType  *tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(3);
         int                     nondropped_natts;  
         Relation        rel;          Relation        rel;
         int16           pknumatts = 0;          int                *pkattnums;
           int                     pknumatts;
         char      **tgt_pkattvals;          char      **tgt_pkattvals;
         int                     tgt_nitems;          int                     tgt_nitems;
         char       *sql;          char       *sql;
Line 1481  dblink_build_sql_delete(PG_FUNCTION_ARGS Line 1464  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);
   
         /*          /*
          * There should be at least one key attribute           * Process pkattnums argument.
          */           */
         if (pknumatts_tmp <= 0)          validate_pkattnums(rel, pkattnums_arg, pknumatts_arg,
                 ereport(ERROR,                                             &pkattnums, &pknumatts);
                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),  
                                  errmsg("number of key attributes must be > 0")));  
   
         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")));  
   
         /*  
          * 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 the           * Target array is made up of key values that will be used to build the
Line 1561  Datum Line 1525  Datum
 dblink_build_sql_update(PG_FUNCTION_ARGS)  dblink_build_sql_update(PG_FUNCTION_ARGS)
 {  {
         text       *relname_text = PG_GETARG_TEXT_P(0);          text       *relname_text = PG_GETARG_TEXT_P(0);
         int2vector *pkattnums = (int2vector *) PG_GETARG_POINTER(1);          int2vector *pkattnums_arg = (int2vector *) PG_GETARG_POINTER(1);
         int32           pknumatts_tmp = PG_GETARG_INT32(2);          int32           pknumatts_arg = PG_GETARG_INT32(2);
         ArrayType  *src_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(3);          ArrayType  *src_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(3);
         ArrayType  *tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(4);          ArrayType  *tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(4);
         int                     nondropped_natts;  
         Relation        rel;          Relation        rel;
         int16           pknumatts = 0;          int                *pkattnums;
           int                     pknumatts;
         char      **src_pkattvals;          char      **src_pkattvals;
         char      **tgt_pkattvals;          char      **tgt_pkattvals;
         int                     src_nitems;          int                     src_nitems;
Line 1580  dblink_build_sql_update(PG_FUNCTION_ARGS Line 1544  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);
   
         /*          /*
          * There should be one source array key values for each key attnum           * Process pkattnums argument.
          */  
         if (pknumatts_tmp <= 0)  
                 ereport(ERROR,  
                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),  
                                  errmsg("number of key attributes must be > 0")));  
   
         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")));  
   
         /*  
          * ensure we don't ask for more pk attributes than we have  
          * non-dropped columns  
          */           */
         nondropped_natts = get_nondropped_natts(rel);          validate_pkattnums(rel, pkattnums_arg, pknumatts_arg,
         if (pknumatts > nondropped_natts)                                             &pkattnums, &pknumatts);
                 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 the           * Source array is made up of key values that will be used to locate the
Line 1787  get_text_array_contents(ArrayType *array Line 1732  get_text_array_contents(ArrayType *array
 }  }
   
 static char *  static char *
 get_sql_insert(Relation rel, int2vector *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 1795  get_sql_insert(Relation rel, int2vector Line 1740  get_sql_insert(Relation rel, int2vector
         int                     natts;          int                     natts;
         StringInfoData buf;          StringInfoData buf;
         char       *val;          char       *val;
         int16           key;          int                     key;
         int                     i;          int                     i;
         bool            needComma;          bool            needComma;
   
Line 1844  get_sql_insert(Relation rel, int2vector Line 1789  get_sql_insert(Relation rel, int2vector
                         appendStringInfo(&buf, ",");                          appendStringInfo(&buf, ",");
   
                 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 1868  get_sql_insert(Relation rel, int2vector Line 1813  get_sql_insert(Relation rel, int2vector
 }  }
   
 static char *  static char *
 get_sql_delete(Relation rel, int2vector *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;
         int                     natts;  
         StringInfoData buf;          StringInfoData buf;
         int                     i;          int                     i;
   
Line 1882  get_sql_delete(Relation rel, int2vector Line 1826  get_sql_delete(Relation rel, int2vector
         relname = generate_relation_name(rel);          relname = generate_relation_name(rel);
   
         tupdesc = rel->rd_att;          tupdesc = rel->rd_att;
         natts = tupdesc->natts;  
   
         appendStringInfo(&buf, "DELETE FROM %s WHERE ", relname);          appendStringInfo(&buf, "DELETE FROM %s WHERE ", relname);
         for (i = 0; i < pknumatts; i++)          for (i = 0; i < pknumatts; i++)
         {          {
                 int16           pkattnum = pkattnums->values[i];                  int                     pkattnum = pkattnums[i];
   
                 if (i > 0)                  if (i > 0)
                         appendStringInfo(&buf, " AND ");                          appendStringInfo(&buf, " AND ");
   
                 appendStringInfoString(&buf,                  appendStringInfoString(&buf,
                    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)
                         /* internal error */                          /* internal error */
Line 1910  get_sql_delete(Relation rel, int2vector Line 1853  get_sql_delete(Relation rel, int2vector
 }  }
   
 static char *  static char *
 get_sql_update(Relation rel, int2vector *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 1918  get_sql_update(Relation rel, int2vector Line 1861  get_sql_update(Relation rel, int2vector
         int                     natts;          int                     natts;
         StringInfoData buf;          StringInfoData buf;
         char       *val;          char       *val;
         int16           key;          int                     key;
         int                     i;          int                     i;
         bool            needComma;          bool            needComma;
   
Line 1951  get_sql_update(Relation rel, int2vector Line 1894  get_sql_update(Relation rel, int2vector
                                           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 1974  get_sql_update(Relation rel, int2vector Line 1917  get_sql_update(Relation rel, int2vector
   
         for (i = 0; i < pknumatts; i++)          for (i = 0; i < pknumatts; i++)
         {          {
                 int16           pkattnum = pkattnums->values[i];                  int                     pkattnum = pkattnums[i];
   
                 if (i > 0)                  if (i > 0)
                         appendStringInfo(&buf, " AND ");                          appendStringInfo(&buf, " AND ");
   
                 appendStringInfo(&buf, "%s",                  appendStringInfo(&buf, "%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 = tgt_pkattvals[i] ? pstrdup(tgt_pkattvals[i]) : NULL;                          val = tgt_pkattvals[i] ? pstrdup(tgt_pkattvals[i]) : NULL;
                 else                  else
                         val = SPI_getvalue(tuple, tupdesc, pkattnum);                          val = SPI_getvalue(tuple, tupdesc, pkattnum + 1);
   
                 if (val != NULL)                  if (val != NULL)
                 {                  {
Line 2037  quote_ident_cstr(char *rawstr) Line 1980  quote_ident_cstr(char *rawstr)
         return result;          return result;
 }  }
   
 static int16  static int
 get_attnum_pk_pos(int2vector *pkattnums, int16 pknumatts, int16 key)  get_attnum_pk_pos(int *pkattnums, int pknumatts, int key)
 {  {
         int                     i;          int                     i;
   
Line 2046  get_attnum_pk_pos(int2vector *pkattnums, Line 1989  get_attnum_pk_pos(int2vector *pkattnums,
          * Not likely a long list anyway, so just scan for the value           * Not likely a long list anyway, so just scan for the value
          */           */
         for (i = 0; i < pknumatts; i++)          for (i = 0; i < pknumatts; i++)
                 if (key == pkattnums->values[i])                  if (key == pkattnums[i])
                         return i;                          return i;
   
         return -1;          return -1;
 }  }
   
 static HeapTuple  static HeapTuple
 get_tuple_of_interest(Relation rel, int2vector *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 2084  get_tuple_of_interest(Relation rel, int2 Line 2027  get_tuple_of_interest(Relation rel, int2
   
         for (i = 0; i < pknumatts; i++)          for (i = 0; i < pknumatts; i++)
         {          {
                 int16           pkattnum = pkattnums->values[i];                  int                     pkattnum = pkattnums[i];
   
                 if (i > 0)                  if (i > 0)
                         appendStringInfo(&buf, " AND ");                          appendStringInfo(&buf, " AND ");
   
                 appendStringInfoString(&buf,                  appendStringInfoString(&buf,
                    quote_ident_cstr(NameStr(tupdesc->attrs[pkattnum - 1]->attname)));                     quote_ident_cstr(NameStr(tupdesc->attrs[pkattnum]->attname)));
   
                 if (src_pkattvals[i] != NULL)                  if (src_pkattvals[i] != NULL)
                         appendStringInfo(&buf, " = %s",                          appendStringInfo(&buf, " = %s",
Line 2464  escape_param_str(const char *str) Line 2407  escape_param_str(const char *str)
         return buf->data;          return buf->data;
 }  }
   
 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,
                                      int2vector *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;          /* Don't take more array elements than there are */
         natts = tupdesc->natts;          pknumatts_arg = Min(pknumatts_arg, pkattnums_arg->dim1);
   
         for (i = 0; i < natts; i++)          /* Must have at least one pk attnum selected */
           if (pknumatts_arg <= 0)
                   ereport(ERROR,
                                   (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                    errmsg("number of key attributes must be > 0")));
   
           /* 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->values[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.82.2.6  
changed lines
  Added in v.1.82.2.7


PostgreSQL CVSweb <[email protected]>