aboutsummaryrefslogtreecommitdiff
path: root/src/interfaces/ecpg/ecpglib/cursor.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/interfaces/ecpg/ecpglib/cursor.c')
-rw-r--r--src/interfaces/ecpg/ecpglib/cursor.c258
1 files changed, 258 insertions, 0 deletions
diff --git a/src/interfaces/ecpg/ecpglib/cursor.c b/src/interfaces/ecpg/ecpglib/cursor.c
new file mode 100644
index 00000000000..ae67bfe8e08
--- /dev/null
+++ b/src/interfaces/ecpg/ecpglib/cursor.c
@@ -0,0 +1,258 @@
+/* src/interfaces/ecpg/ecpglib/cursor.c */
+
+#define POSTGRES_ECPG_INTERNAL
+#include "postgres_fe.h"
+
+#include <ctype.h>
+#include <locale.h>
+#include <string.h>
+
+#include "ecpgtype.h"
+#include "ecpglib.h"
+#include "ecpgerrno.h"
+#include "ecpglib_extern.h"
+#include "sqlca.h"
+
+static void add_cursor(const int, const char *, const char *);
+static void remove_cursor(const char *, struct connection *);
+static bool find_cursor(const char *, const struct connection *);
+
+/*
+ * Function: Handle the EXEC SQL OPEN cursor statement:
+ * Input:
+ * cursor_name --- cursor name
+ * prepared_name --- prepared name
+ * others --- keep same as the parameters in ECPGdo() function
+ */
+bool
+ECPGopen(const char *cursor_name,const char *prepared_name,
+ const int lineno, const int compat,const int force_indicator,
+ const char *connection_name, const bool questionmarks,
+ const int st, const char *query,...)
+{
+ va_list args;
+ bool status;
+ const char *real_connection_name = NULL;
+
+ if (!query)
+ {
+ ecpg_raise(lineno, ECPG_EMPTY, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, NULL);
+ return false;
+ }
+
+ /*
+ * If the declared name is referred by the PREPARE statement then the
+ * prepared_name is same as declared name
+ */
+ real_connection_name = ecpg_get_con_name_by_declared_name(prepared_name);
+ if (real_connection_name)
+ {
+ /* Add the cursor name into the declared node */
+ ecpg_update_declare_statement(prepared_name, cursor_name, lineno);
+ }
+ else
+ {
+ /*
+ * If can't get the connection name by declared name then using connection name
+ * coming from the parameter connection_name
+ */
+ real_connection_name = connection_name;
+ }
+
+
+ /* Add the cursor into the connection */
+ add_cursor(lineno, cursor_name, real_connection_name);
+
+ va_start(args, query);
+
+ status = ecpg_do(lineno, compat, force_indicator, real_connection_name, questionmarks, st, query, args);
+
+ va_end(args);
+
+ return status;
+}
+
+
+/*
+ * Function: Handle the EXEC SQL FETCH/MOVE CURSOR statements:
+ * Input:
+ * cursor_name --- cursor name
+ * others --- keep same as the parameters in ECPGdo() function
+ */
+bool
+ECPGfetch(const char *cursor_name,
+ const int lineno, const int compat,const int force_indicator,
+ const char *connection_name, const bool questionmarks,
+ const int st, const char *query,...)
+{
+ va_list args;
+ bool status;
+ const char *real_connection_name = NULL;
+
+ if (!query)
+ {
+ ecpg_raise(lineno, ECPG_EMPTY, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, NULL);
+ return (false);
+ }
+
+ real_connection_name = ecpg_get_con_name_by_cursor_name(cursor_name);
+ if (real_connection_name == NULL)
+ {
+ /*
+ * If can't get the connection name by cursor name then using connection name
+ * coming from the parameter connection_name
+ */
+ real_connection_name = connection_name;
+ }
+
+ va_start(args, query);
+
+ status = ecpg_do(lineno, compat, force_indicator, real_connection_name, questionmarks, st, query, args);
+
+ va_end(args);
+
+ return status;
+}
+
+
+/*
+ * Function: Handle the EXEC SQL CLOSE CURSOR statements:
+ * Input:
+ * cursor_name --- cursor name
+ * others --- keep same as the parameters in ECPGdo() function
+ */
+bool
+ECPGclose(const char *cursor_name,
+ const int lineno, const int compat,const int force_indicator,
+ const char *connection_name, const bool questionmarks,
+ const int st, const char *query,...)
+{
+ va_list args;
+ bool status;
+ const char *real_connection_name = NULL;
+ struct connection *con = NULL;
+
+ if (!query)
+ {
+ ecpg_raise(lineno, ECPG_EMPTY, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, NULL);
+ return false;
+ }
+
+ real_connection_name = ecpg_get_con_name_by_cursor_name(cursor_name);
+ if (real_connection_name == NULL)
+ {
+ /*
+ * If can't get the connection name by cursor name then using connection name
+ * coming from the parameter connection_name
+ */
+ real_connection_name = connection_name;
+ }
+
+ con = ecpg_get_connection(real_connection_name);
+
+ /* check the existence of the cursor in the connection */
+ if (find_cursor(cursor_name, con) == false)
+ {
+ ecpg_raise(lineno, ECPG_INVALID_CURSOR, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, NULL);
+ return false;
+ }
+
+ va_start(args, query);
+
+ status = ecpg_do(lineno, compat, force_indicator, real_connection_name, questionmarks, st, query, args);
+
+ va_end(args);
+
+ remove_cursor(cursor_name, con);
+
+ return status;
+}
+
+/*
+ * Function: Add a cursor into the connection
+ * The duplication of cursor_name is checked at ecpg.trailer,
+ * so we don't check here.
+ */
+static void
+add_cursor(const int lineno, const char *cursor_name, const char *connection_name)
+{
+ struct connection *con;
+ struct cursor_statement *new = NULL;
+
+ if (!cursor_name)
+ {
+ ecpg_raise(lineno, ECPG_INVALID_CURSOR, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, NULL);
+ return;
+ }
+
+ con = ecpg_get_connection(connection_name);
+ if (!con)
+ {
+ ecpg_raise(lineno, ECPG_NO_CONN, ECPG_SQLSTATE_CONNECTION_DOES_NOT_EXIST,
+ connection_name ? connection_name : ecpg_gettext("NULL"));
+ return;
+ }
+
+ /* allocate a node to store the new cursor */
+ new = (struct cursor_statement *)ecpg_alloc(sizeof(struct cursor_statement), lineno);
+ if (new)
+ {
+ new->name = ecpg_strdup(cursor_name, lineno);
+ new->next = con->cursor_stmts;
+ con->cursor_stmts = new;
+ }
+}
+
+/*
+ * Function: Remove the cursor from the connection
+ */
+static void
+remove_cursor(const char *cursor_name, struct connection *connection)
+{
+ struct cursor_statement *cur = NULL;
+ struct cursor_statement *prev = NULL;
+
+ if (!connection || !cursor_name)
+ return;
+
+ cur = connection->cursor_stmts;
+ while (cur)
+ {
+ if (strcmp(cur->name, cursor_name) == 0)
+ {
+ if (!prev)
+ connection->cursor_stmts = cur->next;
+ else
+ prev->next = cur->next;
+
+ ecpg_free(cur->name);
+ ecpg_free(cur);
+
+ break;
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+}
+
+/*
+ * Function: check the existence of the cursor in the connection
+ * Return: true ---Found
+ * false --- Not found
+ */
+static bool
+find_cursor(const char *cursor_name, const struct connection *connection)
+{
+ struct cursor_statement *cur = NULL;
+
+ if (!connection || !cursor_name)
+ return false;
+
+ for (cur = connection->cursor_stmts; cur != NULL; cur = cur->next)
+ {
+ if (strcmp(cur->name, cursor_name) == 0)
+ return true;
+ }
+
+ return false;
+}