From: Michael Meskes <meskes@topsystem.de>
+ + Wed May 6 16:09:45 CEST 1998 + + - Some more cleanups in the library. + + Thu May 7 12:34:28 CEST 1998 + + - Made CONNECT and DISCONNECT statement more SQL3 compliant. + - Changed the API for the ECPGconnect function to be able to handle + hostnames and ports + + Fri May 8 13:54:45 CEST 1998 + - More changes to the parser. The connect statement now allows + ORACLE style logins. + - db-name is accepted in two ways: + - <dbname>[@<server>][:<port>] + - esql:postgresql://<server>[:<port>][/<dbname>] + + Mon May 11 10:28:37 CEST 1998 + + - Added '? options' to connect call. + - Also allow USING as keyword for the password + + Thu May 14 15:09:58 CEST 1998 + + - Changed preproc.y and pgc.l according to the parser changes in the + backend. + + Fri May 15 09:55:21 CEST 1998 + + - Added connection_name handling + + + Mon May 18 10:33:58 CEST 1998 + + - Fixed some more bugs + - Set version to 2.3.1 + - Set library version to 2.2
This commit is contained in:
parent
d1c5021c67
commit
ef567413d2
@ -189,3 +189,42 @@ Wed May 6 11:42:48 CEST 1998
|
|||||||
an example)
|
an example)
|
||||||
- Set version to 2.3.0
|
- Set version to 2.3.0
|
||||||
- Set library version to 2.1
|
- Set library version to 2.1
|
||||||
|
|
||||||
|
Wed May 6 16:09:45 CEST 1998
|
||||||
|
|
||||||
|
- Some more cleanups in the library.
|
||||||
|
|
||||||
|
Thu May 7 12:34:28 CEST 1998
|
||||||
|
|
||||||
|
- Made CONNECT and DISCONNECT statement more SQL3 compliant.
|
||||||
|
- Changed the API for the ECPGconnect function to be able to handle
|
||||||
|
hostnames and ports
|
||||||
|
|
||||||
|
Fri May 8 13:54:45 CEST 1998
|
||||||
|
- More changes to the parser. The connect statement now allows
|
||||||
|
ORACLE style logins.
|
||||||
|
- db-name is accepted in two ways:
|
||||||
|
- <dbname>[@<server>][:<port>]
|
||||||
|
- esql:postgresql://<server>[:<port>][/<dbname>]
|
||||||
|
|
||||||
|
Mon May 11 10:28:37 CEST 1998
|
||||||
|
|
||||||
|
- Added '? options' to connect call.
|
||||||
|
- Also allow USING as keyword for the password
|
||||||
|
|
||||||
|
Thu May 14 15:09:58 CEST 1998
|
||||||
|
|
||||||
|
- Changed preproc.y and pgc.l according to the parser changes in the
|
||||||
|
backend.
|
||||||
|
|
||||||
|
Fri May 15 09:55:21 CEST 1998
|
||||||
|
|
||||||
|
- Added connection_name handling
|
||||||
|
|
||||||
|
|
||||||
|
Mon May 18 10:33:58 CEST 1998
|
||||||
|
|
||||||
|
- Fixed some more bugs
|
||||||
|
- Set version to 2.3.1
|
||||||
|
- Set library version to 2.2
|
||||||
|
|
||||||
|
@ -1,22 +1,32 @@
|
|||||||
#ifndef _ECPG_ERROR_H
|
#ifndef _ECPG_ERROR_H
|
||||||
#define _ECPG_ERROR_H
|
#define _ECPG_ERROR_H
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
/* This is a list of all error codes the embedded SQL program can return */
|
/* This is a list of all error codes the embedded SQL program can return */
|
||||||
#define ECPG_NO_ERROR 0
|
#define ECPG_NO_ERROR 0
|
||||||
#define ECPG_NOT_FOUND 100
|
#define ECPG_NOT_FOUND 100
|
||||||
|
|
||||||
#define ECPG_PGSQL -1
|
/* system error codes returned by ecpglib get the correct number,
|
||||||
#define ECPG_UNSUPPORTED -2
|
* but are made negative
|
||||||
#define ECPG_TOO_MANY_ARGUMENTS -3
|
*/
|
||||||
#define ECPG_TOO_FEW_ARGUMENTS -4
|
#define ECPG_OUT_OF_MEMORY -ENOMEM
|
||||||
#define ECPG_TRANS -5
|
|
||||||
#define ECPG_TOO_MANY_MATCHES -6
|
/* first we have a set of ecpg messages, they start at 200 */
|
||||||
#define ECPG_INT_FORMAT -7
|
#define ECPG_UNSUPPORTED -200
|
||||||
#define ECPG_UINT_FORMAT -8
|
#define ECPG_TOO_MANY_ARGUMENTS -201
|
||||||
#define ECPG_FLOAT_FORMAT -9
|
#define ECPG_TOO_FEW_ARGUMENTS -202
|
||||||
#define ECPG_CONVERT_BOOL -10
|
#define ECPG_TOO_MANY_MATCHES -203
|
||||||
#define ECPG_EMPTY -11
|
#define ECPG_INT_FORMAT -204
|
||||||
#define ECPG_CONNECT -12
|
#define ECPG_UINT_FORMAT -205
|
||||||
#define ECPG_DISCONNECT -13
|
#define ECPG_FLOAT_FORMAT -206
|
||||||
|
#define ECPG_CONVERT_BOOL -207
|
||||||
|
#define ECPG_EMPTY -208
|
||||||
|
#define ECPG_NO_CONN -209
|
||||||
|
|
||||||
|
/* finally the backend error messages, they start at 300 */
|
||||||
|
#define ECPG_PGSQL -300
|
||||||
|
#define ECPG_TRANS -301
|
||||||
|
#define ECPG_CONNECT -302
|
||||||
|
|
||||||
#endif /* !_ECPG_ERROR_H */
|
#endif /* !_ECPG_ERROR_H */
|
||||||
|
@ -5,11 +5,11 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void ECPGdebug(int, FILE *);
|
void ECPGdebug(int, FILE *);
|
||||||
bool ECPGconnect(const char *);
|
bool ECPGsetconn(int, const char *);
|
||||||
|
bool ECPGconnect(int, const char *, const char *, const char *, const char *);
|
||||||
bool ECPGdo(int, char *,...);
|
bool ECPGdo(int, char *,...);
|
||||||
bool ECPGtrans(int, const char *);
|
bool ECPGtrans(int, const char *);
|
||||||
bool ECPGfinish(void);
|
bool ECPGdisconnect(int, const char *);
|
||||||
bool ECPGdisconnect(const char *);
|
|
||||||
|
|
||||||
void ECPGlog(const char *format,...);
|
void ECPGlog(const char *format,...);
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ include $(SRCDIR)/Makefile.global
|
|||||||
PQ_INCLUDE=-I$(SRCDIR)/interfaces/libpq
|
PQ_INCLUDE=-I$(SRCDIR)/interfaces/libpq
|
||||||
|
|
||||||
SO_MAJOR_VERSION=2
|
SO_MAJOR_VERSION=2
|
||||||
SO_MINOR_VERSION=1
|
SO_MINOR_VERSION=2
|
||||||
|
|
||||||
PORTNAME=@PORTNAME@
|
PORTNAME=@PORTNAME@
|
||||||
|
|
||||||
|
@ -26,7 +26,13 @@
|
|||||||
|
|
||||||
extern int no_auto_trans;
|
extern int no_auto_trans;
|
||||||
|
|
||||||
static PGconn *simple_connection = NULL;
|
static struct connection
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
PGconn *connection;
|
||||||
|
struct connection *next;
|
||||||
|
} *all_connections = NULL, *actual_connection = NULL;
|
||||||
|
|
||||||
static int simple_debug = 0;
|
static int simple_debug = 0;
|
||||||
static FILE *debugstream = NULL;
|
static FILE *debugstream = NULL;
|
||||||
static int committed = true;
|
static int committed = true;
|
||||||
@ -54,6 +60,9 @@ quote_postgres(char *arg)
|
|||||||
int i,
|
int i,
|
||||||
ri;
|
ri;
|
||||||
|
|
||||||
|
if (!res)
|
||||||
|
return(res);
|
||||||
|
|
||||||
for (i = 0, ri = 0; arg[i]; i++, ri++)
|
for (i = 0, ri = 0; arg[i]; i++, ri++)
|
||||||
{
|
{
|
||||||
switch (arg[i])
|
switch (arg[i])
|
||||||
@ -73,6 +82,40 @@ quote_postgres(char *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
ECPGfinish(struct connection *act)
|
||||||
|
{
|
||||||
|
if (act != NULL)
|
||||||
|
{
|
||||||
|
ECPGlog("ECPGfinish: finishing %s.\n", act->name);
|
||||||
|
PQfinish(act->connection);
|
||||||
|
/* remove act from the list */
|
||||||
|
if (act == all_connections)
|
||||||
|
{
|
||||||
|
all_connections = act->next;
|
||||||
|
free(act->name);
|
||||||
|
free(act);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct connection *con;
|
||||||
|
|
||||||
|
for (con = all_connections; con->next && con->next != act; con = con->next);
|
||||||
|
if (con->next)
|
||||||
|
{
|
||||||
|
con->next = act->next;
|
||||||
|
free(act->name);
|
||||||
|
free(act);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actual_connection == act)
|
||||||
|
actual_connection = all_connections;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ECPGlog("ECPGfinish: called an extra time.\n");
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ECPGdo(int lineno, char *query,...)
|
ECPGdo(int lineno, char *query,...)
|
||||||
{
|
{
|
||||||
@ -195,14 +238,40 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
{
|
{
|
||||||
/* set slen to string length if type is char * */
|
/* set slen to string length if type is char * */
|
||||||
int slen = (varcharsize == 0) ? strlen((char *) value) : varcharsize;
|
int slen = (varcharsize == 0) ? strlen((char *) value) : varcharsize;
|
||||||
|
char * tmp;
|
||||||
|
|
||||||
newcopy = (char *) malloc(slen + 1);
|
newcopy = (char *) malloc(slen + 1);
|
||||||
|
if (!newcopy)
|
||||||
|
{
|
||||||
|
ECPGfinish(actual_connection);
|
||||||
|
ECPGlog("out of memory\n");
|
||||||
|
register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
strncpy(newcopy, (char *) value, slen);
|
strncpy(newcopy, (char *) value, slen);
|
||||||
newcopy[slen] = '\0';
|
newcopy[slen] = '\0';
|
||||||
|
|
||||||
mallocedval = (char *) malloc(2 * strlen(newcopy) + 3);
|
mallocedval = (char *) malloc(2 * strlen(newcopy) + 3);
|
||||||
|
if (!mallocedval)
|
||||||
|
{
|
||||||
|
ECPGfinish(actual_connection);
|
||||||
|
ECPGlog("out of memory\n");
|
||||||
|
register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
strcpy(mallocedval, "'");
|
strcpy(mallocedval, "'");
|
||||||
strcat(mallocedval, quote_postgres(newcopy));
|
tmp = quote_postgres(newcopy);
|
||||||
|
if (!tmp)
|
||||||
|
{
|
||||||
|
ECPGfinish(actual_connection);
|
||||||
|
ECPGlog("out of memory\n");
|
||||||
|
register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcat(mallocedval, tmp);
|
||||||
strcat(mallocedval, "'");
|
strcat(mallocedval, "'");
|
||||||
|
|
||||||
free(newcopy);
|
free(newcopy);
|
||||||
@ -215,14 +284,40 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
{
|
{
|
||||||
struct ECPGgeneric_varchar *var =
|
struct ECPGgeneric_varchar *var =
|
||||||
(struct ECPGgeneric_varchar *) value;
|
(struct ECPGgeneric_varchar *) value;
|
||||||
|
char *tmp;
|
||||||
|
|
||||||
newcopy = (char *) malloc(var->len + 1);
|
newcopy = (char *) malloc(var->len + 1);
|
||||||
|
if (!newcopy)
|
||||||
|
{
|
||||||
|
ECPGfinish(actual_connection);
|
||||||
|
ECPGlog("out of memory\n");
|
||||||
|
register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
strncpy(newcopy, var->arr, var->len);
|
strncpy(newcopy, var->arr, var->len);
|
||||||
newcopy[var->len] = '\0';
|
newcopy[var->len] = '\0';
|
||||||
|
|
||||||
mallocedval = (char *) malloc(2 * strlen(newcopy) + 3);
|
mallocedval = (char *) malloc(2 * strlen(newcopy) + 3);
|
||||||
|
if (!mallocedval)
|
||||||
|
{
|
||||||
|
ECPGfinish(actual_connection);
|
||||||
|
ECPGlog("out of memory\n");
|
||||||
|
register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
strcpy(mallocedval, "'");
|
strcpy(mallocedval, "'");
|
||||||
strcat(mallocedval, quote_postgres(newcopy));
|
tmp = quote_postgres(newcopy);
|
||||||
|
if (!tmp)
|
||||||
|
{
|
||||||
|
ECPGfinish(actual_connection);
|
||||||
|
ECPGlog("out of memory\n");
|
||||||
|
register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcat(mallocedval, tmp);
|
||||||
strcat(mallocedval, "'");
|
strcat(mallocedval, "'");
|
||||||
|
|
||||||
free(newcopy);
|
free(newcopy);
|
||||||
@ -249,6 +344,14 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
newcopy = (char *) malloc(strlen(copiedquery)
|
newcopy = (char *) malloc(strlen(copiedquery)
|
||||||
+ strlen(tobeinserted)
|
+ strlen(tobeinserted)
|
||||||
+ 1);
|
+ 1);
|
||||||
|
if (!newcopy)
|
||||||
|
{
|
||||||
|
ECPGfinish(actual_connection);
|
||||||
|
ECPGlog("out of memory\n");
|
||||||
|
register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
strcpy(newcopy, copiedquery);
|
strcpy(newcopy, copiedquery);
|
||||||
if ((p = strstr(newcopy, ";;")) == NULL)
|
if ((p = strstr(newcopy, ";;")) == NULL)
|
||||||
{
|
{
|
||||||
@ -301,7 +404,7 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
|
|
||||||
if (committed && !no_auto_trans)
|
if (committed && !no_auto_trans)
|
||||||
{
|
{
|
||||||
if ((results = PQexec(simple_connection, "begin transaction")) == NULL)
|
if ((results = PQexec(actual_connection->connection, "begin transaction")) == NULL)
|
||||||
{
|
{
|
||||||
register_error(ECPG_TRANS, "Error starting transaction line %d.", lineno);
|
register_error(ECPG_TRANS, "Error starting transaction line %d.", lineno);
|
||||||
return false;
|
return false;
|
||||||
@ -311,15 +414,15 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ECPGlog("ECPGdo line %d: QUERY: %s\n", lineno, copiedquery);
|
ECPGlog("ECPGdo line %d: QUERY: %s\n", lineno, copiedquery);
|
||||||
results = PQexec(simple_connection, copiedquery);
|
results = PQexec(actual_connection->connection, copiedquery);
|
||||||
free(copiedquery);
|
free(copiedquery);
|
||||||
|
|
||||||
if (results == NULL)
|
if (results == NULL)
|
||||||
{
|
{
|
||||||
ECPGlog("ECPGdo line %d: error: %s", lineno,
|
ECPGlog("ECPGdo line %d: error: %s", lineno,
|
||||||
PQerrorMessage(simple_connection));
|
PQerrorMessage(actual_connection->connection));
|
||||||
register_error(ECPG_PGSQL, "Postgres error: %s line %d.",
|
register_error(ECPG_PGSQL, "Postgres error: %s line %d.",
|
||||||
PQerrorMessage(simple_connection), lineno);
|
PQerrorMessage(actual_connection->connection), lineno);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -644,9 +747,9 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
case PGRES_FATAL_ERROR:
|
case PGRES_FATAL_ERROR:
|
||||||
case PGRES_BAD_RESPONSE:
|
case PGRES_BAD_RESPONSE:
|
||||||
ECPGlog("ECPGdo line %d: Error: %s",
|
ECPGlog("ECPGdo line %d: Error: %s",
|
||||||
lineno, PQerrorMessage(simple_connection));
|
lineno, PQerrorMessage(actual_connection->connection));
|
||||||
register_error(ECPG_PGSQL, "Error: %s line %d.",
|
register_error(ECPG_PGSQL, "Error: %s line %d.",
|
||||||
PQerrorMessage(simple_connection), lineno);
|
PQerrorMessage(actual_connection->connection), lineno);
|
||||||
status = false;
|
status = false;
|
||||||
break;
|
break;
|
||||||
case PGRES_COPY_OUT:
|
case PGRES_COPY_OUT:
|
||||||
@ -667,7 +770,7 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* check for asynchronous returns */
|
/* check for asynchronous returns */
|
||||||
notify = PQnotifies(simple_connection);
|
notify = PQnotifies(actual_connection->connection);
|
||||||
if (notify)
|
if (notify)
|
||||||
{
|
{
|
||||||
ECPGlog("ECPGdo line %d: ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
|
ECPGlog("ECPGdo line %d: ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
|
||||||
@ -686,7 +789,7 @@ ECPGtrans(int lineno, const char * transaction)
|
|||||||
PGresult *res;
|
PGresult *res;
|
||||||
|
|
||||||
ECPGlog("ECPGtrans line %d action = %s\n", lineno, transaction);
|
ECPGlog("ECPGtrans line %d action = %s\n", lineno, transaction);
|
||||||
if ((res = PQexec(simple_connection, transaction)) == NULL)
|
if ((res = PQexec(actual_connection->connection, transaction)) == NULL)
|
||||||
{
|
{
|
||||||
register_error(ECPG_TRANS, "Error in transaction processing line %d.", lineno);
|
register_error(ECPG_TRANS, "Error in transaction processing line %d.", lineno);
|
||||||
return (FALSE);
|
return (FALSE);
|
||||||
@ -698,59 +801,101 @@ ECPGtrans(int lineno, const char * transaction)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ECPGsetdb(PGconn *newcon)
|
ECPGsetconn(int lineno, const char *connection_name)
|
||||||
{
|
{
|
||||||
ECPGfinish();
|
struct connection *con = all_connections;
|
||||||
simple_connection = newcon;
|
|
||||||
return true;
|
for (; con && strcmp(connection_name, con->name) == 0; con=con->next);
|
||||||
|
if (con)
|
||||||
|
{
|
||||||
|
actual_connection = con;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
register_error(ECPG_NO_CONN, "No such connection %s in line %d", connection_name, lineno);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ECPGconnect(const char *dbname)
|
ECPGconnect(int lineno, const char *dbname, const char *user, const char *passwd, const char * connection_name)
|
||||||
{
|
{
|
||||||
char *name = strdup(dbname);
|
struct connection *this = malloc(sizeof(struct connection));
|
||||||
|
|
||||||
ECPGlog("ECPGconnect: opening database %s\n", name);
|
if (!this)
|
||||||
|
{
|
||||||
|
ECPGlog("out of memory\n");
|
||||||
|
register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dbname == NULL && connection_name == NULL)
|
||||||
|
connection_name = "DEFAULT";
|
||||||
|
|
||||||
|
/* add connection to our list */
|
||||||
|
if (connection_name != NULL)
|
||||||
|
this->name = strdup(connection_name);
|
||||||
|
else
|
||||||
|
this->name = strdup(dbname);
|
||||||
|
|
||||||
|
if (all_connections == NULL)
|
||||||
|
this->next = NULL;
|
||||||
|
else
|
||||||
|
this->next = all_connections;
|
||||||
|
|
||||||
|
actual_connection = all_connections = this;
|
||||||
|
|
||||||
|
ECPGlog("ECPGconnect: opening database %s %s%s\n", dbname ? dbname : "NULL", user ? "for user ": "", user ? user : "");
|
||||||
|
|
||||||
sqlca.sqlcode = 0;
|
sqlca.sqlcode = 0;
|
||||||
|
|
||||||
ECPGsetdb(PQsetdb(NULL, NULL, NULL, NULL, name));
|
this->connection = PQsetdbLogin(NULL, NULL, NULL, NULL, dbname, user, passwd);
|
||||||
|
|
||||||
free(name);
|
if (PQstatus(this->connection) == CONNECTION_BAD)
|
||||||
name = NULL;
|
|
||||||
|
|
||||||
if (PQstatus(simple_connection) == CONNECTION_BAD)
|
|
||||||
{
|
{
|
||||||
ECPGfinish();
|
ECPGfinish(this);
|
||||||
ECPGlog("connect: could not open database %s\n", dbname);
|
ECPGlog("connect: could not open database %s %s%s in line %d\n", dbname ? dbname : "NULL", user ? "for user ": "", user ? user : "", lineno);
|
||||||
register_error(ECPG_CONNECT, "connect: could not open database %s.", dbname);
|
|
||||||
|
register_error(ECPG_CONNECT, "connect: could not open database %s.", dbname ? dbname : "NULL");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ECPGdisconnect(const char *dbname)
|
ECPGdisconnect(int lineno, const char *connection_name)
|
||||||
{
|
{
|
||||||
if (strlen(dbname) > 0 && strcmp(PQdb(simple_connection), dbname) != 0)
|
struct connection *con;
|
||||||
{
|
|
||||||
ECPGlog("disconnect: not connected to database %s\n", dbname);
|
|
||||||
register_error(ECPG_DISCONNECT, "disconnect: not connected to database %s.", dbname);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return ECPGfinish();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
if (strcmp(connection_name, "CURRENT") == 0)
|
||||||
ECPGfinish(void)
|
ECPGfinish(actual_connection);
|
||||||
{
|
else if (strcmp(connection_name, "ALL") == 0)
|
||||||
if (simple_connection != NULL)
|
|
||||||
{
|
{
|
||||||
ECPGlog("ECPGfinish: finishing.\n");
|
for (con = all_connections; con;)
|
||||||
PQfinish(simple_connection);
|
{
|
||||||
|
struct connection *f = con;
|
||||||
|
|
||||||
|
con = con->next;
|
||||||
|
ECPGfinish(f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ECPGlog("ECPGfinish: called an extra time.\n");
|
{
|
||||||
|
for (con = all_connections; con && strcmp(con->name, connection_name);con = con->next);
|
||||||
|
if (con == NULL)
|
||||||
|
{
|
||||||
|
ECPGlog("disconnect: not connected to connection %s\n", connection_name);
|
||||||
|
register_error(ECPG_NO_CONN, "No such connection %s in line %d", connection_name, lineno);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ECPGfinish(con);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -771,6 +916,9 @@ ECPGlog(const char *format,...)
|
|||||||
{
|
{
|
||||||
char *f = (char *) malloc(strlen(format) + 100);
|
char *f = (char *) malloc(strlen(format) + 100);
|
||||||
|
|
||||||
|
if (!f)
|
||||||
|
return;
|
||||||
|
|
||||||
sprintf(f, "[%d]: %s", getpid(), format);
|
sprintf(f, "[%d]: %s", getpid(), format);
|
||||||
|
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
|
@ -3,7 +3,7 @@ include $(SRCDIR)/Makefile.global
|
|||||||
|
|
||||||
MAJOR_VERSION=2
|
MAJOR_VERSION=2
|
||||||
MINOR_VERSION=3
|
MINOR_VERSION=3
|
||||||
PATCHLEVEL=0
|
PATCHLEVEL=1
|
||||||
|
|
||||||
CFLAGS+=-I../include -DMAJOR_VERSION=$(MAJOR_VERSION) \
|
CFLAGS+=-I../include -DMAJOR_VERSION=$(MAJOR_VERSION) \
|
||||||
-DMINOR_VERSION=$(MINOR_VERSION) -DPATCHLEVEL=$(PATCHLEVEL) \
|
-DMINOR_VERSION=$(MINOR_VERSION) -DPATCHLEVEL=$(PATCHLEVEL) \
|
||||||
|
@ -24,12 +24,14 @@ static ScanKeyword ScanKeywords[] = {
|
|||||||
{"break", SQL_BREAK},
|
{"break", SQL_BREAK},
|
||||||
{"call", SQL_CALL},
|
{"call", SQL_CALL},
|
||||||
{"connect", SQL_CONNECT},
|
{"connect", SQL_CONNECT},
|
||||||
|
{"connection", SQL_CONNECTION},
|
||||||
{"continue", SQL_CONTINUE},
|
{"continue", SQL_CONTINUE},
|
||||||
{"disconnect", SQL_DISCONNECT},
|
{"disconnect", SQL_DISCONNECT},
|
||||||
{"found", SQL_FOUND},
|
{"found", SQL_FOUND},
|
||||||
{"go", SQL_GO},
|
{"go", SQL_GO},
|
||||||
{"goto", SQL_GOTO},
|
{"goto", SQL_GOTO},
|
||||||
{"immediate", SQL_IMMEDIATE},
|
{"identified", SQL_IDENTIFIED},
|
||||||
|
{"immediate", SQL_IMMEDIATE},
|
||||||
{"indicator", SQL_INDICATOR},
|
{"indicator", SQL_INDICATOR},
|
||||||
{"open", SQL_OPEN},
|
{"open", SQL_OPEN},
|
||||||
{"release", SQL_RELEASE},
|
{"release", SQL_RELEASE},
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "parser/keywords.h"
|
#include "parser/keywords.h"
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
/* variables */
|
/* variables */
|
||||||
|
|
||||||
@ -47,7 +48,8 @@ extern void yyerror(char *);
|
|||||||
/* return codes */
|
/* return codes */
|
||||||
|
|
||||||
#define OK 0
|
#define OK 0
|
||||||
#define NO_INCLUDE_FILE 1
|
#define PARSE_ERROR -1
|
||||||
#define PARSE_ERROR 2
|
#define ILLEGAL_OPTION -2
|
||||||
#define OUT_OF_MEMORY 3
|
|
||||||
#define ILLEGAL_OPTION 4
|
#define NO_INCLUDE_FILE ENOENT
|
||||||
|
#define OUT_OF_MEMORY ENOMEM
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/keywords.c,v 1.1 1998/04/21 13:23:06 scrappy Exp $
|
* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/keywords.c,v 1.2 1998/05/18 16:05:00 scrappy Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -189,6 +189,8 @@ static ScanKeyword ScanKeywords[] = {
|
|||||||
{"substring", SUBSTRING},
|
{"substring", SUBSTRING},
|
||||||
{"table", TABLE},
|
{"table", TABLE},
|
||||||
{"time", TIME},
|
{"time", TIME},
|
||||||
|
{"timezone_hour", TIMEZONE_HOUR},
|
||||||
|
{"timezone_minute", TIMEZONE_MINUTE},
|
||||||
{"to", TO},
|
{"to", TO},
|
||||||
{"trailing", TRAILING},
|
{"trailing", TRAILING},
|
||||||
{"transaction", TRANSACTION},
|
{"transaction", TRANSACTION},
|
||||||
|
@ -139,12 +139,13 @@ self [,()\[\].$\:\+\-\*\/\<\>\=\|]
|
|||||||
op_and_self [\~\!\@\#\%\^\&\|\`\?\$\:\+\-\*\/\<\>\=]
|
op_and_self [\~\!\@\#\%\^\&\|\`\?\$\:\+\-\*\/\<\>\=]
|
||||||
operator {op_and_self}+
|
operator {op_and_self}+
|
||||||
|
|
||||||
xminteger {integer}/-
|
|
||||||
xmreal {real}/{space}*-{digit}
|
|
||||||
xmstop -
|
xmstop -
|
||||||
|
|
||||||
integer -?{digit}+
|
integer [\-]?{digit}+
|
||||||
real -?{digit}+\.{digit}+([Ee][-+]?{digit}+)?
|
/*
|
||||||
|
real [\-]?{digit}+\.{digit}+([Ee][-+]?{digit}+)?
|
||||||
|
*/
|
||||||
|
real [\-]?(((({digit}*\.{digit}+)|({digit}+\.{digit}*))([Ee][-+]?{digit}+)?)|({digit}+[Ee][-+]?{digit}+))
|
||||||
|
|
||||||
param \${integer}
|
param \${integer}
|
||||||
|
|
||||||
@ -309,7 +310,8 @@ before_comment);
|
|||||||
|
|
||||||
<SQL>{typecast} { return TYPECAST; }
|
<SQL>{typecast} { return TYPECAST; }
|
||||||
|
|
||||||
<SQL>{self}/-[\.0-9] {
|
<SQL>{self}/{space}*-[\.0-9] {
|
||||||
|
BEGIN(xm);
|
||||||
return (yytext[0]);
|
return (yytext[0]);
|
||||||
}
|
}
|
||||||
<SQL>{self} { return (yytext[0]); }
|
<SQL>{self} { return (yytext[0]); }
|
||||||
|
@ -70,11 +70,13 @@ whenever_action(int mode)
|
|||||||
{
|
{
|
||||||
if (mode == 1 && when_nf.code != W_NOTHING)
|
if (mode == 1 && when_nf.code != W_NOTHING)
|
||||||
{
|
{
|
||||||
|
output_line_number();
|
||||||
fprintf(yyout, "\nif (sqlca.sqlcode == ECPG_NOT_FOUND) ");
|
fprintf(yyout, "\nif (sqlca.sqlcode == ECPG_NOT_FOUND) ");
|
||||||
print_action(&when_nf);
|
print_action(&when_nf);
|
||||||
}
|
}
|
||||||
if (when_error.code != W_NOTHING)
|
if (when_error.code != W_NOTHING)
|
||||||
{
|
{
|
||||||
|
output_line_number();
|
||||||
fprintf(yyout, "\nif (sqlca.sqlcode < 0) ");
|
fprintf(yyout, "\nif (sqlca.sqlcode < 0) ");
|
||||||
print_action(&when_error);
|
print_action(&when_error);
|
||||||
}
|
}
|
||||||
@ -112,7 +114,7 @@ static struct variable * find_variable(char * name);
|
|||||||
static struct variable *
|
static struct variable *
|
||||||
find_struct_member(char *name, char *str, struct ECPGstruct_member *members)
|
find_struct_member(char *name, char *str, struct ECPGstruct_member *members)
|
||||||
{
|
{
|
||||||
char *next = strpbrk(++str, ".-"), c = '\0';
|
char *next = strchr(++str, '.'), c = '\0';
|
||||||
|
|
||||||
if (next != NULL)
|
if (next != NULL)
|
||||||
{
|
{
|
||||||
@ -129,6 +131,8 @@ find_struct_member(char *name, char *str, struct ECPGstruct_member *members)
|
|||||||
/* found the end */
|
/* found the end */
|
||||||
switch (members->typ->typ)
|
switch (members->typ->typ)
|
||||||
{
|
{
|
||||||
|
case ECPGt_array:
|
||||||
|
return(new_variable(name, ECPGmake_array_type(members->typ->u.element, members->typ->size)));
|
||||||
case ECPGt_struct:
|
case ECPGt_struct:
|
||||||
return(new_variable(name, ECPGmake_struct_type(members->typ->u.members)));
|
return(new_variable(name, ECPGmake_struct_type(members->typ->u.members)));
|
||||||
default:
|
default:
|
||||||
@ -138,8 +142,12 @@ find_struct_member(char *name, char *str, struct ECPGstruct_member *members)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
*next = c;
|
*next = c;
|
||||||
if (c == '-') next++;
|
if (c == '-')
|
||||||
return(find_struct_member(name, next, members->typ->u.members));
|
{
|
||||||
|
next++;
|
||||||
|
return(find_struct_member(name, next, members->typ->u.element->u.members));
|
||||||
|
}
|
||||||
|
else return(find_struct_member(name, next, members->typ->u.members));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -159,9 +167,12 @@ find_struct(char * name, char *next)
|
|||||||
|
|
||||||
/* restore the name, we will need it later on */
|
/* restore the name, we will need it later on */
|
||||||
*next = c;
|
*next = c;
|
||||||
if (*next == '-') next++;
|
if (c == '-')
|
||||||
|
{
|
||||||
return (find_struct_member(name, next, p->type->u.members));
|
next++;
|
||||||
|
return (find_struct_member(name, next, p->type->u.element->u.members));
|
||||||
|
}
|
||||||
|
else return (find_struct_member(name, next, p->type->u.members));
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct variable *
|
static struct variable *
|
||||||
@ -178,12 +189,20 @@ find_simple(char * name)
|
|||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Note that this function will end the program in case of an unknown */
|
||||||
|
/* variable */
|
||||||
static struct variable *
|
static struct variable *
|
||||||
find_variable(char * name)
|
find_variable(char * name)
|
||||||
{
|
{
|
||||||
char * next;
|
char * next;
|
||||||
struct variable * p =
|
struct variable * p;
|
||||||
((next = strpbrk(name, ".-")) != NULL) ? find_struct(name, next) : find_simple(name);
|
|
||||||
|
if ((next = strchr(name, '.')) != NULL)
|
||||||
|
p = find_struct(name, next);
|
||||||
|
else if ((next = strstr(name, "->")) != NULL)
|
||||||
|
p = find_struct(name, next);
|
||||||
|
else
|
||||||
|
p = find_simple(name);
|
||||||
|
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
{
|
{
|
||||||
@ -231,7 +250,6 @@ struct arguments {
|
|||||||
struct arguments * next;
|
struct arguments * next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static struct arguments * argsinsert = NULL;
|
static struct arguments * argsinsert = NULL;
|
||||||
static struct arguments * argsresult = NULL;
|
static struct arguments * argsresult = NULL;
|
||||||
|
|
||||||
@ -495,8 +513,9 @@ output_statement(char * stmt, int mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* special embedded SQL token */
|
/* special embedded SQL token */
|
||||||
%token SQL_BREAK SQL_CALL SQL_CONNECT SQL_CONTINUE SQL_DISCONNECT SQL_FOUND SQL_GO SQL_GOTO
|
%token SQL_BREAK SQL_CALL SQL_CONNECT SQL_CONNECTION SQL_CONTINUE
|
||||||
%token SQL_IMMEDIATE SQL_INDICATOR SQL_OPEN SQL_RELEASE
|
%token SQL_DISCONNECT SQL_FOUND SQL_GO SQL_GOTO
|
||||||
|
%token SQL_IDENTIFIED SQL_IMMEDIATE SQL_INDICATOR SQL_OPEN SQL_RELEASE
|
||||||
%token SQL_SECTION SQL_SEMI SQL_SQLERROR SQL_SQLPRINT SQL_START
|
%token SQL_SECTION SQL_SEMI SQL_SQLERROR SQL_SQLPRINT SQL_START
|
||||||
%token SQL_STOP SQL_WHENEVER
|
%token SQL_STOP SQL_WHENEVER
|
||||||
|
|
||||||
@ -527,8 +546,9 @@ output_statement(char * stmt, int mode)
|
|||||||
PARTIAL, POSITION, PRECISION, PRIMARY, PRIVILEGES, PROCEDURE, PUBLIC,
|
PARTIAL, POSITION, PRECISION, PRIMARY, PRIVILEGES, PROCEDURE, PUBLIC,
|
||||||
REFERENCES, REVOKE, RIGHT, ROLLBACK,
|
REFERENCES, REVOKE, RIGHT, ROLLBACK,
|
||||||
SECOND_P, SELECT, SET, SUBSTRING,
|
SECOND_P, SELECT, SET, SUBSTRING,
|
||||||
TABLE, TIME, TIMESTAMP, TO, TRAILING, TRANSACTION, TRIM,
|
TABLE, TIME, TIMESTAMP, TIMEZONE_HOUR, TIMEZONE_MINUTE,
|
||||||
UNION, UNIQUE, UPDATE, USING,
|
TO, TRAILING, TRANSACTION, TRIM,
|
||||||
|
UNION, UNIQUE, UPDATE, USER, USING,
|
||||||
VALUES, VARCHAR, VARYING, VIEW,
|
VALUES, VARCHAR, VARYING, VIEW,
|
||||||
WHERE, WITH, WORK, YEAR_P, ZONE
|
WHERE, WITH, WORK, YEAR_P, ZONE
|
||||||
|
|
||||||
@ -559,7 +579,7 @@ output_statement(char * stmt, int mode)
|
|||||||
*
|
*
|
||||||
* Todd A. Brandys
|
* Todd A. Brandys
|
||||||
*/
|
*/
|
||||||
%token USER, PASSWORD, CREATEDB, NOCREATEDB, CREATEUSER, NOCREATEUSER, VALID, UNTIL
|
%token PASSWORD, CREATEDB, NOCREATEDB, CREATEUSER, NOCREATEUSER, VALID, UNTIL
|
||||||
|
|
||||||
/* Special keywords, not in the query language - see the "lex" file */
|
/* Special keywords, not in the query language - see the "lex" file */
|
||||||
%token <str> IDENT SCONST Op CSTRING CVARIABLE
|
%token <str> IDENT SCONST Op CSTRING CVARIABLE
|
||||||
@ -620,7 +640,7 @@ output_statement(char * stmt, int mode)
|
|||||||
%type <str> sortby OptUseOp opt_inh_star relation_name_list name_list
|
%type <str> sortby OptUseOp opt_inh_star relation_name_list name_list
|
||||||
%type <str> group_clause groupby_list groupby having_clause from_clause
|
%type <str> group_clause groupby_list groupby having_clause from_clause
|
||||||
%type <str> from_list from_val join_expr join_outer join_spec join_list
|
%type <str> from_list from_val join_expr join_outer join_spec join_list
|
||||||
%type <str> join_using where_clause relation_expr
|
%type <str> join_using where_clause relation_expr row_op sub_type
|
||||||
%type <str> opt_column_list insert_rest InsertStmt
|
%type <str> opt_column_list insert_rest InsertStmt
|
||||||
%type <str> columnList DeleteStmt LockStmt UpdateStmt CursorStmt
|
%type <str> columnList DeleteStmt LockStmt UpdateStmt CursorStmt
|
||||||
%type <str> NotifyStmt columnElem copy_dirn OptimizableStmt
|
%type <str> NotifyStmt columnElem copy_dirn OptimizableStmt
|
||||||
@ -650,12 +670,16 @@ output_statement(char * stmt, int mode)
|
|||||||
%type <str> DestroydbStmt ClusterStmt grantee RevokeStmt
|
%type <str> DestroydbStmt ClusterStmt grantee RevokeStmt
|
||||||
%type <str> GrantStmt privileges operation_commalist operation
|
%type <str> GrantStmt privileges operation_commalist operation
|
||||||
|
|
||||||
%type <str> ECPGWhenever ECPGConnect db_name ECPGOpen open_opts
|
%type <str> ECPGWhenever ECPGConnect connection_target ECPGOpen open_opts
|
||||||
%type <str> indicator ECPGExecute c_expr variable_list dotext
|
%type <str> indicator ECPGExecute c_expr variable_list dotext
|
||||||
%type <str> storage_clause opt_initializer vartext c_anything blockstart
|
%type <str> storage_clause opt_initializer vartext c_anything blockstart
|
||||||
%type <str> blockend variable_list variable var_anything sql_anything
|
%type <str> blockend variable_list variable var_anything sql_anything
|
||||||
%type <str> opt_pointer ecpg_ident cvariable ECPGDisconnect dis_name
|
%type <str> opt_pointer ecpg_ident cvariable ECPGDisconnect dis_name
|
||||||
%type <str> stmt symbol opt_symbol ECPGRelease execstring
|
%type <str> stmt symbol opt_symbol ECPGRelease execstring server_name
|
||||||
|
%type <str> connection_object opt_server opt_port
|
||||||
|
%type <str> user_name opt_user char_variable ora_user ident
|
||||||
|
%type <str> db_prefix server opt_options opt_connection_name
|
||||||
|
%type <str> ECPGSetConnection
|
||||||
|
|
||||||
%type <type_enum> simple_type type struct_type
|
%type <type_enum> simple_type type struct_type
|
||||||
|
|
||||||
@ -721,12 +745,12 @@ stmt: AddAttrStmt { output_statement($1, 0); }
|
|||||||
| VariableShowStmt { output_statement($1, 0); }
|
| VariableShowStmt { output_statement($1, 0); }
|
||||||
| VariableResetStmt { output_statement($1, 0); }
|
| VariableResetStmt { output_statement($1, 0); }
|
||||||
| ECPGConnect {
|
| ECPGConnect {
|
||||||
fprintf(yyout, "ECPGconnect(\"%s\");", $1);
|
fprintf(yyout, "ECPGconnect(__LINE__, %s);", $1);
|
||||||
whenever_action(0);
|
whenever_action(0);
|
||||||
free($1);
|
free($1);
|
||||||
}
|
}
|
||||||
| ECPGDisconnect {
|
| ECPGDisconnect {
|
||||||
fprintf(yyout, "ECPGdisconnect(\"%s\");", $1);
|
fprintf(yyout, "ECPGdisconnect(__LINE__, \"%s\");", $1);
|
||||||
whenever_action(0);
|
whenever_action(0);
|
||||||
free($1);
|
free($1);
|
||||||
}
|
}
|
||||||
@ -737,6 +761,11 @@ stmt: AddAttrStmt { output_statement($1, 0); }
|
|||||||
}
|
}
|
||||||
| ECPGOpen { output_statement($1, 0); }
|
| ECPGOpen { output_statement($1, 0); }
|
||||||
| ECPGRelease { /* output already done */ }
|
| ECPGRelease { /* output already done */ }
|
||||||
|
| ECPGSetConnection {
|
||||||
|
fprintf(yyout, "ECPGsetcon(__LINE__, %s);", $1);
|
||||||
|
whenever_action(0);
|
||||||
|
free($1);
|
||||||
|
}
|
||||||
| ECPGWhenever {
|
| ECPGWhenever {
|
||||||
fputs($1, yyout);
|
fputs($1, yyout);
|
||||||
output_line_number();
|
output_line_number();
|
||||||
@ -828,7 +857,7 @@ user_group_clause: IN GROUP user_group_list { $$ = cat2_str(make1_str("in group
|
|||||||
| /*EMPTY*/ { $$ = make1_str(""); }
|
| /*EMPTY*/ { $$ = make1_str(""); }
|
||||||
;
|
;
|
||||||
|
|
||||||
user_valid_clause: VALID UNTIL SCONST { $$ = cat2_str(make1_str("valid until"), $3);; }
|
user_valid_clause: VALID UNTIL Sconst { $$ = cat2_str(make1_str("valid until"), $3);; }
|
||||||
| /*EMPTY*/ { $$ = make1_str(""); }
|
| /*EMPTY*/ { $$ = make1_str(""); }
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -853,6 +882,7 @@ VariableSetStmt: SET ColId TO var_value
|
|||||||
{
|
{
|
||||||
$$ = cat2_str(make1_str("set time zone"), $4);
|
$$ = cat2_str(make1_str("set time zone"), $4);
|
||||||
}
|
}
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
var_value: Sconst { $$ = $1; }
|
var_value: Sconst { $$ = $1; }
|
||||||
@ -1136,7 +1166,9 @@ default_expr: AexprConst
|
|||||||
$$ = "current_timestamp";
|
$$ = "current_timestamp";
|
||||||
}
|
}
|
||||||
| CURRENT_USER
|
| CURRENT_USER
|
||||||
{ $$ = make1_str("current user"); }
|
{ $$ = make1_str("current_user"); }
|
||||||
|
| USER
|
||||||
|
{ $$ = make1_str("user"); }
|
||||||
;
|
;
|
||||||
|
|
||||||
/* ConstraintElem specifies constraint syntax which is not embedded into
|
/* ConstraintElem specifies constraint syntax which is not embedded into
|
||||||
@ -1459,7 +1491,7 @@ TriggerFuncArg: Iconst
|
|||||||
$$ = make_name();
|
$$ = make_name();
|
||||||
}
|
}
|
||||||
| Sconst { $$ = $1; }
|
| Sconst { $$ = $1; }
|
||||||
| ecpg_ident { $$ = $1; }
|
| ident { $$ = $1; }
|
||||||
;
|
;
|
||||||
|
|
||||||
DropTrigStmt: DROP TRIGGER name ON relation_name
|
DropTrigStmt: DROP TRIGGER name ON relation_name
|
||||||
@ -2434,8 +2466,10 @@ groupby: ColId
|
|||||||
|
|
||||||
having_clause: HAVING a_expr
|
having_clause: HAVING a_expr
|
||||||
{
|
{
|
||||||
|
#if FALSE
|
||||||
yyerror("HAVING clause not yet implemented");
|
yyerror("HAVING clause not yet implemented");
|
||||||
/* $$ = cat2_str(make1_str("having"), $2); use this line instead to enable HAVING */
|
#endif
|
||||||
|
$$ = cat2_str(make1_str("having"), $2);
|
||||||
}
|
}
|
||||||
| /*EMPTY*/ { $$ = make1_str(""); }
|
| /*EMPTY*/ { $$ = make1_str(""); }
|
||||||
;
|
;
|
||||||
@ -2610,7 +2644,7 @@ Generic: generic
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
generic: ecpg_ident { $$ = $1; }
|
generic: ident { $$ = $1; }
|
||||||
| TYPE_P { $$ = make1_str("type"); }
|
| TYPE_P { $$ = make1_str("type"); }
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -2724,7 +2758,7 @@ opt_decimal: '(' Iconst ',' Iconst ')'
|
|||||||
Character: character '(' Iconst ')'
|
Character: character '(' Iconst ')'
|
||||||
{
|
{
|
||||||
if (strncasecmp($1, "char", strlen("char")) && strncasecmp($1, "varchar", strlen("varchar")))
|
if (strncasecmp($1, "char", strlen("char")) && strncasecmp($1, "varchar", strlen("varchar")))
|
||||||
yyerror("parse error");
|
yyerror("internal parsing error; unrecognized character type");
|
||||||
if (atol($3) < 1) {
|
if (atol($3) < 1) {
|
||||||
sprintf(errortext, "length for '%s' type must be at least 1",$1);
|
sprintf(errortext, "length for '%s' type must be at least 1",$1);
|
||||||
yyerror(errortext);
|
yyerror(errortext);
|
||||||
@ -2749,10 +2783,9 @@ Character: character '(' Iconst ')'
|
|||||||
|
|
||||||
character: CHARACTER opt_varying opt_charset opt_collate
|
character: CHARACTER opt_varying opt_charset opt_collate
|
||||||
{
|
{
|
||||||
if (strlen($4) > 0) {
|
if (strlen($4) > 0)
|
||||||
sprintf(errortext, "COLLATE %s not yet implemented",$4);
|
fprintf(stderr, "COLLATE %s not yet implemented",$4);
|
||||||
yyerror(errortext);
|
|
||||||
}
|
|
||||||
$$ = cat4_str(make1_str("character"), $2, $3, $4);
|
$$ = cat4_str(make1_str("character"), $2, $3, $4);
|
||||||
}
|
}
|
||||||
| CHAR opt_varying { $$ = cat2_str(make1_str("char"), $2); }
|
| CHAR opt_varying { $$ = cat2_str(make1_str("char"), $2); }
|
||||||
@ -2809,6 +2842,7 @@ opt_interval: datetime { $$ = $1; }
|
|||||||
| DAY_P TO MINUTE_P { $$ = make1_str("day to minute"); }
|
| DAY_P TO MINUTE_P { $$ = make1_str("day to minute"); }
|
||||||
| DAY_P TO SECOND_P { $$ = make1_str("day to second"); }
|
| DAY_P TO SECOND_P { $$ = make1_str("day to second"); }
|
||||||
| HOUR_P TO MINUTE_P { $$ = make1_str("hour to minute"); }
|
| HOUR_P TO MINUTE_P { $$ = make1_str("hour to minute"); }
|
||||||
|
| MINUTE_P TO SECOND_P { $$ = make1_str("minute to second"); }
|
||||||
| HOUR_P TO SECOND_P { $$ = make1_str("hour to second"); }
|
| HOUR_P TO SECOND_P { $$ = make1_str("hour to second"); }
|
||||||
| /*EMPTY*/ { $$ = make1_str(""); }
|
| /*EMPTY*/ { $$ = make1_str(""); }
|
||||||
;
|
;
|
||||||
@ -2831,6 +2865,11 @@ a_expr_or_null: a_expr
|
|||||||
/* Expressions using row descriptors
|
/* Expressions using row descriptors
|
||||||
* Define row_descriptor to allow yacc to break the reduce/reduce conflict
|
* Define row_descriptor to allow yacc to break the reduce/reduce conflict
|
||||||
* with singleton expressions.
|
* with singleton expressions.
|
||||||
|
* Eliminated lots of code by defining row_op and sub_type clauses.
|
||||||
|
* However, can not consolidate EXPR_LINK case with others subselects
|
||||||
|
* due to shift/reduce conflict with the non-subselect clause (the parser
|
||||||
|
* would have to look ahead more than one token to resolve the conflict).
|
||||||
|
* - thomas 1998-05-09
|
||||||
*/
|
*/
|
||||||
row_expr: '(' row_descriptor ')' IN '(' SubSelect ')'
|
row_expr: '(' row_descriptor ')' IN '(' SubSelect ')'
|
||||||
{
|
{
|
||||||
@ -2840,134 +2879,18 @@ row_expr: '(' row_descriptor ')' IN '(' SubSelect ')'
|
|||||||
{
|
{
|
||||||
$$ = make5_str(make1_str("("), $2, make1_str(") not in ("), $7, make1_str(")"));
|
$$ = make5_str(make1_str("("), $2, make1_str(") not in ("), $7, make1_str(")"));
|
||||||
}
|
}
|
||||||
| '(' row_descriptor ')' Op '(' SubSelect ')'
|
| '(' row_descriptor ')' row_op sub_type '(' SubSelect ')'
|
||||||
|
{
|
||||||
|
$$ = make4_str(make5_str(make1_str("("), $2, make1_str(")"), $4, $5), make1_str("("), $7, make1_str(")"));
|
||||||
|
}
|
||||||
|
| '(' row_descriptor ')' row_op '(' SubSelect ')'
|
||||||
{
|
{
|
||||||
$$ = make3_str(make5_str(make1_str("("), $2, make1_str(")"), $4, make1_str("(")), $6, make1_str(")"));
|
$$ = make3_str(make5_str(make1_str("("), $2, make1_str(")"), $4, make1_str("(")), $6, make1_str(")"));
|
||||||
}
|
}
|
||||||
| '(' row_descriptor ')' '+' '(' SubSelect ')'
|
| '(' row_descriptor ')' row_op '(' row_descriptor ')'
|
||||||
{
|
|
||||||
$$ = make5_str(make1_str("("), $2, make1_str(")+("), $6, make1_str(")"));
|
|
||||||
}
|
|
||||||
| '(' row_descriptor ')' '-' '(' SubSelect ')'
|
|
||||||
{
|
|
||||||
$$ = make5_str(make1_str("("), $2, make1_str(")-("), $6, make1_str(")"));
|
|
||||||
}
|
|
||||||
| '(' row_descriptor ')' '/' '(' SubSelect ')'
|
|
||||||
{
|
|
||||||
$$ = make5_str(make1_str("("), $2, make1_str(")/("), $6, make1_str(")"));
|
|
||||||
}
|
|
||||||
| '(' row_descriptor ')' '*' '(' SubSelect ')'
|
|
||||||
{
|
|
||||||
$$ = make5_str(make1_str("("), $2, make1_str(")*("), $6, make1_str(")"));
|
|
||||||
}
|
|
||||||
| '(' row_descriptor ')' '<' '(' SubSelect ')'
|
|
||||||
{
|
|
||||||
$$ = make5_str(make1_str("("), $2, make1_str(")<("), $6, make1_str(")"));
|
|
||||||
}
|
|
||||||
| '(' row_descriptor ')' '>' '(' SubSelect ')'
|
|
||||||
{
|
|
||||||
$$ = make5_str(make1_str("("), $2, make1_str(")>("), $6, make1_str(")"));
|
|
||||||
}
|
|
||||||
| '(' row_descriptor ')' '=' '(' SubSelect ')'
|
|
||||||
{
|
|
||||||
$$ = make5_str(make1_str("("), $2, make1_str(")=("), $6, make1_str(")"));
|
|
||||||
}
|
|
||||||
| '(' row_descriptor ')' Op ANY '(' SubSelect ')'
|
|
||||||
{
|
|
||||||
$$ = cat3_str(make3_str(make1_str("("), $2, make1_str(")")), $4, make3_str(make1_str("any("), $7, make1_str(")")));
|
|
||||||
}
|
|
||||||
| '(' row_descriptor ')' '+' ANY '(' SubSelect ')'
|
|
||||||
{
|
|
||||||
$$ = make5_str(make1_str("("), $2, make1_str(")+any("), $7, make1_str(")"));
|
|
||||||
}
|
|
||||||
| '(' row_descriptor ')' '-' ANY '(' SubSelect ')'
|
|
||||||
{
|
|
||||||
$$ = make5_str(make1_str("("), $2, make1_str(")-any("), $7, make1_str(")"));
|
|
||||||
}
|
|
||||||
| '(' row_descriptor ')' '/' ANY '(' SubSelect ')'
|
|
||||||
{
|
|
||||||
$$ = make5_str(make1_str("("), $2, make1_str(")/any("), $7, make1_str(")"));
|
|
||||||
}
|
|
||||||
| '(' row_descriptor ')' '*' ANY '(' SubSelect ')'
|
|
||||||
{
|
|
||||||
$$ = make5_str(make1_str("("), $2, make1_str(")*any("), $7, make1_str(")"));
|
|
||||||
}
|
|
||||||
| '(' row_descriptor ')' '<' ANY '(' SubSelect ')'
|
|
||||||
{
|
|
||||||
$$ = make5_str(make1_str("("), $2, make1_str(")<any("), $7, make1_str(")"));
|
|
||||||
}
|
|
||||||
| '(' row_descriptor ')' '>' ANY '(' SubSelect ')'
|
|
||||||
{
|
|
||||||
$$ = make5_str(make1_str("("), $2, make1_str(")>any("), $7, make1_str(")"));
|
|
||||||
}
|
|
||||||
| '(' row_descriptor ')' '=' ANY '(' SubSelect ')'
|
|
||||||
{
|
|
||||||
$$ = make5_str(make1_str("("), $2, make1_str(")=any("), $7, make1_str(")"));
|
|
||||||
}
|
|
||||||
| '(' row_descriptor ')' Op ALL '(' SubSelect ')'
|
|
||||||
{
|
|
||||||
$$ = cat3_str(make3_str(make1_str("("), $2, make1_str(")")), $4, make3_str(make1_str("all("), $7, make1_str(")")));
|
|
||||||
}
|
|
||||||
| '(' row_descriptor ')' '+' ALL '(' SubSelect ')'
|
|
||||||
{
|
|
||||||
$$ = make5_str(make1_str("("), $2, make1_str(")+all("), $7, make1_str(")"));
|
|
||||||
}
|
|
||||||
| '(' row_descriptor ')' '-' ALL '(' SubSelect ')'
|
|
||||||
{
|
|
||||||
$$ = make5_str(make1_str("("), $2, make1_str(")-all("), $7, make1_str(")"));
|
|
||||||
}
|
|
||||||
| '(' row_descriptor ')' '/' ALL '(' SubSelect ')'
|
|
||||||
{
|
|
||||||
$$ = make5_str(make1_str("("), $2, make1_str(")/all("), $7, make1_str(")"));
|
|
||||||
}
|
|
||||||
| '(' row_descriptor ')' '*' ALL '(' SubSelect ')'
|
|
||||||
{
|
|
||||||
$$ = make5_str(make1_str("("), $2, make1_str(")*all("), $7, make1_str(")"));
|
|
||||||
}
|
|
||||||
| '(' row_descriptor ')' '<' ALL '(' SubSelect ')'
|
|
||||||
{
|
|
||||||
$$ = make5_str(make1_str("("), $2, make1_str(")<all("), $7, make1_str(")"));
|
|
||||||
}
|
|
||||||
| '(' row_descriptor ')' '>' ALL '(' SubSelect ')'
|
|
||||||
{
|
|
||||||
$$ = make5_str(make1_str("("), $2, make1_str(")>all("), $7, make1_str(")"));
|
|
||||||
}
|
|
||||||
| '(' row_descriptor ')' '=' ALL '(' SubSelect ')'
|
|
||||||
{
|
|
||||||
$$ = make5_str(make1_str("("), $2, make1_str(")=all("), $7, make1_str(")"));
|
|
||||||
}
|
|
||||||
| '(' row_descriptor ')' Op '(' row_descriptor ')'
|
|
||||||
{
|
{
|
||||||
$$ = cat3_str(make3_str(make1_str("("), $2, make1_str(")")), $4, make3_str(make1_str("("), $6, make1_str(")")));
|
$$ = cat3_str(make3_str(make1_str("("), $2, make1_str(")")), $4, make3_str(make1_str("("), $6, make1_str(")")));
|
||||||
}
|
}
|
||||||
| '(' row_descriptor ')' '+' '(' row_descriptor ')'
|
|
||||||
{
|
|
||||||
$$ = make5_str(make1_str("("), $2, make1_str(")+("), $6, make1_str(")"));
|
|
||||||
}
|
|
||||||
| '(' row_descriptor ')' '-' '(' row_descriptor ')'
|
|
||||||
{
|
|
||||||
$$ = make5_str(make1_str("("), $2, make1_str(")-("), $6, make1_str(")"));
|
|
||||||
}
|
|
||||||
| '(' row_descriptor ')' '/' '(' row_descriptor ')'
|
|
||||||
{
|
|
||||||
$$ = make5_str(make1_str("("), $2, make1_str(")/("), $6, make1_str(")"));
|
|
||||||
}
|
|
||||||
| '(' row_descriptor ')' '*' '(' row_descriptor ')'
|
|
||||||
{
|
|
||||||
$$ = make5_str(make1_str("("), $2, make1_str(")*("), $6, make1_str(")"));
|
|
||||||
}
|
|
||||||
| '(' row_descriptor ')' '<' '(' row_descriptor ')'
|
|
||||||
{
|
|
||||||
$$ = make5_str(make1_str("("), $2, make1_str(")<("), $6, make1_str(")"));
|
|
||||||
}
|
|
||||||
| '(' row_descriptor ')' '>' '(' row_descriptor ')'
|
|
||||||
{
|
|
||||||
$$ = make5_str(make1_str("("), $2, make1_str(")>("), $6, make1_str(")"));
|
|
||||||
}
|
|
||||||
| '(' row_descriptor ')' '=' '(' row_descriptor ')'
|
|
||||||
{
|
|
||||||
$$ = make5_str(make1_str("("), $2, make1_str(")=("), $6, make1_str(")"));
|
|
||||||
}
|
|
||||||
;
|
;
|
||||||
|
|
||||||
row_descriptor: row_list ',' a_expr
|
row_descriptor: row_list ',' a_expr
|
||||||
@ -2976,6 +2899,21 @@ row_descriptor: row_list ',' a_expr
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
row_op: Op { $$ = $1; }
|
||||||
|
| '<' { $$ = "<"; }
|
||||||
|
| '=' { $$ = "="; }
|
||||||
|
| '>' { $$ = ">"; }
|
||||||
|
| '+' { $$ = "+"; }
|
||||||
|
| '-' { $$ = "-"; }
|
||||||
|
| '*' { $$ = "*"; }
|
||||||
|
| '/' { $$ = "/"; }
|
||||||
|
;
|
||||||
|
|
||||||
|
sub_type: ANY { $$ = make1_str("ANY"); }
|
||||||
|
| ALL { $$ = make1_str("ALL"); }
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
row_list: row_list ',' a_expr
|
row_list: row_list ',' a_expr
|
||||||
{
|
{
|
||||||
$$ = cat3_str($1, make1_str(","), $3);
|
$$ = cat3_str($1, make1_str(","), $3);
|
||||||
@ -3089,6 +3027,11 @@ a_expr: attr opt_indirection
|
|||||||
{
|
{
|
||||||
$$ = make1_str("current_user");
|
$$ = make1_str("current_user");
|
||||||
}
|
}
|
||||||
|
| USER
|
||||||
|
{
|
||||||
|
$$ = make1_str("user");
|
||||||
|
}
|
||||||
|
|
||||||
| EXISTS '(' SubSelect ')'
|
| EXISTS '(' SubSelect ')'
|
||||||
{
|
{
|
||||||
$$ = make3_str(make1_str("exists("), $3, make1_str(")"));
|
$$ = make3_str(make1_str("exists("), $3, make1_str(")"));
|
||||||
@ -3358,6 +3301,10 @@ b_expr: attr opt_indirection
|
|||||||
{
|
{
|
||||||
$$ = make1_str("current_user");
|
$$ = make1_str("current_user");
|
||||||
}
|
}
|
||||||
|
| USER
|
||||||
|
{
|
||||||
|
$$ = make1_str("user");
|
||||||
|
}
|
||||||
| POSITION '(' position_list ')'
|
| POSITION '(' position_list ')'
|
||||||
{
|
{
|
||||||
$$ = make3_str(make1_str("position ("), $3, make1_str(")"));
|
$$ = make3_str(make1_str("position ("), $3, make1_str(")"));
|
||||||
@ -3417,12 +3364,9 @@ extract_list: extract_arg FROM a_expr
|
|||||||
{ $$ = make1_str(";;"); }
|
{ $$ = make1_str(";;"); }
|
||||||
;
|
;
|
||||||
|
|
||||||
/* Add in TIMEZONE_HOUR and TIMEZONE_MINUTE for SQL92 compliance
|
extract_arg: datetime { $$ = $1; }
|
||||||
* for next release. Just set up extract_arg for now...
|
| TIMEZONE_HOUR { $$ = make1_str("timezone_hour"); }
|
||||||
* - thomas 1998-04-08
|
| TIMEZONE_MINUTE { $$ = make1_str("timezone_minute"); }
|
||||||
*/
|
|
||||||
extract_arg: datetime
|
|
||||||
{ $$ = $1; }
|
|
||||||
;
|
;
|
||||||
|
|
||||||
position_list: position_expr IN position_expr
|
position_list: position_expr IN position_expr
|
||||||
@ -3660,9 +3604,9 @@ relation_name: SpecialRuleRelation
|
|||||||
;
|
;
|
||||||
|
|
||||||
database_name: ColId { $$ = $1; };
|
database_name: ColId { $$ = $1; };
|
||||||
access_method: ecpg_ident { $$ = $1; };
|
access_method: ident { $$ = $1; };
|
||||||
attr_name: ColId { $$ = $1; };
|
attr_name: ColId { $$ = $1; };
|
||||||
class: ecpg_ident { $$ = $1; };
|
class: ident { $$ = $1; };
|
||||||
index_name: ColId { $$ = $1; };
|
index_name: ColId { $$ = $1; };
|
||||||
|
|
||||||
/* Functions
|
/* Functions
|
||||||
@ -3673,7 +3617,7 @@ name: ColId { $$ = $1; };
|
|||||||
func_name: ColId { $$ = $1; };
|
func_name: ColId { $$ = $1; };
|
||||||
|
|
||||||
file_name: Sconst { $$ = $1; };
|
file_name: Sconst { $$ = $1; };
|
||||||
recipe_name: ecpg_ident { $$ = $1; };
|
recipe_name: ident { $$ = $1; };
|
||||||
|
|
||||||
/* Constants
|
/* Constants
|
||||||
* Include TRUE/FALSE for SQL3 support. - thomas 1997-10-24
|
* Include TRUE/FALSE for SQL3 support. - thomas 1997-10-24
|
||||||
@ -3723,8 +3667,9 @@ Sconst: SCONST {
|
|||||||
strcpy($$+1, $1);
|
strcpy($$+1, $1);
|
||||||
$$[strlen($1)+2]='\0';
|
$$[strlen($1)+2]='\0';
|
||||||
$$[strlen($1)+1]='\'';
|
$$[strlen($1)+1]='\'';
|
||||||
|
free($1);
|
||||||
}
|
}
|
||||||
UserId: ecpg_ident { $$ = $1;};
|
UserId: ident { $$ = $1;};
|
||||||
|
|
||||||
/* Column and type identifier
|
/* Column and type identifier
|
||||||
* Does not include explicit datetime types
|
* Does not include explicit datetime types
|
||||||
@ -3746,7 +3691,7 @@ TypeId: ColId
|
|||||||
* list due to shift/reduce conflicts in yacc. If so, move
|
* list due to shift/reduce conflicts in yacc. If so, move
|
||||||
* down to the ColLabel entity. - thomas 1997-11-06
|
* down to the ColLabel entity. - thomas 1997-11-06
|
||||||
*/
|
*/
|
||||||
ColId: ecpg_ident { $$ = $1; }
|
ColId: ident { $$ = $1; }
|
||||||
| datetime { $$ = $1; }
|
| datetime { $$ = $1; }
|
||||||
| ACTION { $$ = make1_str("action"); }
|
| ACTION { $$ = make1_str("action"); }
|
||||||
| CACHE { $$ = make1_str("cache"); }
|
| CACHE { $$ = make1_str("cache"); }
|
||||||
@ -3773,9 +3718,10 @@ ColId: ecpg_ident { $$ = $1; }
|
|||||||
| START { $$ = make1_str("start"); }
|
| START { $$ = make1_str("start"); }
|
||||||
| STATEMENT { $$ = make1_str("statement"); }
|
| STATEMENT { $$ = make1_str("statement"); }
|
||||||
| TIME { $$ = make1_str("time"); }
|
| TIME { $$ = make1_str("time"); }
|
||||||
|
| TIMEZONE_HOUR { $$ = make1_str("timezone_hour"); }
|
||||||
|
| TIMEZONE_MINUTE { $$ = make1_str("timezone_minute"); }
|
||||||
| TRIGGER { $$ = make1_str("trigger"); }
|
| TRIGGER { $$ = make1_str("trigger"); }
|
||||||
| TYPE_P { $$ = make1_str("type"); }
|
| TYPE_P { $$ = make1_str("type"); }
|
||||||
| USER { $$ = make1_str("user"); }
|
|
||||||
| VALID { $$ = make1_str("valid"); }
|
| VALID { $$ = make1_str("valid"); }
|
||||||
| VERSION { $$ = make1_str("version"); }
|
| VERSION { $$ = make1_str("version"); }
|
||||||
| ZONE { $$ = make1_str("zone"); }
|
| ZONE { $$ = make1_str("zone"); }
|
||||||
@ -4011,7 +3957,7 @@ variable: opt_pointer symbol opt_array_bounds opt_initializer
|
|||||||
if (struct_level == 0)
|
if (struct_level == 0)
|
||||||
new_variable($2, type);
|
new_variable($2, type);
|
||||||
else
|
else
|
||||||
ECPGmake_struct_member($2, type, &(struct_member_list[struct_level-1]));
|
ECPGmake_struct_member($2, type, &(struct_member_list[struct_level - 1]))->typ;
|
||||||
|
|
||||||
free($1);
|
free($1);
|
||||||
free($2);
|
free($2);
|
||||||
@ -4028,10 +3974,114 @@ opt_pointer: /* empty */ { $$ = make1_str(""); }
|
|||||||
/*
|
/*
|
||||||
* the exec sql connect statement: connect to the given database
|
* the exec sql connect statement: connect to the given database
|
||||||
*/
|
*/
|
||||||
ECPGConnect: SQL_CONNECT db_name { $$ = $2; }
|
ECPGConnect: SQL_CONNECT TO connection_target opt_connection_name opt_user
|
||||||
|
{
|
||||||
|
$$ = make5_str($3, make1_str(","), $5, make1_str(","), $4);
|
||||||
|
}
|
||||||
|
| SQL_CONNECT TO DEFAULT
|
||||||
|
{
|
||||||
|
$$ = make1_str("NULL,NULL,NULL,\"DEFAULT\"");
|
||||||
|
}
|
||||||
|
/* also allow ORACLE syntax */
|
||||||
|
| SQL_CONNECT ora_user
|
||||||
|
{
|
||||||
|
$$ = make3_str(make1_str("NULL,"), $2, make1_str(",NULL"));
|
||||||
|
}
|
||||||
|
|
||||||
db_name: database_name { $$ = $1; }
|
connection_target: database_name opt_server opt_port
|
||||||
| cvariable { /* check if we have a char variable */
|
{
|
||||||
|
/* old style: dbname[@server][:port] */
|
||||||
|
if (strlen($2) > 0 && *($2) != '@')
|
||||||
|
{
|
||||||
|
sprintf(errortext, "parse error at or near '%s'", $2);
|
||||||
|
yyerror(errortext);
|
||||||
|
}
|
||||||
|
|
||||||
|
$$ = make5_str(make1_str("\""), $1, $2, $3, make1_str("\""));
|
||||||
|
}
|
||||||
|
| db_prefix server opt_port '/' database_name opt_options
|
||||||
|
{
|
||||||
|
/* new style: esql:postgresql://server[:port][/dbname] */
|
||||||
|
if (strncmp($2, "://", 3) != 0)
|
||||||
|
{
|
||||||
|
sprintf(errortext, "parse error at or near '%s'", $2);
|
||||||
|
yyerror(errortext);
|
||||||
|
}
|
||||||
|
|
||||||
|
$$ = make4_str(make5_str(make1_str("\""), $1, $2, $3, make1_str("/")), $5, $6, make1_str("\""));
|
||||||
|
}
|
||||||
|
| char_variable
|
||||||
|
{
|
||||||
|
$$ = $1;
|
||||||
|
}
|
||||||
|
|
||||||
|
db_prefix: ident cvariable
|
||||||
|
{
|
||||||
|
if (strcmp($2, "postgresql") != 0 && strcmp($2, "postgres") != 0)
|
||||||
|
{
|
||||||
|
sprintf(errortext, "parse error at or near '%s'", $2);
|
||||||
|
yyerror(errortext);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp($1, "esql") != 0 && strcmp($1, "ecpg") != 0 && strcmp($1, "sql") != 0 && strcmp($1, "isql") != 0 && strcmp($1, "proc") != 0)
|
||||||
|
{
|
||||||
|
sprintf(errortext, "Illegal connection type %s", $1);
|
||||||
|
yyerror(errortext);
|
||||||
|
}
|
||||||
|
|
||||||
|
$$ = make3_str($1, make1_str(":"), $2);
|
||||||
|
}
|
||||||
|
|
||||||
|
server: Op server_name
|
||||||
|
{
|
||||||
|
if (strcmp($1, "@") != 0 && strcmp($1, "://") != 0)
|
||||||
|
{
|
||||||
|
sprintf(errortext, "parse error at or near '%s'", $1);
|
||||||
|
yyerror(errortext);
|
||||||
|
}
|
||||||
|
|
||||||
|
$$ = make2_str($1, $2);
|
||||||
|
}
|
||||||
|
|
||||||
|
opt_server: server { $$ = $1; }
|
||||||
|
| /* empty */ { $$ = make1_str(""); }
|
||||||
|
|
||||||
|
server_name: ColId { $$ = $1; }
|
||||||
|
| ColId '.' server_name { $$ = make3_str($1, make1_str("."), $3); }
|
||||||
|
|
||||||
|
opt_port: ':' Iconst { $$ = make2_str(make1_str(":"), $2); }
|
||||||
|
| /* empty */ { $$ = make1_str(""); }
|
||||||
|
|
||||||
|
opt_connection_name: AS connection_target { $$ = $2; }
|
||||||
|
| /* empty */ { $$ = make1_str("NULL"); }
|
||||||
|
|
||||||
|
opt_user: USER ora_user { $$ = $2; }
|
||||||
|
| /* empty */ { $$ = make1_str("NULL,NULL"); }
|
||||||
|
|
||||||
|
ora_user: user_name
|
||||||
|
{
|
||||||
|
$$ = make2_str($1, make1_str(",NULL"));
|
||||||
|
}
|
||||||
|
| user_name '/' ColId
|
||||||
|
{
|
||||||
|
$$ = make3_str($1, make1_str(","), $3);
|
||||||
|
}
|
||||||
|
| user_name SQL_IDENTIFIED BY user_name
|
||||||
|
{
|
||||||
|
$$ = make3_str($1, make1_str(","), $4);
|
||||||
|
}
|
||||||
|
| user_name USING user_name
|
||||||
|
{
|
||||||
|
$$ = make3_str($1, make1_str(","), $3);
|
||||||
|
}
|
||||||
|
|
||||||
|
user_name: UserId { $$ = make3_str(make1_str("\""), $1, make1_str("\"")); }
|
||||||
|
| char_variable { $$ = $1; }
|
||||||
|
| CSTRING { $$ = make3_str(make1_str("\""), $1, make1_str("\"")); }
|
||||||
|
| SCONST { $$ = make3_str(make1_str("\""), $1, make1_str("\"")); }
|
||||||
|
|
||||||
|
char_variable: cvariable
|
||||||
|
{ /* check if we have a char variable */
|
||||||
struct variable *p = find_variable($1);
|
struct variable *p = find_variable($1);
|
||||||
enum ECPGttype typ = p->type->typ;
|
enum ECPGttype typ = p->type->typ;
|
||||||
|
|
||||||
@ -4039,33 +4089,48 @@ db_name: database_name { $$ = $1; }
|
|||||||
if (typ == ECPGt_array)
|
if (typ == ECPGt_array)
|
||||||
typ = p->type->u.element->typ;
|
typ = p->type->u.element->typ;
|
||||||
|
|
||||||
if (typ != ECPGt_char && typ != ECPGt_unsigned_char)
|
switch (typ)
|
||||||
yyerror("invalid datatype");
|
{
|
||||||
$$ = $1;
|
case ECPGt_char:
|
||||||
}
|
case ECPGt_unsigned_char:
|
||||||
|
$$ = $1;
|
||||||
|
break;
|
||||||
|
case ECPGt_varchar:
|
||||||
|
$$ = make2_str($1, make1_str(".arr"));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
yyerror("invalid datatype");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
opt_options: Op ColId
|
||||||
|
{
|
||||||
|
if (strlen($1) == 0)
|
||||||
|
yyerror("parse error");
|
||||||
|
|
||||||
|
if (strcmp($1, "?") != 0)
|
||||||
|
{
|
||||||
|
sprintf(errortext, "parse error at or near %s", $1);
|
||||||
|
yyerror(errortext);
|
||||||
|
}
|
||||||
|
|
||||||
|
$$ = make2_str(make1_str("?"), $2);
|
||||||
|
}
|
||||||
|
| /* empty */ { $$ = make1_str(""); }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* the exec sql disconnect statement: disconnect from the given database
|
* the exec sql disconnect statement: disconnect from the given database
|
||||||
*/
|
*/
|
||||||
ECPGDisconnect: SQL_DISCONNECT dis_name { $$ = $2; }
|
ECPGDisconnect: SQL_DISCONNECT dis_name { $$ = $2; }
|
||||||
|
|
||||||
dis_name: database_name { $$ = $1; }
|
dis_name: connection_object { $$ = $1; }
|
||||||
| cvariable { /* check if we have a char variable */
|
| CURRENT { $$ = make1_str("CURRENT"); }
|
||||||
struct variable *p = find_variable($1);
|
| ALL { $$ = make1_str("ALL"); }
|
||||||
enum ECPGttype typ = p->type->typ;
|
| /* empty */ { $$ = make1_str("CURRENT"); }
|
||||||
|
|
||||||
/* if array see what's inside */
|
connection_object: connection_target { $$ = $1; }
|
||||||
if (typ == ECPGt_array)
|
| DEFAULT { $$ = make1_str("DEFAULT"); }
|
||||||
typ = p->type->u.element->typ;
|
|
||||||
|
|
||||||
if (typ != ECPGt_char && typ != ECPGt_unsigned_char)
|
|
||||||
yyerror("invalid datatype");
|
|
||||||
$$ = $1;
|
|
||||||
}
|
|
||||||
| CURRENT { $$ = make1_str(""); }
|
|
||||||
| DEFAULT { $$ = make1_str(""); }
|
|
||||||
| ALL { $$ = make1_str(""); }
|
|
||||||
| /* empty */ { $$ = make1_str(""); }
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* execute a given string as sql command
|
* execute a given string as sql command
|
||||||
@ -4118,6 +4183,14 @@ ECPGRelease: TransactionStmt SQL_RELEASE
|
|||||||
free($1);
|
free($1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* set the actual connection, this needs a differnet handling as the other
|
||||||
|
* set commands
|
||||||
|
*/
|
||||||
|
ECPGSetConnection: SET SQL_CONNECTION connection_object
|
||||||
|
{
|
||||||
|
$$ = $3;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* whenever statement: decide what to do in case of error/no data found
|
* whenever statement: decide what to do in case of error/no data found
|
||||||
* according to SQL standards we miss: SQLSTATE, CONSTRAINT, SQLEXCEPTION
|
* according to SQL standards we miss: SQLSTATE, CONSTRAINT, SQLEXCEPTION
|
||||||
@ -4163,7 +4236,7 @@ action : SQL_CONTINUE {
|
|||||||
| DO name '(' dotext ')' {
|
| DO name '(' dotext ')' {
|
||||||
$<action>$.code = W_DO;
|
$<action>$.code = W_DO;
|
||||||
$<action>$.command = make4_str($2, make1_str("("), $4, make1_str(")"));
|
$<action>$.command = make4_str($2, make1_str("("), $4, make1_str(")"));
|
||||||
$<action>$.str = cat2_str(make1_str("do"), $<action>$.command);
|
$<action>$.str = cat2_str(make1_str("do"), strdup($<action>$.command));
|
||||||
}
|
}
|
||||||
| DO SQL_BREAK {
|
| DO SQL_BREAK {
|
||||||
$<action>$.code = W_BREAK;
|
$<action>$.code = W_BREAK;
|
||||||
@ -4173,7 +4246,7 @@ action : SQL_CONTINUE {
|
|||||||
| SQL_CALL name '(' dotext ')' {
|
| SQL_CALL name '(' dotext ')' {
|
||||||
$<action>$.code = W_DO;
|
$<action>$.code = W_DO;
|
||||||
$<action>$.command = make4_str($2, make1_str("("), $4, make1_str(")"));
|
$<action>$.command = make4_str($2, make1_str("("), $4, make1_str(")"));
|
||||||
$<action>$.str = cat2_str(make1_str("call"), $<action>$.command);
|
$<action>$.str = cat2_str(make1_str("call"), strdup($<action>$.command));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* some other stuff for ecpg */
|
/* some other stuff for ecpg */
|
||||||
@ -4478,14 +4551,16 @@ civariableonly : cvariable name {
|
|||||||
add_variable(&argsinsert, find_variable($1), &no_indicator);
|
add_variable(&argsinsert, find_variable($1), &no_indicator);
|
||||||
}
|
}
|
||||||
|
|
||||||
cvariable: CVARIABLE { $$ = $1; }
|
cvariable: CVARIABLE { $$ = make1_str($1); }
|
||||||
|
|
||||||
indicator: /* empty */ { $$ = NULL; }
|
indicator: /* empty */ { $$ = NULL; }
|
||||||
| cvariable { check_indicator((find_variable($1))->type); $$ = $1; }
|
| cvariable { check_indicator((find_variable($1))->type); $$ = $1; }
|
||||||
| SQL_INDICATOR cvariable { check_indicator((find_variable($2))->type); $$ = $2; }
|
| SQL_INDICATOR cvariable { check_indicator((find_variable($2))->type); $$ = $2; }
|
||||||
| SQL_INDICATOR name { check_indicator((find_variable($2))->type); $$ = $2; }
|
| SQL_INDICATOR name { check_indicator((find_variable($2))->type); $$ = $2; }
|
||||||
|
|
||||||
ecpg_ident: IDENT { $$ = $1; }
|
ident: IDENT { $$ = make1_str($1); }
|
||||||
|
|
||||||
|
ecpg_ident: ident { $$ = $1; }
|
||||||
| CSTRING { $$ = make3_str(make1_str("\""), $1, make1_str("\"")); }
|
| CSTRING { $$ = make3_str(make1_str("\""), $1, make1_str("\"")); }
|
||||||
/*
|
/*
|
||||||
* C stuff
|
* C stuff
|
||||||
|
@ -20,21 +20,6 @@ mm_alloc(size_t size)
|
|||||||
return (ptr);
|
return (ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* realloc + error check */
|
|
||||||
void *
|
|
||||||
mm_realloc(void *ptr, size_t size)
|
|
||||||
{
|
|
||||||
ptr = realloc(ptr, size);
|
|
||||||
|
|
||||||
if (ptr == NULL)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Out of memory\n");
|
|
||||||
exit(OUT_OF_MEMORY);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* duplicate memberlist */
|
/* duplicate memberlist */
|
||||||
static struct ECPGstruct_member *
|
static struct ECPGstruct_member *
|
||||||
struct_member_dup(struct ECPGstruct_member * rm)
|
struct_member_dup(struct ECPGstruct_member * rm)
|
||||||
@ -43,7 +28,22 @@ struct_member_dup(struct ECPGstruct_member * rm)
|
|||||||
|
|
||||||
while (rm)
|
while (rm)
|
||||||
{
|
{
|
||||||
ECPGmake_struct_member(rm->name, rm->typ, &new);
|
struct ECPGtype *type;
|
||||||
|
|
||||||
|
switch(rm->typ->typ)
|
||||||
|
{
|
||||||
|
case ECPGt_struct:
|
||||||
|
type = ECPGmake_struct_type(rm->typ->u.members);
|
||||||
|
break;
|
||||||
|
case ECPGt_array:
|
||||||
|
type = ECPGmake_array_type(ECPGmake_simple_type(rm->typ->u.element->typ, rm->typ->u.element->size), rm->typ->size);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
type = ECPGmake_simple_type(rm->typ->typ, rm->typ->size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ECPGmake_struct_member(rm->name, type, &new);
|
||||||
|
|
||||||
rm = rm->next;
|
rm = rm->next;
|
||||||
}
|
}
|
||||||
@ -165,11 +165,11 @@ static const char *get_type(enum ECPGttype typ)
|
|||||||
size is the maxsize in case it is a varchar. Otherwise it is the size of
|
size is the maxsize in case it is a varchar. Otherwise it is the size of
|
||||||
the variable (required to do array fetches of structs).
|
the variable (required to do array fetches of structs).
|
||||||
*/
|
*/
|
||||||
void
|
static void
|
||||||
ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ,
|
ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ,
|
||||||
long varcharsize,
|
long varcharsize,
|
||||||
long arrsiz, const char *siz, const char *prefix);
|
long arrsiz, const char *siz, const char *prefix);
|
||||||
void
|
static void
|
||||||
ECPGdump_a_struct(FILE *o, const char *name, const char *ind_name, long arrsiz,
|
ECPGdump_a_struct(FILE *o, const char *name, const char *ind_name, long arrsiz,
|
||||||
struct ECPGtype * typ, struct ECPGtype * ind_typ, const char *offset, const char *prefix, const char * ind_prefix);
|
struct ECPGtype * typ, struct ECPGtype * ind_typ, const char *offset, const char *prefix, const char * ind_prefix);
|
||||||
|
|
||||||
@ -223,7 +223,7 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * typ, const char *in
|
|||||||
|
|
||||||
/* If siz is NULL, then the offset is 0, if not use siz as a
|
/* If siz is NULL, then the offset is 0, if not use siz as a
|
||||||
string, it represents the offset needed if we are in an array of structs. */
|
string, it represents the offset needed if we are in an array of structs. */
|
||||||
void
|
static void
|
||||||
ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ,
|
ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ,
|
||||||
long varcharsize,
|
long varcharsize,
|
||||||
long arrsize,
|
long arrsize,
|
||||||
@ -272,7 +272,7 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ,
|
|||||||
|
|
||||||
|
|
||||||
/* Penetrate a struct and dump the contents. */
|
/* Penetrate a struct and dump the contents. */
|
||||||
void
|
static void
|
||||||
ECPGdump_a_struct(FILE *o, const char *name, const char * ind_name, long arrsiz, struct ECPGtype * typ, struct ECPGtype * ind_typ, const char *offsetarg, const char *prefix, const char *ind_prefix)
|
ECPGdump_a_struct(FILE *o, const char *name, const char * ind_name, long arrsiz, struct ECPGtype * typ, struct ECPGtype * ind_typ, const char *offsetarg, const char *prefix, const char *ind_prefix)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -319,6 +319,7 @@ ECPGfree_struct_member(struct ECPGstruct_member * rm)
|
|||||||
|
|
||||||
rm = rm->next;
|
rm = rm->next;
|
||||||
free(p->name);
|
free(p->name);
|
||||||
|
free(p->typ);
|
||||||
free(p);
|
free(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -337,7 +338,7 @@ ECPGfree_type(struct ECPGtype * typ)
|
|||||||
else if (typ->u.element->typ == ECPGt_struct)
|
else if (typ->u.element->typ == ECPGt_struct)
|
||||||
{
|
{
|
||||||
/* Array of structs. */
|
/* Array of structs. */
|
||||||
ECPGfree_struct_member(typ->u.members);
|
ECPGfree_struct_member(typ->u.element->u.members);
|
||||||
free(typ->u.members);
|
free(typ->u.members);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -28,7 +28,7 @@ exec sql begin declare section;
|
|||||||
exec sql end declare section;
|
exec sql end declare section;
|
||||||
struct timeval tvs, tve;
|
struct timeval tvs, tve;
|
||||||
|
|
||||||
exec sql connect mm;
|
exec sql connect to mm;
|
||||||
|
|
||||||
exec sql create table perftest1(number int4, ascii char(16));
|
exec sql create table perftest1(number int4, ascii char(16));
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ exec sql end declare section;
|
|||||||
ECPGdebug(1, dbgs);
|
ECPGdebug(1, dbgs);
|
||||||
|
|
||||||
strcpy(msg, "connect");
|
strcpy(msg, "connect");
|
||||||
exec sql connect mm;
|
exec sql connect to mm;
|
||||||
|
|
||||||
strcpy(msg, "create");
|
strcpy(msg, "create");
|
||||||
exec sql create table test(name char(8), amount int);
|
exec sql create table test(name char(8), amount int);
|
||||||
|
@ -11,9 +11,9 @@ exec sql begin declare section;
|
|||||||
short age;
|
short age;
|
||||||
} birth;
|
} birth;
|
||||||
} personal;
|
} personal;
|
||||||
struct personal_indicator { short name;
|
struct personal_indicator { short ind_name;
|
||||||
struct birth_indicator { short born;
|
struct birth_indicator { short ind_born;
|
||||||
int age;
|
int ind_age;
|
||||||
} ind_birth;
|
} ind_birth;
|
||||||
} ind_personal;
|
} ind_personal;
|
||||||
long ind_married;
|
long ind_married;
|
||||||
@ -26,7 +26,7 @@ exec sql end declare section;
|
|||||||
ECPGdebug(1, dbgs);
|
ECPGdebug(1, dbgs);
|
||||||
|
|
||||||
strcpy(msg, "connect");
|
strcpy(msg, "connect");
|
||||||
exec sql connect mm;
|
exec sql connect to mm;
|
||||||
|
|
||||||
strcpy(msg, "create");
|
strcpy(msg, "create");
|
||||||
exec sql create table meskes(name char(8), born integer, age smallint, married char(8));
|
exec sql create table meskes(name char(8), born integer, age smallint, married char(8));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user