aboutsummaryrefslogtreecommitdiff
path: root/src/interfaces/ecpg/ecpglib/execute.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/interfaces/ecpg/ecpglib/execute.c')
-rw-r--r--src/interfaces/ecpg/ecpglib/execute.c82
1 files changed, 80 insertions, 2 deletions
diff --git a/src/interfaces/ecpg/ecpglib/execute.c b/src/interfaces/ecpg/ecpglib/execute.c
index 8e61339ae30..2db1b620586 100644
--- a/src/interfaces/ecpg/ecpglib/execute.c
+++ b/src/interfaces/ecpg/ecpglib/execute.c
@@ -488,6 +488,23 @@ sprintf_float_value(char *ptr, float value, const char *delim)
sprintf(ptr, "%.15g%s", value, delim);
}
+static char*
+convert_bytea_to_string(char *from_data, int from_len, int lineno)
+{
+ char *to_data;
+ int to_len = ecpg_hex_enc_len(from_len) + 4 + 1; /* backslash + 'x' + quote + quote */
+
+ to_data = ecpg_alloc(to_len, lineno);
+ if (!to_data)
+ return NULL;
+
+ strcpy(to_data, "'\\x");
+ ecpg_hex_encode(from_data, from_len, to_data + 3);
+ strcpy(to_data + 3 + ecpg_hex_enc_len(from_len), "\'");
+
+ return to_data;
+}
+
bool
ecpg_store_input(const int lineno, const bool force_indicator, const struct variable *var,
char **tobeinserted_p, bool quote)
@@ -1433,6 +1450,36 @@ ecpg_build_params(struct statement *stmt)
*/
else if (stmt->command[position] == '0')
{
+ if (stmt->statement_type == ECPGst_prepare ||
+ stmt->statement_type == ECPGst_exec_with_exprlist)
+ {
+ /* Add double quote both side for embedding statement name. */
+ char *str = ecpg_alloc(strlen(tobeinserted) + 2 + 1, stmt->lineno);
+ sprintf(str, "\"%s\"", tobeinserted);
+ ecpg_free(tobeinserted);
+ tobeinserted = str;
+ }
+ if (!insert_tobeinserted(position, 2, stmt, tobeinserted))
+ {
+ ecpg_free_params(stmt, false);
+ return false;
+ }
+ tobeinserted = NULL;
+ }
+ else if (stmt->statement_type == ECPGst_exec_with_exprlist)
+ {
+
+ if (binary_format)
+ {
+ char *p = convert_bytea_to_string(tobeinserted, binary_length, stmt->lineno);
+ if (!p)
+ {
+ ecpg_free_params(stmt, false);
+ return false;
+ }
+ tobeinserted = p;
+ }
+
if (!insert_tobeinserted(position, 2, stmt, tobeinserted))
{
ecpg_free_params(stmt, false);
@@ -1493,8 +1540,12 @@ ecpg_build_params(struct statement *stmt)
var = var->next;
}
- /* Check if there are unmatched things left. */
- if (next_insert(stmt->command, position, stmt->questionmarks, std_strings) >= 0)
+ /*
+ * Check if there are unmatched things left.
+ * PREPARE AS has no parameter. Check other statement.
+ */
+ if (stmt->statement_type != ECPGst_prepare &&
+ next_insert(stmt->command, position, stmt->questionmarks, std_strings) >= 0)
{
ecpg_raise(stmt->lineno, ECPG_TOO_FEW_ARGUMENTS,
ECPG_SQLSTATE_USING_CLAUSE_DOES_NOT_MATCH_PARAMETERS, NULL);
@@ -1560,8 +1611,18 @@ ecpg_execute(struct statement *stmt)
(const int *) stmt->paramlengths,
(const int *) stmt->paramformats,
0);
+
ecpg_log("ecpg_execute on line %d: using PQexecParams\n", stmt->lineno);
}
+
+ if (stmt->statement_type == ECPGst_prepare)
+ {
+ if(! ecpg_register_prepared_stmt(stmt))
+ {
+ ecpg_free_params(stmt, true);
+ return false;
+ }
+ }
}
ecpg_free_params(stmt, true);
@@ -1874,6 +1935,7 @@ ecpg_do_prologue(int lineno, const int compat, const int force_indicator,
enum ECPGttype type;
struct variable **list;
char *prepname;
+ bool is_prepared_name_set;
*stmt_out = NULL;
@@ -1975,6 +2037,7 @@ ecpg_do_prologue(int lineno, const int compat, const int force_indicator,
return false;
}
}
+ /* name of PREPARE AS will be set in loop of inlist */
stmt->connection = con;
stmt->lineno = lineno;
@@ -2004,6 +2067,8 @@ ecpg_do_prologue(int lineno, const int compat, const int force_indicator,
*------
*/
+ is_prepared_name_set = false;
+
list = &(stmt->inlist);
type = va_arg(args, enum ECPGttype);
@@ -2092,6 +2157,12 @@ ecpg_do_prologue(int lineno, const int compat, const int force_indicator,
*list = var;
else
ptr->next = var;
+
+ if (!is_prepared_name_set && stmt->statement_type == ECPGst_prepare)
+ {
+ stmt->name = ecpg_strdup(var->value, lineno);
+ is_prepared_name_set = true;
+ }
}
type = va_arg(args, enum ECPGttype);
@@ -2105,6 +2176,13 @@ ecpg_do_prologue(int lineno, const int compat, const int force_indicator,
return false;
}
+ if (!is_prepared_name_set && stmt->statement_type == ECPGst_prepare)
+ {
+ ecpg_raise(lineno, ECPG_TOO_FEW_ARGUMENTS, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, (con) ? con->name : ecpg_gettext("<empty>"));
+ ecpg_do_epilogue(stmt);
+ return false;
+ }
+
/* initialize auto_mem struct */
ecpg_clear_auto_mem();