aboutsummaryrefslogtreecommitdiff
path: root/src/interfaces/ecpg/lib/prepare.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/interfaces/ecpg/lib/prepare.c')
-rw-r--r--src/interfaces/ecpg/lib/prepare.c149
1 files changed, 149 insertions, 0 deletions
diff --git a/src/interfaces/ecpg/lib/prepare.c b/src/interfaces/ecpg/lib/prepare.c
new file mode 100644
index 00000000000..409d289027f
--- /dev/null
+++ b/src/interfaces/ecpg/lib/prepare.c
@@ -0,0 +1,149 @@
+#include <ctype.h>
+
+#include <ecpgtype.h>
+#include <ecpglib.h>
+#include <sqlca.h>
+
+static struct prepared_statement
+{
+ char *name;
+ struct statement *stmt;
+ struct prepared_statement *next;
+} *prep_stmts = NULL;
+
+static bool
+isvarchar(unsigned char c)
+{
+ if (isalnum(c))
+ return true;
+
+ if (c == '_' || c == '>' || c == '-' || c == '.')
+ return true;
+
+ if (c >= 128)
+ return true;
+
+ return (false);
+}
+
+static void
+replace_variables(char *text)
+{
+ char *ptr = text;
+ bool string = false;
+
+ for (; *ptr != '\0'; ptr++)
+ {
+ if (*ptr == '\'')
+ string = string ? false : true;
+
+ if (!string && *ptr == ':')
+ {
+ *ptr = '?';
+ for (++ptr; *ptr && isvarchar(*ptr); ptr++)
+ *ptr = ' ';
+ }
+ }
+}
+
+/* handle the EXEC SQL PREPARE statement */
+bool
+ECPGprepare(int lineno, char *name, char *variable)
+{
+ struct statement *stmt;
+ struct prepared_statement *this;
+
+ /* check if we already have prepared this statement */
+ for (this = prep_stmts; this != NULL && strcmp(this->name, name) != 0; this = this->next);
+ if (this)
+ {
+ bool b = ECPGdeallocate(lineno, name);
+
+ if (!b)
+ return false;
+ }
+
+ this = (struct prepared_statement *) ecpg_alloc(sizeof(struct prepared_statement), lineno);
+ if (!this)
+ return false;
+
+ stmt = (struct statement *) ecpg_alloc(sizeof(struct statement), lineno);
+ if (!stmt)
+ {
+ free(this);
+ return false;
+ }
+
+ /* create statement */
+ stmt->lineno = lineno;
+ stmt->connection = NULL;
+ stmt->command = ecpg_strdup(variable, lineno);
+ stmt->inlist = stmt->outlist = NULL;
+
+ /* if we have C variables in our statment replace them with '?' */
+ replace_variables(stmt->command);
+
+ /* add prepared statement to our list */
+ this->name = ecpg_strdup(name, lineno);
+ this->stmt = stmt;
+
+ if (prep_stmts == NULL)
+ this->next = NULL;
+ else
+ this->next = prep_stmts;
+
+ prep_stmts = this;
+ return true;
+}
+
+/* handle the EXEC SQL DEALLOCATE PREPARE statement */
+bool
+ECPGdeallocate(int lineno, char *name)
+{
+ struct prepared_statement *this,
+ *prev;
+
+ /* check if we really have prepared this statement */
+ for (this = prep_stmts, prev = NULL; this != NULL && strcmp(this->name, name) != 0; prev = this, this = this->next);
+ if (this)
+ {
+ /* okay, free all the resources */
+ free(this->name);
+ free(this->stmt->command);
+ free(this->stmt);
+ if (prev != NULL)
+ prev->next = this->next;
+ else
+ prep_stmts = this->next;
+
+ free(this);
+ return true;
+ }
+ ECPGlog("deallocate_prepare: invalid statement name %s\n", name);
+ ECPGraise(lineno, ECPG_INVALID_STMT, name);
+ return false;
+}
+
+bool
+ECPGdeallocate_all(int lineno)
+{
+ /* deallocate all prepared statements */
+ while(prep_stmts != NULL)
+ {
+ bool b = ECPGdeallocate(lineno, prep_stmts->name);
+
+ if (!b)
+ return false;
+ }
+
+}
+
+/* return the prepared statement */
+char *
+ECPGprepared_statement(char *name)
+{
+ struct prepared_statement *this;
+
+ for (this = prep_stmts; this != NULL && strcmp(this->name, name) != 0; this = this->next);
+ return (this) ? this->stmt->command : NULL;
+}