mirror of
https://github.com/postgres/postgres.git
synced 2025-10-27 00:12:01 +03:00
Revert "Add DECLARE STATEMENT support to ECPG."
This reverts commit bd7c95f0c1,
along with assorted follow-on fixes. There are some questions
about the definition and implementation of that statement, and
we don't have time to resolve them before v13 release. Rather
than ship the feature and then have backwards-compatibility
concerns constraining any redesign, let's remove it for now
and try again later.
Discussion: https://postgr.es/m/TY2PR01MB2443EC8286995378AEB7D9F8F5B10@TY2PR01MB2443.jpnprd01.prod.outlook.com
This commit is contained in:
@@ -23,7 +23,7 @@ override CPPFLAGS := -I../include -I$(top_srcdir)/src/interfaces/ecpg/include \
|
||||
override CFLAGS += $(PTHREAD_CFLAGS)
|
||||
|
||||
OBJS= execute.o typename.o descriptor.o sqlda.o data.o error.o prepare.o \
|
||||
memory.o connect.o misc.o cursor.o $(WIN32RES)
|
||||
memory.o connect.o misc.o $(WIN32RES)
|
||||
|
||||
SHLIB_LINK_INTERNAL = -L../pgtypeslib -lpgtypes $(libpq_pgport_shlib)
|
||||
SHLIB_LINK = $(filter -lintl -lm, $(LIBS)) $(PTHREAD_LIBS)
|
||||
|
||||
@@ -340,8 +340,6 @@ ECPGconnect(int lineno, int c, const char *name, const char *user, const char *p
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(this, 0, sizeof(struct connection));
|
||||
|
||||
if (dbname != NULL)
|
||||
{
|
||||
/* get the detail information from dbname */
|
||||
@@ -707,7 +705,6 @@ ECPGdisconnect(int lineno, const char *connection_name)
|
||||
struct connection *f = con;
|
||||
|
||||
con = con->next;
|
||||
ecpg_release_declared_statement(f->name);
|
||||
ecpg_finish(f);
|
||||
}
|
||||
}
|
||||
@@ -723,10 +720,7 @@ ECPGdisconnect(int lineno, const char *connection_name)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ecpg_release_declared_statement(connection_name);
|
||||
ecpg_finish(con);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_THREAD_SAFETY
|
||||
|
||||
@@ -1,261 +0,0 @@
|
||||
/* 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);
|
||||
|
||||
/* send the query to backend */
|
||||
va_start(args, query);
|
||||
|
||||
status = ecpg_do(lineno, compat, force_indicator, real_connection_name, questionmarks, st, query, args);
|
||||
|
||||
va_end(args);
|
||||
|
||||
/* if it fails, raise an error */
|
||||
if (!status)
|
||||
{
|
||||
ecpg_raise(lineno, ECPG_INVALID_CURSOR, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* check the existence of the cursor in the connection */
|
||||
if (find_cursor(cursor_name, con) == true)
|
||||
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;
|
||||
}
|
||||
@@ -861,7 +861,6 @@ ECPGdescribe(int line, int compat, bool input, const char *connection_name, cons
|
||||
struct prepared_statement *prep;
|
||||
PGresult *res;
|
||||
va_list args;
|
||||
const char *real_connection_name = NULL;
|
||||
|
||||
/* DESCRIBE INPUT is not yet supported */
|
||||
if (input)
|
||||
@@ -870,21 +869,11 @@ ECPGdescribe(int line, int compat, bool input, const char *connection_name, cons
|
||||
return ret;
|
||||
}
|
||||
|
||||
real_connection_name = ecpg_get_con_name_by_declared_name(stmt_name);
|
||||
if (real_connection_name == NULL)
|
||||
{
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
con = ecpg_get_connection(real_connection_name);
|
||||
con = ecpg_get_connection(connection_name);
|
||||
if (!con)
|
||||
{
|
||||
ecpg_raise(line, ECPG_NO_CONN, ECPG_SQLSTATE_CONNECTION_DOES_NOT_EXIST,
|
||||
real_connection_name ? real_connection_name : ecpg_gettext("NULL"));
|
||||
connection_name ? connection_name : ecpg_gettext("NULL"));
|
||||
return ret;
|
||||
}
|
||||
prep = ecpg_find_prepared_statement(stmt_name, con, NULL);
|
||||
|
||||
@@ -88,15 +88,6 @@ struct statement
|
||||
PGresult *results;
|
||||
};
|
||||
|
||||
/* structure to store declared statements */
|
||||
struct declared_statement
|
||||
{
|
||||
char *name; /* declared name */
|
||||
char *connection_name;
|
||||
char *cursor_name;
|
||||
struct declared_statement *next;
|
||||
};
|
||||
|
||||
/* structure to store prepared statements for a connection */
|
||||
struct prepared_statement
|
||||
{
|
||||
@@ -106,12 +97,6 @@ struct prepared_statement
|
||||
struct prepared_statement *next;
|
||||
};
|
||||
|
||||
struct cursor_statement
|
||||
{
|
||||
char *name; /* cursor name */
|
||||
struct cursor_statement *next;
|
||||
};
|
||||
|
||||
/* structure to store connections */
|
||||
struct connection
|
||||
{
|
||||
@@ -120,7 +105,6 @@ struct connection
|
||||
bool autocommit;
|
||||
struct ECPGtype_information_cache *cache_head;
|
||||
struct prepared_statement *prep_stmts;
|
||||
struct cursor_statement *cursor_stmts;
|
||||
struct connection *next;
|
||||
};
|
||||
|
||||
@@ -202,11 +186,6 @@ struct descriptor *ecpg_find_desc(int line, const char *name);
|
||||
struct prepared_statement *ecpg_find_prepared_statement(const char *,
|
||||
struct connection *, struct prepared_statement **);
|
||||
|
||||
void ecpg_update_declare_statement(const char *, const char *, const int);
|
||||
char *ecpg_get_con_name_by_declared_name(const char *);
|
||||
const char *ecpg_get_con_name_by_cursor_name(const char *);
|
||||
void ecpg_release_declared_statement(const char *);
|
||||
|
||||
bool ecpg_store_result(const PGresult *results, int act_field,
|
||||
const struct statement *stmt, struct variable *var);
|
||||
bool ecpg_store_input(const int, const bool, const struct variable *, char **, bool);
|
||||
|
||||
@@ -200,13 +200,6 @@ ecpg_raise(int line, int code, const char *sqlstate, const char *str)
|
||||
ecpg_gettext("could not connect to database \"%s\" on line %d"), str, line);
|
||||
break;
|
||||
|
||||
case ECPG_INVALID_CURSOR:
|
||||
snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
|
||||
/*------
|
||||
translator: this string will be truncated at 149 characters expanded. */
|
||||
ecpg_gettext("cursor is invalid on line %d"), line);
|
||||
break;
|
||||
|
||||
default:
|
||||
snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
|
||||
/*------
|
||||
|
||||
@@ -2280,32 +2280,9 @@ ECPGdo(const int lineno, const int compat, const int force_indicator, const char
|
||||
{
|
||||
va_list args;
|
||||
bool ret;
|
||||
const char *real_connection_name = NULL;
|
||||
|
||||
real_connection_name = connection_name;
|
||||
|
||||
if (!query)
|
||||
{
|
||||
ecpg_raise(lineno, ECPG_EMPTY, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Handle the EXEC SQL EXECUTE... statement */
|
||||
if (ECPGst_execute == st)
|
||||
{
|
||||
real_connection_name = ecpg_get_con_name_by_declared_name(query);
|
||||
if (real_connection_name == NULL)
|
||||
{
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
va_start(args, query);
|
||||
ret = ecpg_do(lineno, compat, force_indicator, real_connection_name,
|
||||
ret = ecpg_do(lineno, compat, force_indicator, connection_name,
|
||||
questionmarks, st, query, args);
|
||||
va_end(args);
|
||||
|
||||
|
||||
@@ -29,7 +29,3 @@ ECPGget_PGconn 26
|
||||
ECPGtransactionStatus 27
|
||||
ECPGset_var 28
|
||||
ECPGget_var 29
|
||||
ECPGdeclare 30
|
||||
ECPGopen 31
|
||||
ECPGfetch 32
|
||||
ECPGclose 33
|
||||
@@ -36,11 +36,10 @@ typedef struct
|
||||
|
||||
static int nextStmtID = 1;
|
||||
static stmtCacheEntry *stmtCacheEntries = NULL;
|
||||
static struct declared_statement *g_declared_list;
|
||||
|
||||
static bool deallocate_one(int lineno, enum COMPAT_MODE c, struct connection *con,
|
||||
struct prepared_statement *prev, struct prepared_statement *this);
|
||||
static struct declared_statement *ecpg_find_declared_statement(const char *);
|
||||
|
||||
static bool
|
||||
isvarchar(unsigned char c)
|
||||
{
|
||||
@@ -61,19 +60,10 @@ ecpg_register_prepared_stmt(struct statement *stmt)
|
||||
{
|
||||
struct statement *prep_stmt;
|
||||
struct prepared_statement *this;
|
||||
struct connection *con = NULL;
|
||||
struct connection *con = stmt->connection;
|
||||
struct prepared_statement *prev = NULL;
|
||||
char *real_connection_name;
|
||||
int lineno = stmt->lineno;
|
||||
|
||||
real_connection_name = ecpg_get_con_name_by_declared_name(stmt->name);
|
||||
if (real_connection_name == NULL)
|
||||
real_connection_name = stmt->connection->name;
|
||||
|
||||
con = ecpg_get_connection(real_connection_name);
|
||||
if (!ecpg_init(con, real_connection_name, stmt->lineno))
|
||||
return false;
|
||||
|
||||
/* check if we already have prepared this statement */
|
||||
this = ecpg_find_prepared_statement(stmt->name, con, &prev);
|
||||
if (this && !deallocate_one(lineno, ECPG_COMPAT_PGSQL, con, prev, this))
|
||||
@@ -183,7 +173,6 @@ prepare_common(int lineno, struct connection *con, const char *name, const char
|
||||
ecpg_free(this);
|
||||
return false;
|
||||
}
|
||||
memset(stmt, 0, sizeof(struct statement));
|
||||
|
||||
/* create statement */
|
||||
stmt->lineno = lineno;
|
||||
@@ -231,22 +220,11 @@ ECPGprepare(int lineno, const char *connection_name, const bool questionmarks,
|
||||
struct connection *con;
|
||||
struct prepared_statement *this,
|
||||
*prev;
|
||||
const char *real_connection_name = NULL;
|
||||
|
||||
(void) questionmarks; /* quiet the compiler */
|
||||
|
||||
real_connection_name = ecpg_get_con_name_by_declared_name(name);
|
||||
if (real_connection_name == NULL)
|
||||
{
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
con = ecpg_get_connection(real_connection_name);
|
||||
if (!ecpg_init(con, real_connection_name, lineno))
|
||||
con = ecpg_get_connection(connection_name);
|
||||
if (!ecpg_init(con, connection_name, lineno))
|
||||
return false;
|
||||
|
||||
/* check if we already have prepared this statement */
|
||||
@@ -339,20 +317,9 @@ ECPGdeallocate(int lineno, int c, const char *connection_name, const char *name)
|
||||
struct connection *con;
|
||||
struct prepared_statement *this,
|
||||
*prev;
|
||||
const char *real_connection_name = NULL;
|
||||
|
||||
real_connection_name = ecpg_get_con_name_by_declared_name(name);
|
||||
if (real_connection_name == NULL)
|
||||
{
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
con = ecpg_get_connection(real_connection_name);
|
||||
if (!ecpg_init(con, real_connection_name, lineno))
|
||||
con = ecpg_get_connection(connection_name);
|
||||
if (!ecpg_init(con, connection_name, lineno))
|
||||
return false;
|
||||
|
||||
this = ecpg_find_prepared_statement(name, con, &prev);
|
||||
@@ -400,21 +367,9 @@ ecpg_prepared(const char *name, struct connection *con)
|
||||
char *
|
||||
ECPGprepared_statement(const char *connection_name, const char *name, int lineno)
|
||||
{
|
||||
const char *real_connection_name = NULL;
|
||||
|
||||
(void) lineno; /* keep the compiler quiet */
|
||||
|
||||
real_connection_name = ecpg_get_con_name_by_declared_name(name);
|
||||
if (real_connection_name == NULL)
|
||||
{
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
return ecpg_prepared(name, ecpg_get_connection(real_connection_name));
|
||||
return ecpg_prepared(name, ecpg_get_connection(connection_name));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -645,210 +600,3 @@ ecpg_auto_prepare(int lineno, const char *connection_name, const int compat, cha
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* handle the EXEC SQL DECLARE STATEMENT
|
||||
* Input: connection_name -- connection name
|
||||
* name -- declared name
|
||||
*/
|
||||
bool
|
||||
ECPGdeclare(int lineno, const char *connection_name, const char *name)
|
||||
{
|
||||
struct connection *con = NULL;
|
||||
struct declared_statement *p = NULL;
|
||||
|
||||
if (name == NULL)
|
||||
{
|
||||
/* Should never go to here because ECPG pre-compiler will check it */
|
||||
return false;
|
||||
}
|
||||
|
||||
if (connection_name == NULL)
|
||||
{
|
||||
/*
|
||||
* Going to here means not using AT clause in the DECLARE STATEMENT
|
||||
* ECPG pre-processor allows this case. However, we don't allocate a
|
||||
* node to store the declared name because the DECLARE STATEMENT
|
||||
* without using AT clause will be ignored. The following statement
|
||||
* such as PREPARE, EXECUTE are executed as usual on the current
|
||||
* connection.
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
con = ecpg_get_connection(connection_name);
|
||||
if (!ecpg_init(con, connection_name, lineno))
|
||||
return false;
|
||||
|
||||
if (ecpg_find_declared_statement(name))
|
||||
{
|
||||
/*
|
||||
* Should not go to here because the pre-compiler has check the
|
||||
* duplicate name
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
/* allocate a declared_statement as a new node */
|
||||
p = (struct declared_statement *) ecpg_alloc(sizeof(struct declared_statement), lineno);
|
||||
if (!p)
|
||||
return false;
|
||||
|
||||
memset(p, 0, sizeof(struct declared_statement));
|
||||
|
||||
ecpg_log("ECPGdeclare on line %d: declared name \"%s\" on connection: \"%s\"\n", lineno, name, connection_name);
|
||||
|
||||
p->name = ecpg_strdup(name, lineno);
|
||||
p->connection_name = ecpg_strdup(connection_name, lineno);
|
||||
|
||||
/* Add the new node into the g_declared_list */
|
||||
if (g_declared_list != NULL)
|
||||
{
|
||||
p->next = g_declared_list;
|
||||
g_declared_list = p;
|
||||
}
|
||||
else
|
||||
g_declared_list = p;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a declared node by declared name
|
||||
* Input: name -- declared name
|
||||
* Return: Found -- The pointer points to the declared node
|
||||
* Not found -- NULL
|
||||
*/
|
||||
static struct declared_statement *
|
||||
ecpg_find_declared_statement(const char *name)
|
||||
{
|
||||
struct declared_statement *p;
|
||||
|
||||
if (name == NULL)
|
||||
return NULL;
|
||||
|
||||
p = g_declared_list;
|
||||
while (p)
|
||||
{
|
||||
if (strcmp(p->name, name) == 0)
|
||||
return p;
|
||||
p = p->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Build the relationship between the declared name and cursor name
|
||||
* Input: declared_name -- the name declared in the DECLARE STATEMENT
|
||||
* cursor_name -- cursor name declared in the DECLARE/OPEN CURSOR statement
|
||||
*/
|
||||
void
|
||||
ecpg_update_declare_statement(const char *declared_name, const char *cursor_name, const int lineno)
|
||||
{
|
||||
struct declared_statement *p = NULL;
|
||||
|
||||
if (!declared_name || !cursor_name)
|
||||
return;
|
||||
|
||||
/* Find the declared node by declared name */
|
||||
p = ecpg_find_declared_statement(declared_name);
|
||||
if (p)
|
||||
{
|
||||
if (p->cursor_name)
|
||||
ecpg_free(p->cursor_name);
|
||||
p->cursor_name = ecpg_strdup(cursor_name, lineno);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Find and return the connection name referred by the declared name
|
||||
* Input: declared_name -- the name declared in the DECLARE STATEMENT
|
||||
* Return: Found -- The connection name
|
||||
* Not found -- NULL
|
||||
*/
|
||||
char *
|
||||
ecpg_get_con_name_by_declared_name(const char *declared_name)
|
||||
{
|
||||
struct declared_statement *p;
|
||||
|
||||
p = ecpg_find_declared_statement(declared_name);
|
||||
if (p)
|
||||
return p->connection_name;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the connection name by referring the declared statements
|
||||
* cursors by using the provided cursor name
|
||||
* Input: cursor_name -- the cursor name
|
||||
* Return: Found -- The connection name
|
||||
* Not found -- NULL
|
||||
*/
|
||||
const char *
|
||||
ecpg_get_con_name_by_cursor_name(const char *cursor_name)
|
||||
{
|
||||
struct declared_statement *p;
|
||||
|
||||
if (cursor_name == NULL)
|
||||
return NULL;
|
||||
|
||||
p = g_declared_list;
|
||||
while (p)
|
||||
{
|
||||
/* Search the cursor name in the declared list */
|
||||
if (p->cursor_name && (strcmp(p->cursor_name, cursor_name) == 0))
|
||||
return p->connection_name;
|
||||
|
||||
p = p->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Release the declare node from the g_declared_list which refers the connection_name
|
||||
* Input: connection_name -- connection name
|
||||
*/
|
||||
void
|
||||
ecpg_release_declared_statement(const char *connection_name)
|
||||
{
|
||||
struct declared_statement *cur = NULL;
|
||||
struct declared_statement *prev = NULL;
|
||||
|
||||
if (connection_name == NULL)
|
||||
return;
|
||||
|
||||
cur = g_declared_list;
|
||||
while (cur)
|
||||
{
|
||||
if (strcmp(cur->connection_name, connection_name) == 0)
|
||||
{
|
||||
/* If find then release the declared node from the list */
|
||||
if (prev)
|
||||
prev->next = cur->next;
|
||||
else
|
||||
g_declared_list = cur->next;
|
||||
|
||||
ecpg_log("ecpg_release_declared_statement: declared name \"%s\" is released\n", cur->name);
|
||||
|
||||
ecpg_free(cur->name);
|
||||
ecpg_free(cur->connection_name);
|
||||
ecpg_free(cur->cursor_name);
|
||||
ecpg_free(cur);
|
||||
|
||||
/*
|
||||
* One connection can be used by multiple declared name, so no
|
||||
* break here
|
||||
*/
|
||||
}
|
||||
else
|
||||
prev = cur;
|
||||
|
||||
if (prev)
|
||||
cur = prev->next;
|
||||
else
|
||||
cur = g_declared_list;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user