aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Meskes <meskes@postgresql.org>2015-02-11 10:45:46 +0100
committerMichael Meskes <meskes@postgresql.org>2015-02-11 10:57:02 +0100
commit66c4ea8cb6e8d282111783326e5c9bec330bf4e2 (patch)
treef46e4871bb53f6ba381610e4ed1f58ff7cf20cf1 /src
parenta592e5883529b7a73188d1b325c30a5a4eee65e4 (diff)
downloadpostgresql-66c4ea8cb6e8d282111783326e5c9bec330bf4e2.tar.gz
postgresql-66c4ea8cb6e8d282111783326e5c9bec330bf4e2.zip
Fixed array handling in ecpg.
When ecpg was rewritten to the new protocol version not all variable types were corrected. This patch rewrites the code for these types to fix that. It also fixes the documentation to correctly tell the status of array handling.
Diffstat (limited to 'src')
-rw-r--r--src/interfaces/ecpg/ecpglib/data.c63
-rw-r--r--src/interfaces/ecpg/ecpglib/execute.c268
2 files changed, 150 insertions, 181 deletions
diff --git a/src/interfaces/ecpg/ecpglib/data.c b/src/interfaces/ecpg/ecpglib/data.c
index 28b1be758af..2d0c1180a3c 100644
--- a/src/interfaces/ecpg/ecpglib/data.c
+++ b/src/interfaces/ecpg/ecpglib/data.c
@@ -291,6 +291,7 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
date ddres;
timestamp tres;
interval *ires;
+ char *endptr, endchar;
case ECPGt_short:
case ECPGt_int:
@@ -564,10 +565,11 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
case ECPGt_decimal:
case ECPGt_numeric:
- if (isarray && *pval == '"')
- nres = PGTYPESnumeric_from_asc(pval + 1, &scan_length);
- else
- nres = PGTYPESnumeric_from_asc(pval, &scan_length);
+ for (endptr = pval; *endptr && *endptr != ',' && *endptr != '}'; endptr++);
+ endchar = *endptr;
+ *endptr = '\0';
+ nres = PGTYPESnumeric_from_asc(pval, &scan_length);
+ *endptr = endchar;
/* did we get an error? */
if (nres == NULL)
@@ -600,10 +602,7 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
}
else
{
- if (isarray && *scan_length == '"')
- scan_length++;
-
- if (garbage_left(isarray, scan_length, compat))
+ if (!isarray && garbage_left(isarray, scan_length, compat))
{
free(nres);
ecpg_raise(lineno, ECPG_NUMERIC_FORMAT,
@@ -622,10 +621,14 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
break;
case ECPGt_interval:
- if (isarray && *pval == '"')
- ires = PGTYPESinterval_from_asc(pval + 1, &scan_length);
- else
- ires = PGTYPESinterval_from_asc(pval, &scan_length);
+ if (*pval == '"')
+ pval++;
+
+ for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
+ endchar = *endptr;
+ *endptr = '\0';
+ ires = PGTYPESinterval_from_asc(pval, &scan_length);
+ *endptr = endchar;
/* did we get an error? */
if (ires == NULL)
@@ -654,10 +657,10 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
}
else
{
- if (isarray && *scan_length == '"')
+ if (*scan_length == '"')
scan_length++;
- if (garbage_left(isarray, scan_length, compat))
+ if (!isarray && garbage_left(isarray, scan_length, compat))
{
free(ires);
ecpg_raise(lineno, ECPG_INTERVAL_FORMAT,
@@ -672,10 +675,14 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
break;
case ECPGt_date:
- if (isarray && *pval == '"')
- ddres = PGTYPESdate_from_asc(pval + 1, &scan_length);
- else
- ddres = PGTYPESdate_from_asc(pval, &scan_length);
+ if (*pval == '"')
+ pval++;
+
+ for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
+ endchar = *endptr;
+ *endptr = '\0';
+ ddres = PGTYPESdate_from_asc(pval, &scan_length);
+ *endptr = endchar;
/* did we get an error? */
if (errno != 0)
@@ -700,10 +707,10 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
}
else
{
- if (isarray && *scan_length == '"')
+ if (*scan_length == '"')
scan_length++;
- if (garbage_left(isarray, scan_length, compat))
+ if (!isarray && garbage_left(isarray, scan_length, compat))
{
ecpg_raise(lineno, ECPG_DATE_FORMAT,
ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
@@ -716,10 +723,14 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
break;
case ECPGt_timestamp:
- if (isarray && *pval == '"')
- tres = PGTYPEStimestamp_from_asc(pval + 1, &scan_length);
- else
- tres = PGTYPEStimestamp_from_asc(pval, &scan_length);
+ if (*pval == '"')
+ pval++;
+
+ for (endptr = pval; *endptr && *endptr != ',' && *endptr != '"' && *endptr != '}'; endptr++);
+ endchar = *endptr;
+ *endptr = '\0';
+ tres = PGTYPEStimestamp_from_asc(pval, &scan_length);
+ *endptr = endchar;
/* did we get an error? */
if (errno != 0)
@@ -744,10 +755,10 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
}
else
{
- if (isarray && *scan_length == '"')
+ if (*scan_length == '"')
scan_length++;
- if (garbage_left(isarray, scan_length, compat))
+ if (!isarray && garbage_left(isarray, scan_length, compat))
{
ecpg_raise(lineno, ECPG_TIMESTAMP_FORMAT,
ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
diff --git a/src/interfaces/ecpg/ecpglib/execute.c b/src/interfaces/ecpg/ecpglib/execute.c
index a4c7151f9a3..c5f1c165105 100644
--- a/src/interfaces/ecpg/ecpglib/execute.c
+++ b/src/interfaces/ecpg/ecpglib/execute.c
@@ -501,16 +501,10 @@ ecpg_store_input(const int lineno, const bool force_indicator, const struct vari
char *newcopy = NULL;
/*
- * arrays are not possible unless the attribute is an array too FIXME: we
- * do not know if the attribute is an array here
+ * arrays are not possible unless the column is an array, too
+ * FIXME: we do not know if the column is an array here
+ * array input to singleton column will result in a runtime error
*/
-#if 0
- if (var->arrsize > 1 &&...)
- {
- ecpg_raise(lineno, ECPG_ARRAY_INSERT, ECPG_SQLSTATE_DATATYPE_MISMATCH, NULL);
- return false;
- }
-#endif
/*
* Some special treatment is needed for records since we want their
@@ -568,12 +562,12 @@ ecpg_store_input(const int lineno, const bool force_indicator, const struct vari
if (asize > 1)
{
- strcpy(mallocedval, "array [");
+ strcpy(mallocedval, "{");
for (element = 0; element < asize; element++)
sprintf(mallocedval + strlen(mallocedval), "%hd,", ((short *) var->value)[element]);
- strcpy(mallocedval + strlen(mallocedval) - 1, "]");
+ strcpy(mallocedval + strlen(mallocedval) - 1, "}");
}
else
sprintf(mallocedval, "%hd", *((short *) var->value));
@@ -606,12 +600,12 @@ ecpg_store_input(const int lineno, const bool force_indicator, const struct vari
if (asize > 1)
{
- strcpy(mallocedval, "array [");
+ strcpy(mallocedval, "{");
for (element = 0; element < asize; element++)
sprintf(mallocedval + strlen(mallocedval), "%hu,", ((unsigned short *) var->value)[element]);
- strcpy(mallocedval + strlen(mallocedval) - 1, "]");
+ strcpy(mallocedval + strlen(mallocedval) - 1, "}");
}
else
sprintf(mallocedval, "%hu", *((unsigned short *) var->value));
@@ -625,12 +619,12 @@ ecpg_store_input(const int lineno, const bool force_indicator, const struct vari
if (asize > 1)
{
- strcpy(mallocedval, "array [");
+ strcpy(mallocedval, "{");
for (element = 0; element < asize; element++)
sprintf(mallocedval + strlen(mallocedval), "%u,", ((unsigned int *) var->value)[element]);
- strcpy(mallocedval + strlen(mallocedval) - 1, "]");
+ strcpy(mallocedval + strlen(mallocedval) - 1, "}");
}
else
sprintf(mallocedval, "%u", *((unsigned int *) var->value));
@@ -644,12 +638,12 @@ ecpg_store_input(const int lineno, const bool force_indicator, const struct vari
if (asize > 1)
{
- strcpy(mallocedval, "array [");
+ strcpy(mallocedval, "{");
for (element = 0; element < asize; element++)
sprintf(mallocedval + strlen(mallocedval), "%ld,", ((long *) var->value)[element]);
- strcpy(mallocedval + strlen(mallocedval) - 1, "]");
+ strcpy(mallocedval + strlen(mallocedval) - 1, "}");
}
else
sprintf(mallocedval, "%ld", *((long *) var->value));
@@ -663,12 +657,12 @@ ecpg_store_input(const int lineno, const bool force_indicator, const struct vari
if (asize > 1)
{
- strcpy(mallocedval, "array [");
+ strcpy(mallocedval, "{");
for (element = 0; element < asize; element++)
sprintf(mallocedval + strlen(mallocedval), "%lu,", ((unsigned long *) var->value)[element]);
- strcpy(mallocedval + strlen(mallocedval) - 1, "]");
+ strcpy(mallocedval + strlen(mallocedval) - 1, "}");
}
else
sprintf(mallocedval, "%lu", *((unsigned long *) var->value));
@@ -682,12 +676,12 @@ ecpg_store_input(const int lineno, const bool force_indicator, const struct vari
if (asize > 1)
{
- strcpy(mallocedval, "array [");
+ strcpy(mallocedval, "{");
for (element = 0; element < asize; element++)
sprintf(mallocedval + strlen(mallocedval), "%lld,", ((long long int *) var->value)[element]);
- strcpy(mallocedval + strlen(mallocedval) - 1, "]");
+ strcpy(mallocedval + strlen(mallocedval) - 1, "}");
}
else
sprintf(mallocedval, "%lld", *((long long int *) var->value));
@@ -701,12 +695,12 @@ ecpg_store_input(const int lineno, const bool force_indicator, const struct vari
if (asize > 1)
{
- strcpy(mallocedval, "array [");
+ strcpy(mallocedval, "{");
for (element = 0; element < asize; element++)
sprintf(mallocedval + strlen(mallocedval), "%llu,", ((unsigned long long int *) var->value)[element]);
- strcpy(mallocedval + strlen(mallocedval) - 1, "]");
+ strcpy(mallocedval + strlen(mallocedval) - 1, "}");
}
else
sprintf(mallocedval, "%llu", *((unsigned long long int *) var->value));
@@ -720,12 +714,12 @@ ecpg_store_input(const int lineno, const bool force_indicator, const struct vari
if (asize > 1)
{
- strcpy(mallocedval, "array [");
+ strcpy(mallocedval, "{");
for (element = 0; element < asize; element++)
sprintf_float_value(mallocedval + strlen(mallocedval), ((float *) var->value)[element], ",");
- strcpy(mallocedval + strlen(mallocedval) - 1, "]");
+ strcpy(mallocedval + strlen(mallocedval) - 1, "}");
}
else
sprintf_float_value(mallocedval, *((float *) var->value), "");
@@ -739,12 +733,12 @@ ecpg_store_input(const int lineno, const bool force_indicator, const struct vari
if (asize > 1)
{
- strcpy(mallocedval, "array [");
+ strcpy(mallocedval, "{");
for (element = 0; element < asize; element++)
sprintf_double_value(mallocedval + strlen(mallocedval), ((double *) var->value)[element], ",");
- strcpy(mallocedval + strlen(mallocedval) - 1, "]");
+ strcpy(mallocedval + strlen(mallocedval) - 1, "}");
}
else
sprintf_double_value(mallocedval, *((double *) var->value), "");
@@ -753,27 +747,27 @@ ecpg_store_input(const int lineno, const bool force_indicator, const struct vari
break;
case ECPGt_bool:
- if (!(mallocedval = ecpg_alloc(var->arrsize + sizeof("array []"), lineno)))
+ if (!(mallocedval = ecpg_alloc(var->arrsize + sizeof("{}"), lineno)))
return false;
if (var->arrsize > 1)
{
- strcpy(mallocedval, "array [");
+ strcpy(mallocedval, "{");
if (var->offset == sizeof(char))
- for (element = 0; element < var->arrsize; element++)
+ for (element = 0; element < asize; element++)
sprintf(mallocedval + strlen(mallocedval), "%c,", (((char *) var->value)[element]) ? 't' : 'f');
/*
* this is necessary since sizeof(C++'s bool)==sizeof(int)
*/
else if (var->offset == sizeof(int))
- for (element = 0; element < var->arrsize; element++)
+ for (element = 0; element < asize; element++)
sprintf(mallocedval + strlen(mallocedval), "%c,", (((int *) var->value)[element]) ? 't' : 'f');
else
ecpg_raise(lineno, ECPG_CONVERT_BOOL, ECPG_SQLSTATE_DATATYPE_MISMATCH, NULL);
- strcpy(mallocedval + strlen(mallocedval) - 1, "]");
+ strcpy(mallocedval + strlen(mallocedval) - 1, "}");
}
else
{
@@ -849,61 +843,33 @@ ecpg_store_input(const int lineno, const bool force_indicator, const struct vari
numeric *nval;
if (var->arrsize > 1)
- {
- if (!(mallocedval = ecpg_strdup("array [", lineno)))
- return false;
-
- for (element = 0; element < var->arrsize; element++)
- {
- int result;
-
- nval = PGTYPESnumeric_new();
- if (!nval)
- return false;
-
- if (var->type == ECPGt_numeric)
- result = PGTYPESnumeric_copy((numeric *) ((var + var->offset * element)->value), nval);
- else
- result = PGTYPESnumeric_from_decimal((decimal *) ((var + var->offset * element)->value), nval);
-
- if (result != 0)
- {
- PGTYPESnumeric_free(nval);
- return false;
- }
-
- str = PGTYPESnumeric_to_asc(nval, nval->dscale);
- slen = strlen(str);
- PGTYPESnumeric_free(nval);
+ mallocedval = ecpg_strdup("{", lineno);
+ else
+ mallocedval = ecpg_strdup("", lineno);
- if (!(mallocedval = ecpg_realloc(mallocedval, strlen(mallocedval) + slen + 2, lineno)))
- {
- ecpg_free(str);
- return false;
- }
+ if (!mallocedval)
+ return false;
- strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
- strcpy(mallocedval + strlen(mallocedval), ",");
- ecpg_free(str);
- }
- strcpy(mallocedval + strlen(mallocedval) - 1, "]");
- }
- else
+ for (element = 0; element < asize; element++)
{
int result;
nval = PGTYPESnumeric_new();
if (!nval)
+ {
+ ecpg_free(mallocedval);
return false;
+ }
if (var->type == ECPGt_numeric)
- result = PGTYPESnumeric_copy((numeric *) (var->value), nval);
+ result = PGTYPESnumeric_copy(&(((numeric *) (var->value))[element]), nval);
else
- result = PGTYPESnumeric_from_decimal((decimal *) (var->value), nval);
+ result = PGTYPESnumeric_from_decimal(&(((decimal *) (var->value))[element]), nval);
if (result != 0)
{
PGTYPESnumeric_free(nval);
+ ecpg_free(mallocedval);
return false;
}
@@ -911,17 +877,25 @@ ecpg_store_input(const int lineno, const bool force_indicator, const struct vari
slen = strlen(str);
PGTYPESnumeric_free(nval);
- if (!(mallocedval = ecpg_alloc(slen + 1, lineno)))
+ if (!(newcopy = ecpg_realloc(mallocedval, strlen(mallocedval) + slen + 2, lineno)))
{
- free(str);
+ ecpg_free(mallocedval);
+ ecpg_free(str);
return false;
}
+ mallocedval = newcopy;
+
+ /* also copy trailing '\0' */
+ memcpy(mallocedval + strlen(mallocedval), str, slen + 1);
+ if (var->arrsize > 1)
+ strcpy(mallocedval + strlen(mallocedval), ",");
- strncpy(mallocedval, str, slen);
- mallocedval[slen] = '\0';
ecpg_free(str);
}
+ if (var->arrsize > 1)
+ strcpy(mallocedval + strlen(mallocedval) - 1, "}");
+
*tobeinserted_p = mallocedval;
}
break;
@@ -932,47 +906,43 @@ ecpg_store_input(const int lineno, const bool force_indicator, const struct vari
int slen;
if (var->arrsize > 1)
- {
- if (!(mallocedval = ecpg_strdup("array [", lineno)))
- return false;
-
- for (element = 0; element < var->arrsize; element++)
- {
- str = quote_postgres(PGTYPESinterval_to_asc((interval *) ((var + var->offset * element)->value)), quote, lineno);
- if (!str)
- return false;
- slen = strlen(str);
+ mallocedval = ecpg_strdup("{", lineno);
+ else
+ mallocedval = ecpg_strdup("", lineno);
- if (!(mallocedval = ecpg_realloc(mallocedval, strlen(mallocedval) + slen + 2, lineno)))
- {
- ecpg_free(str);
- return false;
- }
+ if (!mallocedval)
+ return false;
- strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
- strcpy(mallocedval + strlen(mallocedval), ",");
- ecpg_free(str);
- }
- strcpy(mallocedval + strlen(mallocedval) - 1, "]");
- }
- else
+ for (element = 0; element < asize; element++)
{
- str = quote_postgres(PGTYPESinterval_to_asc((interval *) (var->value)), quote, lineno);
+ str = quote_postgres(PGTYPESinterval_to_asc(&(((interval *) (var->value))[element])), quote, lineno);
if (!str)
+ {
+ ecpg_free(mallocedval);
return false;
+ }
+
slen = strlen(str);
- if (!(mallocedval = ecpg_alloc(slen + sizeof("interval ") + 1, lineno)))
+ if (!(newcopy = ecpg_realloc(mallocedval, strlen(mallocedval) + slen + 2, lineno)))
{
+ ecpg_free(mallocedval);
ecpg_free(str);
return false;
}
+ mallocedval = newcopy;
/* also copy trailing '\0' */
- strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
+ memcpy(mallocedval + strlen(mallocedval), str, slen + 1);
+ if (var->arrsize > 1)
+ strcpy(mallocedval + strlen(mallocedval), ",");
+
ecpg_free(str);
}
+ if (var->arrsize > 1)
+ strcpy(mallocedval + strlen(mallocedval) - 1, "}");
+
*tobeinserted_p = mallocedval;
}
break;
@@ -983,47 +953,43 @@ ecpg_store_input(const int lineno, const bool force_indicator, const struct vari
int slen;
if (var->arrsize > 1)
- {
- if (!(mallocedval = ecpg_strdup("array [", lineno)))
- return false;
-
- for (element = 0; element < var->arrsize; element++)
- {
- str = quote_postgres(PGTYPESdate_to_asc(*(date *) ((var + var->offset * element)->value)), quote, lineno);
- if (!str)
- return false;
- slen = strlen(str);
+ mallocedval = ecpg_strdup("{", lineno);
+ else
+ mallocedval = ecpg_strdup("", lineno);
- if (!(mallocedval = ecpg_realloc(mallocedval, strlen(mallocedval) + slen + 2, lineno)))
- {
- ecpg_free(str);
- return false;
- }
+ if (!mallocedval)
+ return false;
- strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
- strcpy(mallocedval + strlen(mallocedval), ",");
- ecpg_free(str);
- }
- strcpy(mallocedval + strlen(mallocedval) - 1, "]");
- }
- else
+ for (element = 0; element < asize; element++)
{
- str = quote_postgres(PGTYPESdate_to_asc(*(date *) (var->value)), quote, lineno);
+ str = quote_postgres(PGTYPESdate_to_asc(((date *) (var->value))[element]), quote, lineno);
if (!str)
+ {
+ ecpg_free(mallocedval);
return false;
+ }
+
slen = strlen(str);
- if (!(mallocedval = ecpg_alloc(slen + sizeof("date ") + 1, lineno)))
+ if (!(newcopy = ecpg_realloc(mallocedval, strlen(mallocedval) + slen + 2, lineno)))
{
+ ecpg_free(mallocedval);
ecpg_free(str);
return false;
}
+ mallocedval = newcopy;
/* also copy trailing '\0' */
- strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
+ memcpy(mallocedval + strlen(mallocedval), str, slen + 1);
+ if (var->arrsize > 1)
+ strcpy(mallocedval + strlen(mallocedval), ",");
+
ecpg_free(str);
}
+ if (var->arrsize > 1)
+ strcpy(mallocedval + strlen(mallocedval) - 1, "}");
+
*tobeinserted_p = mallocedval;
}
break;
@@ -1034,51 +1000,43 @@ ecpg_store_input(const int lineno, const bool force_indicator, const struct vari
int slen;
if (var->arrsize > 1)
- {
- if (!(mallocedval = ecpg_strdup("array [", lineno)))
- return false;
-
- for (element = 0; element < var->arrsize; element++)
- {
- str = quote_postgres(PGTYPEStimestamp_to_asc(*(timestamp *) ((var + var->offset * element)->value)), quote, lineno);
- if (!str)
- {
- ecpg_free(mallocedval);
- return false;
- }
-
- slen = strlen(str);
+ mallocedval = ecpg_strdup("{", lineno);
+ else
+ mallocedval = ecpg_strdup("", lineno);
- if (!(mallocedval = ecpg_realloc(mallocedval, strlen(mallocedval) + slen + 2, lineno)))
- {
- ecpg_free(str);
- return false;
- }
+ if (!mallocedval)
+ return false;
- strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
- strcpy(mallocedval + strlen(mallocedval), ",");
- ecpg_free(str);
- }
- strcpy(mallocedval + strlen(mallocedval) - 1, "]");
- }
- else
+ for (element = 0; element < asize; element++)
{
- str = quote_postgres(PGTYPEStimestamp_to_asc(*(timestamp *) (var->value)), quote, lineno);
+ str = quote_postgres(PGTYPEStimestamp_to_asc(((timestamp *) (var->value))[element]), quote, lineno);
if (!str)
+ {
+ ecpg_free(mallocedval);
return false;
+ }
+
slen = strlen(str);
- if (!(mallocedval = ecpg_alloc(slen + sizeof("timestamp") + 1, lineno)))
+ if (!(newcopy = ecpg_realloc(mallocedval, strlen(mallocedval) + slen + 2, lineno)))
{
+ ecpg_free(mallocedval);
ecpg_free(str);
return false;
}
+ mallocedval = newcopy;
/* also copy trailing '\0' */
- strncpy(mallocedval + strlen(mallocedval), str, slen + 1);
+ memcpy(mallocedval + strlen(mallocedval), str, slen + 1);
+ if (var->arrsize > 1)
+ strcpy(mallocedval + strlen(mallocedval), ",");
+
ecpg_free(str);
}
+ if (var->arrsize > 1)
+ strcpy(mallocedval + strlen(mallocedval) - 1, "}");
+
*tobeinserted_p = mallocedval;
}
break;