mirror of
https://github.com/postgres/postgres.git
synced 2025-05-12 16:21:30 +03:00
Erk, the whole directory structure changed on us here...
This commit is contained in:
parent
a8313f9671
commit
38201e21d0
16
src/interfaces/ecpg/include/Makefile
Normal file
16
src/interfaces/ecpg/include/Makefile
Normal file
@ -0,0 +1,16 @@
|
||||
# Generated automatically from Makefile.in by configure.
|
||||
SRCDIR= ../../..
|
||||
include $(SRCDIR)/Makefile.global
|
||||
|
||||
all clean::
|
||||
@echo Nothing to be done.
|
||||
|
||||
install::
|
||||
install ecpglib.h $(HEADERDIR)
|
||||
install ecpgtype.h $(HEADERDIR)
|
||||
install sqlca.h $(HEADERDIR)
|
||||
|
||||
uninstall::
|
||||
rm -f $(HEADERDIR)/ecpglib.h
|
||||
rm -f $(HEADERDIR)/ecpgtype.h
|
||||
rm -f $(HEADERDIR)/sqlca.h
|
15
src/interfaces/ecpg/include/Makefile.in
Normal file
15
src/interfaces/ecpg/include/Makefile.in
Normal file
@ -0,0 +1,15 @@
|
||||
SRCDIR= ../../..
|
||||
include $(SRCDIR)/Makefile.global
|
||||
|
||||
all clean::
|
||||
@echo Nothing to be done.
|
||||
|
||||
install::
|
||||
install ecpglib.h $(HEADERDIR)
|
||||
install ecpgtype.h $(HEADERDIR)
|
||||
install sqlca.h $(HEADERDIR)
|
||||
|
||||
uninstall::
|
||||
rm -f $(HEADERDIR)/ecpglib.h
|
||||
rm -f $(HEADERDIR)/ecpgtype.h
|
||||
rm -f $(HEADERDIR)/sqlca.h
|
@ -1,6 +1,6 @@
|
||||
#include <c.h>
|
||||
|
||||
void ECPGdebug(int);
|
||||
void ECPGdebug(int, FILE *);
|
||||
bool ECPGconnect(const char * dbname);
|
||||
bool ECPGdo(int, char *, ...);
|
||||
bool ECPGcommit(int);
|
@ -32,13 +32,13 @@
|
||||
enum ECPGttype {
|
||||
ECPGt_char = 1, ECPGt_unsigned_char, ECPGt_short, ECPGt_unsigned_short,
|
||||
ECPGt_int, ECPGt_unsigned_int, ECPGt_long, ECPGt_unsigned_long,
|
||||
ECPGt_bool,
|
||||
ECPGt_float, ECPGt_double,
|
||||
ECPGt_varchar, ECPGt_varchar2,
|
||||
ECPGt_array,
|
||||
ECPGt_record,
|
||||
ECPGt_EOIT, /* End of insert types. */
|
||||
ECPGt_EORT /* End of result types. */
|
||||
|
||||
};
|
||||
|
||||
#define IS_SIMPLE_TYPE(type) ((type) >= ECPGt_char && (type) <= ECPGt_varchar2)
|
@ -1,19 +1,21 @@
|
||||
# Generated automatically from Makefile.in by configure.
|
||||
TOPDIR=/home/meskes/data/computer/databases/postgres/pgsql/src/interfaces/ecpg/../..
|
||||
PQ_INCLUDE=-I$(TOPDIR)/include -I$(TOPDIR)/interfaces/libpq
|
||||
POSTGRES_LIB=$(POSTGRESTOP)/lib
|
||||
SRCDIR= ../../..
|
||||
include $(SRCDIR)/Makefile.global
|
||||
|
||||
PQ_INCLUDE=-I$(SRCDIR)/include -I$(SRCDIR)/interfaces/libpq
|
||||
|
||||
all: lib
|
||||
|
||||
lib: libecpg.a
|
||||
|
||||
clean::
|
||||
clean:
|
||||
rm -f *.o *.a core a.out *~
|
||||
|
||||
install:: libecpg.a
|
||||
install -m644 libecpg.a $(POSTGRES_LIB)
|
||||
install: libecpg.a
|
||||
install -m 644 libecpg.a $(LIBDIR)
|
||||
|
||||
uninstall::
|
||||
rm -f $(POSTGRES_LIB)/libecpg.a
|
||||
rm -f $(LIBDIR)/libecpg.a
|
||||
|
||||
# Rules that do something
|
||||
libecpg.a : libecpg.a(ecpglib.o) libecpg.a(typename.o)
|
@ -1,18 +1,20 @@
|
||||
TOPDIR=@TOPSRC@
|
||||
PQ_INCLUDE=-I$(TOPDIR)/include -I$(TOPDIR)/interfaces/libpq
|
||||
POSTGRES_LIB=$(POSTGRESTOP)/lib
|
||||
SRCDIR= ../../..
|
||||
include $(SRCDIR)/Makefile.global
|
||||
|
||||
PQ_INCLUDE=-I$(SRCDIR)/include -I$(SRCDIR)/interfaces/libpq
|
||||
|
||||
all: lib
|
||||
|
||||
lib: libecpg.a
|
||||
|
||||
clean::
|
||||
clean:
|
||||
rm -f *.o *.a core a.out *~
|
||||
|
||||
install:: libecpg.a
|
||||
install -m644 libecpg.a $(POSTGRES_LIB)
|
||||
install: libecpg.a
|
||||
install -m 644 libecpg.a $(LIBDIR)
|
||||
|
||||
uninstall::
|
||||
rm -f $(POSTGRES_LIB)/libecpg.a
|
||||
rm -f $(LIBDIR)/libecpg.a
|
||||
|
||||
# Rules that do something
|
||||
libecpg.a : libecpg.a(ecpglib.o) libecpg.a(typename.o)
|
648
src/interfaces/ecpg/lib/ecpglib.c
Normal file
648
src/interfaces/ecpg/lib/ecpglib.c
Normal file
@ -0,0 +1,648 @@
|
||||
/* Copyright comment */
|
||||
/*
|
||||
* The aim is to get a simpler inteface to the database routines.
|
||||
* All the tidieous messing around with tuples is supposed to be hidden
|
||||
* by this function.
|
||||
*/
|
||||
/* Author: Linus Tolke
|
||||
(actually most if the code is "borrowed" from the distribution and just
|
||||
slightly modified)
|
||||
*/
|
||||
|
||||
/* Taken over as part of PostgreSQL by Michael Meskes <meskes@debian.org>
|
||||
on Feb. 5th, 1998 */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <ecpgtype.h>
|
||||
#include <ecpglib.h>
|
||||
#include <sqlca.h>
|
||||
#include <libpq-fe.h>
|
||||
#include <libpq/pqcomm.h>
|
||||
|
||||
static PGconn *simple_connection;
|
||||
static int simple_debug = 0;
|
||||
static FILE *debugstream = NULL;
|
||||
static int committed = true;
|
||||
|
||||
static void
|
||||
register_error(int code, char *fmt,...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
sqlca.sqlcode = code;
|
||||
va_start(args, fmt);
|
||||
vsprintf(sqlca.sqlerrm.sqlerrmc, fmt, args);
|
||||
va_end(args);
|
||||
sqlca.sqlerrm.sqlerrml = strlen(sqlca.sqlerrm.sqlerrmc);
|
||||
}
|
||||
|
||||
/* This function returns a newly malloced string that has the ' and \
|
||||
in the argument quoted with \.
|
||||
*/
|
||||
static
|
||||
char *
|
||||
quote_postgres(char *arg)
|
||||
{
|
||||
char *res = (char *) malloc(2 * strlen(arg) + 1);
|
||||
int i,
|
||||
ri;
|
||||
|
||||
for (i = 0, ri = 0; arg[i]; i++, ri++)
|
||||
{
|
||||
switch (arg[i])
|
||||
{
|
||||
case '\'':
|
||||
case '\\':
|
||||
res[ri++] = '\\';
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
res[ri] = arg[i];
|
||||
}
|
||||
res[ri] = '\0';
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ECPGdo(int lineno, char *query,...)
|
||||
{
|
||||
va_list ap;
|
||||
bool status = false;
|
||||
char *copiedquery;
|
||||
PGresult *results;
|
||||
PGnotify *notify;
|
||||
enum ECPGttype type;
|
||||
|
||||
va_start(ap, query);
|
||||
|
||||
sqlca.sqlcode = 0;
|
||||
copiedquery = strdup(query);
|
||||
|
||||
type = va_arg(ap, enum ECPGttype);
|
||||
|
||||
/*
|
||||
* Now, if the type is one of the fill in types then we take the argument
|
||||
* and enter that in the string at the first %s position. Then if there
|
||||
* are any more fill in types we fill in at the next and so on.
|
||||
*/
|
||||
while (type != ECPGt_EOIT)
|
||||
{
|
||||
void *value = NULL;
|
||||
short varcharsize;
|
||||
short size;
|
||||
short arrsize;
|
||||
|
||||
char *newcopy;
|
||||
char *mallocedval = NULL;
|
||||
char *tobeinserted = NULL;
|
||||
char *p;
|
||||
char buff[20];
|
||||
|
||||
/* Some special treatment is needed for records since we want their
|
||||
contents to arrive in a comma-separated list on insert (I think). */
|
||||
|
||||
value = va_arg(ap, void *);
|
||||
varcharsize = va_arg(ap, short);
|
||||
size = va_arg(ap, short);
|
||||
arrsize = va_arg(ap, short);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case ECPGt_char:
|
||||
case ECPGt_short:
|
||||
case ECPGt_int:
|
||||
sprintf(buff, "%d", *(int *) value);
|
||||
tobeinserted = buff;
|
||||
break;
|
||||
|
||||
case ECPGt_unsigned_char:
|
||||
case ECPGt_unsigned_short:
|
||||
case ECPGt_unsigned_int:
|
||||
sprintf(buff, "%d", *(unsigned int *) value);
|
||||
tobeinserted = buff;
|
||||
break;
|
||||
|
||||
case ECPGt_long:
|
||||
sprintf(buff, "%ld", *(long *) value);
|
||||
tobeinserted = buff;
|
||||
break;
|
||||
|
||||
case ECPGt_unsigned_long:
|
||||
sprintf(buff, "%ld", *(unsigned long *) value);
|
||||
tobeinserted = buff;
|
||||
break;
|
||||
|
||||
case ECPGt_float:
|
||||
sprintf(buff, "%.14g", *(float *) value);
|
||||
tobeinserted = buff;
|
||||
break;
|
||||
|
||||
case ECPGt_double:
|
||||
sprintf(buff, "%.14g", *(double *) value);
|
||||
tobeinserted = buff;
|
||||
break;
|
||||
|
||||
case ECPGt_bool:
|
||||
sprintf(buff, "'%c'", (*(char *) value ? 't' : 'f'));
|
||||
tobeinserted = buff;
|
||||
break;
|
||||
|
||||
case ECPGt_varchar:
|
||||
case ECPGt_varchar2:
|
||||
{
|
||||
struct ECPGgeneric_varchar *var =
|
||||
(struct ECPGgeneric_varchar *) value;
|
||||
|
||||
newcopy = (char *) malloc(var->len + 1);
|
||||
strncpy(newcopy, var->arr, var->len);
|
||||
newcopy[var->len] = '\0';
|
||||
|
||||
mallocedval = (char *) malloc(2 * strlen(newcopy) + 3);
|
||||
strcpy(mallocedval, "'");
|
||||
strcat(mallocedval, quote_postgres(newcopy));
|
||||
strcat(mallocedval, "'");
|
||||
|
||||
free(newcopy);
|
||||
|
||||
tobeinserted = mallocedval;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Not implemented yet */
|
||||
register_error(-1, "Unsupported type %s on line %d.",
|
||||
ECPGtype_name(type), lineno);
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Now tobeinserted points to an area that is to be inserted at
|
||||
the first %s
|
||||
*/
|
||||
newcopy = (char *) malloc(strlen(copiedquery)
|
||||
+ strlen(tobeinserted)
|
||||
+ 1);
|
||||
strcpy(newcopy, copiedquery);
|
||||
if ((p = strstr(newcopy, ";;")) == NULL)
|
||||
{
|
||||
/* We have an argument but we dont have the matched up string
|
||||
in the string
|
||||
*/
|
||||
register_error(-1, "Too many arguments line %d.", lineno);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(p, tobeinserted);
|
||||
/* The strange thing in the second argument is the rest of the
|
||||
string from the old string */
|
||||
strcat(newcopy,
|
||||
copiedquery
|
||||
+ (p - newcopy)
|
||||
+ 2 /* Length of ;; */ );
|
||||
}
|
||||
|
||||
/* Now everything is safely copied to the newcopy. Lets free the
|
||||
oldcopy and let the copiedquery get the value from the newcopy.
|
||||
*/
|
||||
if (mallocedval != NULL)
|
||||
{
|
||||
free(mallocedval);
|
||||
mallocedval = NULL;
|
||||
}
|
||||
|
||||
free(copiedquery);
|
||||
copiedquery = newcopy;
|
||||
|
||||
type = va_arg(ap, enum ECPGttype);
|
||||
}
|
||||
|
||||
/* Check if there are unmatched things left. */
|
||||
if (strstr(copiedquery, ";;") != NULL)
|
||||
{
|
||||
register_error(-1, "Too few arguments line %d.", lineno);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Now then request is built. */
|
||||
|
||||
if (committed)
|
||||
{
|
||||
if ((results = PQexec(simple_connection, "begin")) == NULL)
|
||||
{
|
||||
register_error(-1, "Error starting transaction line %d.", lineno);
|
||||
return false;
|
||||
}
|
||||
PQclear(results);
|
||||
committed = 0;
|
||||
}
|
||||
|
||||
ECPGlog("ECPGdo line %d: QUERY: %s\n", lineno, copiedquery);
|
||||
results = PQexec(simple_connection, copiedquery);
|
||||
free(copiedquery);
|
||||
|
||||
if (results == NULL)
|
||||
{
|
||||
ECPGlog("ECPGdo line %d: error: %s", lineno,
|
||||
PQerrorMessage(simple_connection));
|
||||
register_error(-1, "Postgres error: %s line %d.",
|
||||
PQerrorMessage(simple_connection), lineno);
|
||||
}
|
||||
else
|
||||
switch (PQresultStatus(results))
|
||||
{
|
||||
int m,
|
||||
n,
|
||||
x;
|
||||
|
||||
case PGRES_TUPLES_OK:
|
||||
/* XXX Cheap Hack. For now, we see only the last group
|
||||
* of tuples. This is clearly not the right
|
||||
* way to do things !!
|
||||
*/
|
||||
|
||||
m = PQnfields(results);
|
||||
n = PQntuples(results);
|
||||
|
||||
if (n < 1)
|
||||
{
|
||||
ECPGlog("ECPGdo lineno %d: Incorrect number of matches: %d\n",
|
||||
lineno, n);
|
||||
register_error(1, "Data not found line %d.", lineno);
|
||||
break;
|
||||
}
|
||||
|
||||
if (n > 1)
|
||||
{
|
||||
ECPGlog("ECPGdo line %d: Incorrect number of matches: %d\n",
|
||||
lineno, n);
|
||||
register_error(-1, "To many matches line %d.", lineno);
|
||||
break;
|
||||
}
|
||||
|
||||
status = true;
|
||||
|
||||
for (x = 0; x < m && status; x++)
|
||||
{
|
||||
void *value = NULL;
|
||||
short varcharsize;
|
||||
short size;
|
||||
short arrsize;
|
||||
|
||||
char *pval = PQgetvalue(results, 0, x);
|
||||
|
||||
/*long int * res_int;
|
||||
char ** res_charstar;
|
||||
char * res_char;
|
||||
int res_len; */
|
||||
char *scan_length;
|
||||
|
||||
ECPGlog("ECPGdo line %d: RESULT: %s\n", lineno, pval ? pval : "");
|
||||
|
||||
/* No the pval is a pointer to the value. */
|
||||
/* We will have to decode the value */
|
||||
type = va_arg(ap, enum ECPGttype);
|
||||
value = va_arg(ap, void *);
|
||||
varcharsize = va_arg(ap, short);
|
||||
size = va_arg(ap, short);
|
||||
arrsize = va_arg(ap, short);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
long res;
|
||||
unsigned long ures;
|
||||
double dres;
|
||||
|
||||
case ECPGt_char:
|
||||
case ECPGt_short:
|
||||
case ECPGt_int:
|
||||
case ECPGt_long:
|
||||
if (pval)
|
||||
{
|
||||
res = strtol(pval, &scan_length, 10);
|
||||
if (*scan_length != '\0') /* Garbage left */
|
||||
{
|
||||
register_error(-1, "Not correctly formatted int type: %s line %d.",
|
||||
pval, lineno);
|
||||
status = false;
|
||||
res = 0L;
|
||||
}
|
||||
}
|
||||
else
|
||||
res = 0L;
|
||||
|
||||
/* Again?! Yes */
|
||||
switch (type)
|
||||
{
|
||||
case ECPGt_char:
|
||||
*(char *) value = (char) res;
|
||||
break;
|
||||
case ECPGt_short:
|
||||
*(short *) value = (short) res;
|
||||
break;
|
||||
case ECPGt_int:
|
||||
*(int *) value = (int) res;
|
||||
break;
|
||||
case ECPGt_long:
|
||||
*(long *) value = res;
|
||||
break;
|
||||
default:
|
||||
/* Cannot happen */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case ECPGt_unsigned_char:
|
||||
case ECPGt_unsigned_short:
|
||||
case ECPGt_unsigned_int:
|
||||
case ECPGt_unsigned_long:
|
||||
if (pval)
|
||||
{
|
||||
ures = strtoul(pval, &scan_length, 10);
|
||||
if (*scan_length != '\0') /* Garbage left */
|
||||
{
|
||||
register_error(-1, "Not correctly formatted unsigned type: %s line %d.",
|
||||
pval, lineno);
|
||||
status = false;
|
||||
ures = 0L;
|
||||
}
|
||||
}
|
||||
else
|
||||
ures = 0L;
|
||||
|
||||
/* Again?! Yes */
|
||||
switch (type)
|
||||
{
|
||||
case ECPGt_unsigned_char:
|
||||
*(unsigned char *) value = (unsigned char) ures;
|
||||
break;
|
||||
case ECPGt_unsigned_short:
|
||||
*(unsigned short *) value = (unsigned short) ures;
|
||||
break;
|
||||
case ECPGt_unsigned_int:
|
||||
*(unsigned int *) value = (unsigned int) ures;
|
||||
break;
|
||||
case ECPGt_unsigned_long:
|
||||
*(unsigned long *) value = ures;
|
||||
break;
|
||||
default:
|
||||
/* Cannot happen */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case ECPGt_float:
|
||||
case ECPGt_double:
|
||||
if (pval)
|
||||
{
|
||||
dres = strtod(pval, &scan_length);
|
||||
if (*scan_length != '\0') /* Garbage left */
|
||||
{
|
||||
register_error(-1, "Not correctly formatted floating point type: %s line %d.",
|
||||
pval, lineno);
|
||||
status = false;
|
||||
dres = 0.0;
|
||||
}
|
||||
}
|
||||
else
|
||||
dres = 0.0;
|
||||
|
||||
/* Again?! Yes */
|
||||
switch (type)
|
||||
{
|
||||
case ECPGt_float:
|
||||
*(float *) value = dres;
|
||||
break;
|
||||
case ECPGt_double:
|
||||
*(double *) value = dres;
|
||||
break;
|
||||
default:
|
||||
/* Cannot happen */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case ECPGt_bool:
|
||||
if (pval)
|
||||
{
|
||||
if (pval[0] == 'f' && pval[1] == '\0')
|
||||
{
|
||||
*(char *) value = false;
|
||||
break;
|
||||
}
|
||||
else if (pval[0] == 't' && pval[1] == '\0')
|
||||
{
|
||||
*(char *) value = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
register_error(-1, "Unable to convert %s to bool on line %d.",
|
||||
(pval ? pval : "NULL"),
|
||||
lineno);
|
||||
return false;
|
||||
break;
|
||||
|
||||
case ECPGt_varchar:
|
||||
{
|
||||
struct ECPGgeneric_varchar *var =
|
||||
(struct ECPGgeneric_varchar *) value;
|
||||
|
||||
strncpy(var->arr, pval, varcharsize);
|
||||
var->len = strlen(pval);
|
||||
if (var->len > varcharsize)
|
||||
var->len = varcharsize;
|
||||
}
|
||||
break;
|
||||
|
||||
case ECPGt_EORT:
|
||||
ECPGlog("ECPGdo line %d: Too few arguments.\n", lineno);
|
||||
register_error(-1, "Too few arguments line %d.", lineno);
|
||||
status = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
register_error(-1, "Unsupported type %s on line %d.",
|
||||
ECPGtype_name(type), lineno);
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
type = va_arg(ap, enum ECPGttype);
|
||||
|
||||
if (status && type != ECPGt_EORT)
|
||||
{
|
||||
register_error(-1, "Too many arguments line %d.", lineno);
|
||||
return false;
|
||||
}
|
||||
|
||||
PQclear(results);
|
||||
break;
|
||||
case PGRES_EMPTY_QUERY:
|
||||
/* do nothing */
|
||||
register_error(-1, "Empty query line %d.", lineno);
|
||||
break;
|
||||
case PGRES_COMMAND_OK:
|
||||
status = true;
|
||||
ECPGlog("ECPGdo line %d Ok: %s\n", lineno, PQcmdStatus(results));
|
||||
break;
|
||||
case PGRES_NONFATAL_ERROR:
|
||||
case PGRES_FATAL_ERROR:
|
||||
case PGRES_BAD_RESPONSE:
|
||||
ECPGlog("ECPGdo line %d: Error: %s",
|
||||
lineno, PQerrorMessage(simple_connection));
|
||||
register_error(-1, "Error: %s line %d.",
|
||||
PQerrorMessage(simple_connection), lineno);
|
||||
break;
|
||||
case PGRES_COPY_OUT:
|
||||
ECPGlog("ECPGdo line %d: Got PGRES_COPY_OUT ... tossing.\n", lineno);
|
||||
PQendcopy(results->conn);
|
||||
break;
|
||||
case PGRES_COPY_IN:
|
||||
ECPGlog("ECPGdo line %d: Got PGRES_COPY_IN ... tossing.\n", lineno);
|
||||
PQendcopy(results->conn);
|
||||
break;
|
||||
default:
|
||||
ECPGlog("ECPGdo line %d: Got something else, postgres error.\n",
|
||||
lineno);
|
||||
register_error(-1, "Postgres error line %d.", lineno);
|
||||
break;
|
||||
}
|
||||
|
||||
/* check for asynchronous returns */
|
||||
notify = PQnotifies(simple_connection);
|
||||
if (notify)
|
||||
{
|
||||
ECPGlog("ECPGdo line %d: ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
|
||||
lineno, notify->relname, notify->be_pid);
|
||||
free(notify);
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ECPGcommit(int lineno)
|
||||
{
|
||||
PGresult *res;
|
||||
|
||||
ECPGlog("ECPGcommit line %d\n", lineno);
|
||||
if ((res = PQexec(simple_connection, "end")) == NULL)
|
||||
{
|
||||
register_error(-1, "Error committing line %d.", lineno);
|
||||
return (FALSE);
|
||||
}
|
||||
PQclear(res);
|
||||
committed = 1;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
bool
|
||||
ECPGrollback(int lineno)
|
||||
{
|
||||
PGresult *res;
|
||||
|
||||
ECPGlog("ECPGrollback line %d\n", lineno);
|
||||
if ((res = PQexec(simple_connection, "abort")) == NULL)
|
||||
{
|
||||
register_error(-1, "Error rolling back line %d.", lineno);
|
||||
return (FALSE);
|
||||
}
|
||||
PQclear(res);
|
||||
committed = 1;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
ECPGsetdb(PGconn *newcon)
|
||||
{
|
||||
ECPGfinish();
|
||||
simple_connection = newcon;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ECPGconnect(const char *dbname)
|
||||
{
|
||||
char *name = strdup(dbname);
|
||||
|
||||
ECPGlog("ECPGconnect: opening database %s\n", name);
|
||||
|
||||
sqlca.sqlcode = 0;
|
||||
|
||||
ECPGsetdb(PQsetdb(NULL, NULL, NULL, NULL, name));
|
||||
|
||||
free(name);
|
||||
name = NULL;
|
||||
|
||||
if (PQstatus(simple_connection) == CONNECTION_BAD)
|
||||
{
|
||||
ECPGfinish();
|
||||
ECPGlog("ECPGconnect: could not open database %s\n", dbname);
|
||||
register_error(-1, "ECPGconnect: could not open database %s.", dbname);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ECPGstatus()
|
||||
{
|
||||
return PQstatus(simple_connection) != CONNECTION_BAD;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ECPGfinish()
|
||||
{
|
||||
if (simple_connection != NULL)
|
||||
{
|
||||
ECPGlog("ECPGfinish: finishing.\n");
|
||||
PQfinish(simple_connection);
|
||||
}
|
||||
else
|
||||
ECPGlog("ECPGfinish: called an extra time.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ECPGdebug(int n, FILE *dbgs)
|
||||
{
|
||||
simple_debug = n;
|
||||
debugstream = dbgs;
|
||||
ECPGlog("ECPGdebug: set to %d\n", simple_debug);
|
||||
}
|
||||
|
||||
void
|
||||
ECPGlog(const char *format,...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (simple_debug)
|
||||
{
|
||||
char *f = (char *) malloc(strlen(format) + 100);
|
||||
|
||||
sprintf(f, "[%d]: %s", getpid(), format);
|
||||
|
||||
va_start(ap, format);
|
||||
vfprintf(debugstream, f, ap);
|
||||
va_end(ap);
|
||||
|
||||
free(f);
|
||||
}
|
||||
}
|
@ -17,6 +17,7 @@ ECPGtype_name(enum ECPGttype typ)
|
||||
case ECPGt_unsigned_long: return "unsigned long";
|
||||
case ECPGt_float: return "float";
|
||||
case ECPGt_double: return "double";
|
||||
case ECPGt_bool: return "bool";
|
||||
default:
|
||||
abort();
|
||||
}
|
@ -1,36 +1,32 @@
|
||||
# Generated automatically from Makefile.in by configure.
|
||||
POSTGRESTOP=@POSTGRESERVER@
|
||||
POSTGRES_BIN=$(POSTGRESTOP)/bin
|
||||
POSTGRES_LIB=$(POSTGRESTOP)/lib
|
||||
SRCDIR= ../../..
|
||||
include $(SRCDIR)/Makefile.global
|
||||
|
||||
CC=gcc
|
||||
LEX=flex
|
||||
LEXLIB=-lfl
|
||||
YACC=bison -y
|
||||
|
||||
YACC=/usr/bin/bison
|
||||
YFLAGS=-y -d
|
||||
|
||||
CFLAGS=-I../include -O2 -g -Wall
|
||||
|
||||
all:: ecpg
|
||||
|
||||
clean::
|
||||
rm -f *.o core a.out ecpg y.tab.h y.tab.c *~
|
||||
clean:
|
||||
rm -f *.o core a.out ecpg preproc.tab.h y.tab.c *~
|
||||
|
||||
install:: all
|
||||
install -c -d -m755 $(POSTGRES_LIB)/ecpg
|
||||
install -c -m555 preproc $(POSTGRES_LIB)/ecpg
|
||||
install -c -m555 ecpg $(POSTGRES_BIN)
|
||||
install: all
|
||||
install -c -m 755 ecpg $(BINDIR)
|
||||
|
||||
uninstall::
|
||||
rm -f $(POSTGRES_BIN)/ecpg
|
||||
rm -f $(POSTGRES_LIB)/ecpg/preproc
|
||||
uninstall:
|
||||
rm -f $(BINDIR)/ecpg
|
||||
|
||||
# Rule that really do something.
|
||||
ecpg: y.tab.o pgc.o type.o ecpg.o
|
||||
$(CC) -g -O2 -Wall -o ecpg y.tab.o pgc.o type.o ecpg.o -L../lib -lecpg $(LEXLIB)
|
||||
|
||||
y.tab.h y.tab.c: preproc.y
|
||||
$(YACC) -d $<
|
||||
$(YACC) $(YFLAGS) $<
|
||||
|
||||
y.tab.o : y.tab.h ../include/ecpgtype.h
|
||||
type.o : ../include/ecpgtype.h
|
32
src/interfaces/ecpg/preproc/Makefile.in
Normal file
32
src/interfaces/ecpg/preproc/Makefile.in
Normal file
@ -0,0 +1,32 @@
|
||||
SRCDIR= ../../..
|
||||
include $(SRCDIR)/Makefile.global
|
||||
|
||||
CC=@CC@
|
||||
LEX=@LEX@
|
||||
LEXLIB=@LEXLIB@
|
||||
YACC=@YACC@
|
||||
YFLAGS=@YFLAGS@
|
||||
|
||||
CFLAGS=-I../include -O2 -g -Wall
|
||||
|
||||
all:: ecpg
|
||||
|
||||
clean:
|
||||
rm -f *.o core a.out ecpg preproc.tab.h y.tab.c *~
|
||||
|
||||
install: all
|
||||
install -c -m 755 ecpg $(BINDIR)
|
||||
|
||||
uninstall:
|
||||
rm -f $(BINDIR)/ecpg
|
||||
|
||||
# Rule that really do something.
|
||||
ecpg: y.tab.o pgc.o type.o ecpg.o
|
||||
$(CC) -g -O2 -Wall -o ecpg y.tab.o pgc.o type.o ecpg.o -L../lib -lecpg $(LEXLIB)
|
||||
|
||||
y.tab.h y.tab.c: preproc.y
|
||||
$(YACC) $(YFLAGS) $<
|
||||
|
||||
y.tab.o : y.tab.h ../include/ecpgtype.h
|
||||
type.o : ../include/ecpgtype.h
|
||||
pgc.o : ../include/ecpgtype.h
|
@ -8,10 +8,9 @@
|
||||
#include <strings.h>
|
||||
|
||||
extern void lex_init(void);
|
||||
extern FILE *yyin,
|
||||
*yyout;
|
||||
|
||||
int yyparse(void);
|
||||
extern FILE *yyin, *yyout;
|
||||
extern char * input_filename;
|
||||
extern int yyparse(void);
|
||||
|
||||
static void
|
||||
usage(char *progname)
|
||||
@ -22,7 +21,8 @@ usage(char *progname)
|
||||
int
|
||||
main(int argc, char *const argv[])
|
||||
{
|
||||
char c, out_option = 0;
|
||||
char c,
|
||||
out_option = 0;
|
||||
int fnr;
|
||||
|
||||
while ((c = getopt(argc, argv, "o:")) != EOF)
|
||||
@ -58,7 +58,8 @@ main(int argc, char *const argv[])
|
||||
|
||||
ptr2ext = strrchr(filename, '.');
|
||||
/* no extension or extension not equal .pgc */
|
||||
if (ptr2ext == NULL || strcmp(ptr2ext, ".pgc") != 0) {
|
||||
if (ptr2ext == NULL || strcmp(ptr2ext, ".pgc") != 0)
|
||||
{
|
||||
ptr2ext = filename + strlen(filename);
|
||||
ptr2ext[0] = '.';
|
||||
}
|
||||
@ -67,17 +68,18 @@ main(int argc, char *const argv[])
|
||||
ptr2ext[1] = 'c';
|
||||
ptr2ext[2] = '\0';
|
||||
|
||||
if (out_option == 0) /* calculate the output name */
|
||||
if (out_option == 0) /* calculate the output name */
|
||||
{
|
||||
yyout = fopen(filename, "w");
|
||||
if (yyout == NULL) {
|
||||
if (yyout == NULL)
|
||||
{
|
||||
perror(filename);
|
||||
free(filename);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
yyin = fopen(argv[fnr], "r");
|
||||
yyin = fopen(input_filename = argv[fnr], "r");
|
||||
if (yyin == NULL)
|
||||
{
|
||||
perror(argv[fnr]);
|
||||
@ -95,7 +97,7 @@ main(int argc, char *const argv[])
|
||||
|
||||
fclose(yyin);
|
||||
if (out_option == 0)
|
||||
fclose (yyout);
|
||||
fclose(yyout);
|
||||
}
|
||||
|
||||
free(filename);
|
@ -3,8 +3,11 @@
|
||||
#include "type.h"
|
||||
#include "y.tab.h"
|
||||
|
||||
#define dbg(arg) fprintf(stderr, "DEBUG: %s\n", #arg);
|
||||
extern int debugging;
|
||||
|
||||
#define dbg(arg) if (debugging) fprintf(stderr, "DEBUG, %d: %s\n", yylineno, #arg);
|
||||
%}
|
||||
%option yylineno
|
||||
%s C SQL
|
||||
ccomment \/\*([^*]|\*[^/]|\*\*[^/])*\*\/
|
||||
ws ([ \t\n][ \t\n]*|{ccomment})*
|
||||
@ -53,7 +56,8 @@ int { dbg(S_INT); return S_INT; }
|
||||
char { dbg(S_CHAR); return S_CHAR; }
|
||||
float { dbg(S_FLOAT); return S_FLOAT; }
|
||||
double { dbg(S_DOUBLE); return S_DOUBLE; }
|
||||
|
||||
bool { dbg(S_BOOL); return S_BOOL; }
|
||||
|
||||
{string} { dbg(SQL_STRING); return SQL_STRING; }
|
||||
<SQL>{ws} ;
|
||||
{symbol} { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
@ -100,12 +104,12 @@ double { dbg(S_DOUBLE); return S_DOUBLE; }
|
||||
. { dbg(.); return S_ANYTHING; }
|
||||
%%
|
||||
void
|
||||
lex_init()
|
||||
lex_init(void)
|
||||
{
|
||||
BEGIN C;
|
||||
}
|
||||
|
||||
int yywrap()
|
||||
int yywrap(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
@ -8,8 +8,26 @@
|
||||
void yyerror(char *);
|
||||
extern FILE * yyout;
|
||||
extern char * yytext;
|
||||
extern int yylineno;
|
||||
extern int yyleng;
|
||||
|
||||
/*
|
||||
* Variables containing simple states.
|
||||
*/
|
||||
int debugging = 0;
|
||||
|
||||
/*
|
||||
* Handle the filename and line numbering.
|
||||
*/
|
||||
char * input_filename = NULL;
|
||||
|
||||
void
|
||||
output_line_number()
|
||||
{
|
||||
if (input_filename)
|
||||
fprintf(yyout, "\n#line %d \"%s\"\n", yylineno, input_filename);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handling of the variables.
|
||||
*/
|
||||
@ -144,7 +162,7 @@ dump_variables(struct arguments * list)
|
||||
%token <tagname> S_VARCHAR S_VARCHAR2
|
||||
%token <tagname> S_EXTERN S_STATIC
|
||||
%token <tagname> S_UNSIGNED S_SIGNED
|
||||
%token <tagname> S_LONG S_SHORT S_INT S_CHAR S_FLOAT S_DOUBLE
|
||||
%token <tagname> S_LONG S_SHORT S_INT S_CHAR S_FLOAT S_DOUBLE S_BOOL
|
||||
%token <tagname> '[' ']' ';' ','
|
||||
|
||||
%type <type> type type_detailed varchar_type simple_type array_type
|
||||
@ -175,10 +193,12 @@ sqldeclaration : sql_startdeclare
|
||||
sql_enddeclare;
|
||||
|
||||
sql_startdeclare : SQL_START SQL_BEGIN SQL_DECLARE SQL_SECTION SQL_SEMI {
|
||||
printf("/* exec sql begin declare section */\n");
|
||||
fprintf(yyout, "/* exec sql begin declare section */\n");
|
||||
output_line_number();
|
||||
};
|
||||
sql_enddeclare : SQL_START SQL_END SQL_DECLARE SQL_SECTION SQL_SEMI {
|
||||
printf("/* exec sql end declare section */\n");
|
||||
fprintf(yyout,"/* exec sql end declare section */\n");
|
||||
output_line_number();
|
||||
};
|
||||
|
||||
variable_declarations : /* empty */
|
||||
@ -235,7 +255,8 @@ simple_tag : S_CHAR { $<type_enum>$ = ECPGt_char; }
|
||||
| S_LONG { $<type_enum>$ = ECPGt_long; }
|
||||
| S_UNSIGNED S_LONG { $<type_enum>$ = ECPGt_unsigned_long; }
|
||||
| S_FLOAT { $<type_enum>$ = ECPGt_float; }
|
||||
| S_DOUBLE { $<type_enum>$ = ECPGt_double; };
|
||||
| S_DOUBLE { $<type_enum>$ = ECPGt_double; }
|
||||
| S_BOOL { $<type_enum>$ = ECPGt_bool; };
|
||||
|
||||
maybe_storage_clause : S_EXTERN { fwrite(yytext, yyleng, 1, yyout); }
|
||||
| S_STATIC { fwrite(yytext, yyleng, 1, yyout); }
|
||||
@ -248,17 +269,17 @@ index : '[' length ']' {
|
||||
length : S_LENGTH { $<indexsize>$ = atoi(yytext); }
|
||||
|
||||
sqlinclude : SQL_START SQL_INCLUDE { fprintf(yyout, "#include \""); }
|
||||
filename SQL_SEMI { fprintf(yyout, ".h\""); };
|
||||
filename SQL_SEMI { fprintf(yyout, ".h\""); output_line_number(); };
|
||||
|
||||
filename : cthing
|
||||
| filename cthing;
|
||||
|
||||
sqlconnect : SQL_START SQL_CONNECT { fprintf(yyout, "ECPGconnect(\""); }
|
||||
SQL_STRING { fwrite(yytext + 1, yyleng - 2, 1, yyout); }
|
||||
SQL_SEMI { fprintf(yyout, "\");"); };
|
||||
SQL_SEMI { fprintf(yyout, "\");"); output_line_number(); };
|
||||
|
||||
/* Open is an open cursor. Removed. */
|
||||
sqlopen : SQL_START SQL_OPEN sqlgarbage SQL_SEMI { };
|
||||
sqlopen : SQL_START SQL_OPEN sqlgarbage SQL_SEMI { output_line_number(); };
|
||||
|
||||
sqlgarbage : /* Empty */
|
||||
| sqlgarbage sqlanything;
|
||||
@ -266,9 +287,11 @@ sqlgarbage : /* Empty */
|
||||
|
||||
sqlcommit : SQL_START SQL_COMMIT SQL_SEMI {
|
||||
fprintf(yyout, "ECPGcommit(__LINE__);");
|
||||
output_line_number();
|
||||
};
|
||||
sqlrollback : SQL_START SQL_ROLLBACK SQL_SEMI {
|
||||
fprintf(yyout, "ECPGrollback(__LINE__);");
|
||||
output_line_number();
|
||||
};
|
||||
|
||||
sqlstatement : SQL_START { /* Reset stack */
|
||||
@ -283,6 +306,7 @@ sqlstatement : SQL_START { /* Reset stack */
|
||||
fprintf(yyout, "ECPGt_EOIT, ");
|
||||
dump_variables(argsresult);
|
||||
fprintf(yyout, "ECPGt_EORT );");
|
||||
output_line_number();
|
||||
};
|
||||
|
||||
sqlstatement_words : sqlstatement_word
|
@ -1,6 +1,5 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "type.h"
|
||||
|
||||
@ -134,55 +133,59 @@ ECPGdump_a_simple(FILE * o, const char * name, enum ECPGttype typ,
|
||||
switch (typ)
|
||||
{
|
||||
case ECPGt_char:
|
||||
fprintf(o, "ECPGt_char,&%s,0,%d,%s, ", name, arrsiz,
|
||||
fprintf(o, "\n\tECPGt_char,&%s,0,%d,%s, ", name, arrsiz,
|
||||
siz == NULL ? "sizeof(char)" : siz);
|
||||
break;
|
||||
case ECPGt_unsigned_char:
|
||||
fprintf(o, "ECPGt_unsigned_char,&%s,0,%d,%s, ", name, arrsiz,
|
||||
fprintf(o, "\n\tECPGt_unsigned_char,&%s,0,%d,%s, ", name, arrsiz,
|
||||
siz == NULL ? "sizeof(unsigned char)" : siz);
|
||||
break;
|
||||
case ECPGt_short:
|
||||
fprintf(o, "ECPGt_short,&%s,0,%d,%s, ", name, arrsiz,
|
||||
fprintf(o, "\n\tECPGt_short,&%s,0,%d,%s, ", name, arrsiz,
|
||||
siz == NULL ? "sizeof(short)" : siz);
|
||||
break;
|
||||
case ECPGt_unsigned_short:
|
||||
fprintf(o,
|
||||
"ECPGt_unsigned_short,&%s,0,%d,%s, ", name, arrsiz,
|
||||
"\n\tECPGt_unsigned_short,&%s,0,%d,%s, ", name, arrsiz,
|
||||
siz == NULL ? "sizeof(unsigned short)" : siz);
|
||||
break;
|
||||
case ECPGt_int:
|
||||
fprintf(o, "ECPGt_int,&%s,0,%d,%s, ", name, arrsiz,
|
||||
fprintf(o, "\n\tECPGt_int,&%s,0,%d,%s, ", name, arrsiz,
|
||||
siz == NULL ? "sizeof(int)" : siz);
|
||||
break;
|
||||
case ECPGt_unsigned_int:
|
||||
fprintf(o, "ECPGt_unsigned_int,&%s,0,%d,%s, ", name, arrsiz,
|
||||
fprintf(o, "\n\tECPGt_unsigned_int,&%s,0,%d,%s, ", name, arrsiz,
|
||||
siz == NULL ? "sizeof(unsigned int)" : siz);
|
||||
break;
|
||||
case ECPGt_long:
|
||||
fprintf(o, "ECPGt_long,&%s,0,%d,%s, ", name, arrsiz,
|
||||
fprintf(o, "\n\tECPGt_long,&%s,0,%d,%s, ", name, arrsiz,
|
||||
siz == NULL ? "sizeof(long)" : siz);
|
||||
break;
|
||||
case ECPGt_unsigned_long:
|
||||
fprintf(o, "ECPGt_unsigned_int,&%s,0,%d,%s, ", name, arrsiz,
|
||||
fprintf(o, "\n\tECPGt_unsigned_int,&%s,0,%d,%s, ", name, arrsiz,
|
||||
siz == NULL ? "sizeof(unsigned int)" : siz);
|
||||
break;
|
||||
case ECPGt_float:
|
||||
fprintf(o, "ECPGt_float,&%s,0,%d,%s, ", name, arrsiz,
|
||||
fprintf(o, "\n\tECPGt_float,&%s,0,%d,%s, ", name, arrsiz,
|
||||
siz == NULL ? "sizeof(float)" : siz);
|
||||
break;
|
||||
case ECPGt_double:
|
||||
fprintf(o, "ECPGt_double,&%s,0,%d,%s, ", name, arrsiz,
|
||||
fprintf(o, "\n\tECPGt_double,&%s,0,%d,%s, ", name, arrsiz,
|
||||
siz == NULL ? "sizeof(double)" : siz);
|
||||
break;
|
||||
case ECPGt_bool:
|
||||
fprintf(o, "\n\tECPGt_bool,&%s,0,%d,%s, ", name, arrsiz,
|
||||
siz == NULL ? "sizeof(bool)" : siz);
|
||||
break;
|
||||
case ECPGt_varchar:
|
||||
case ECPGt_varchar2:
|
||||
if (siz == NULL)
|
||||
fprintf(o, "ECPGt_varchar,&%s,%d,%d,sizeof(struct varchar_%s), ",
|
||||
fprintf(o, "\n\tECPGt_varchar,&%s,%d,%d,sizeof(struct varchar_%s), ",
|
||||
name,
|
||||
varcharsize,
|
||||
arrsiz, name);
|
||||
else
|
||||
fprintf(o, "ECPGt_varchar,&%s,%d,%d,%s, ",
|
||||
fprintf(o, "\n\tECPGt_varchar,&%s,%d,%d,%s, ",
|
||||
name,
|
||||
varcharsize,
|
||||
arrsiz, siz);
|
39
src/interfaces/ecpg/preproc/y.tab.h
Normal file
39
src/interfaces/ecpg/preproc/y.tab.h
Normal file
@ -0,0 +1,39 @@
|
||||
typedef union {
|
||||
int tagname;
|
||||
struct ECPGtemp_type type;
|
||||
char * symbolname;
|
||||
int indexsize;
|
||||
enum ECPGttype type_enum;
|
||||
} YYSTYPE;
|
||||
#define SQL_START 258
|
||||
#define SQL_SEMI 259
|
||||
#define SQL_STRING 260
|
||||
#define SQL_INTO 261
|
||||
#define SQL_BEGIN 262
|
||||
#define SQL_END 263
|
||||
#define SQL_DECLARE 264
|
||||
#define SQL_SECTION 265
|
||||
#define SQL_INCLUDE 266
|
||||
#define SQL_CONNECT 267
|
||||
#define SQL_OPEN 268
|
||||
#define SQL_COMMIT 269
|
||||
#define SQL_ROLLBACK 270
|
||||
#define S_SYMBOL 271
|
||||
#define S_LENGTH 272
|
||||
#define S_ANYTHING 273
|
||||
#define S_VARCHAR 274
|
||||
#define S_VARCHAR2 275
|
||||
#define S_EXTERN 276
|
||||
#define S_STATIC 277
|
||||
#define S_UNSIGNED 278
|
||||
#define S_SIGNED 279
|
||||
#define S_LONG 280
|
||||
#define S_SHORT 281
|
||||
#define S_INT 282
|
||||
#define S_CHAR 283
|
||||
#define S_FLOAT 284
|
||||
#define S_DOUBLE 285
|
||||
#define S_BOOL 286
|
||||
|
||||
|
||||
extern YYSTYPE yylval;
|
@ -1,16 +0,0 @@
|
||||
# Generated automatically from Makefile.in by configure.
|
||||
POSTGRESTOP=@POSTGRESERVER@
|
||||
POSTGRES_INCLUDE=$(POSTGRESTOP)/include
|
||||
|
||||
all clean::
|
||||
@echo Nothing to be done.
|
||||
|
||||
install::
|
||||
install ecpglib.h $(POSTGRES_INCLUDE)
|
||||
install ecpgtype.h $(POSTGRES_INCLUDE)
|
||||
install sqlca.h $(POSTGRES_INCLUDE)
|
||||
|
||||
uninstall::
|
||||
rm -f $(POSTGRES_INCLUDE)/ecpglib.h
|
||||
rm -f $(POSTGRES_INCLUDE)/ecpgtype.h
|
||||
rm -f $(POSTGRES_INCLUDE)/sqlca.h
|
@ -1,15 +0,0 @@
|
||||
POSTGRESTOP=@POSTGRESERVER@
|
||||
POSTGRES_INCLUDE=$(POSTGRESTOP)/include
|
||||
|
||||
all clean::
|
||||
@echo Nothing to be done.
|
||||
|
||||
install::
|
||||
install ecpglib.h $(POSTGRES_INCLUDE)
|
||||
install ecpgtype.h $(POSTGRES_INCLUDE)
|
||||
install sqlca.h $(POSTGRES_INCLUDE)
|
||||
|
||||
uninstall::
|
||||
rm -f $(POSTGRES_INCLUDE)/ecpglib.h
|
||||
rm -f $(POSTGRES_INCLUDE)/ecpgtype.h
|
||||
rm -f $(POSTGRES_INCLUDE)/sqlca.h
|
@ -1,609 +0,0 @@
|
||||
/* Copyright comment */
|
||||
/*
|
||||
* The aim is to get a simpler inteface to the database routines.
|
||||
* All the tidieous messing around with tuples is supposed to be hidden
|
||||
* by this function.
|
||||
*/
|
||||
/* Author: Linus Tolke
|
||||
(actually most if the code is "borrowed" from the distribution and just
|
||||
slightly modified)
|
||||
*/
|
||||
|
||||
/* Taken over as part of PostgreSQL by Michael Meskes <meskes@debian.org>
|
||||
on Feb. 5th, 1998 */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <ecpgtype.h>
|
||||
#include <ecpglib.h>
|
||||
#include <sqlca.h>
|
||||
#include <libpq-fe.h>
|
||||
#include <libpq/pqcomm.h>
|
||||
|
||||
static PGconn * simple_connection;
|
||||
static int simple_debug = 0;
|
||||
static int committed = true;
|
||||
|
||||
static void
|
||||
register_error(int code, char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
sqlca.sqlcode = code;
|
||||
va_start (args, fmt);
|
||||
vsprintf (sqlca.sqlerrm.sqlerrmc, fmt, args);
|
||||
va_end (args);
|
||||
sqlca.sqlerrm.sqlerrml = strlen (sqlca.sqlerrm.sqlerrmc);
|
||||
}
|
||||
|
||||
/* This function returns a newly malloced string that has the ' and \
|
||||
in the argument quoted with \.
|
||||
*/
|
||||
static
|
||||
char *
|
||||
quote_postgres(char * arg)
|
||||
{
|
||||
char * res = (char *)malloc(2 * strlen(arg) + 1);
|
||||
int i, ri;
|
||||
|
||||
for (i = 0, ri = 0; arg[i]; i++, ri++)
|
||||
{
|
||||
switch (arg[i])
|
||||
{
|
||||
case '\'':
|
||||
case '\\':
|
||||
res[ri++] = '\\';
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
res[ri] = arg[i];
|
||||
}
|
||||
res[ri] = '\0';
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ECPGdo(int lineno, char * query, ...)
|
||||
{
|
||||
va_list ap;
|
||||
bool status = false;
|
||||
char * copiedquery;
|
||||
PGresult * results;
|
||||
PGnotify * notify;
|
||||
enum ECPGttype type;
|
||||
|
||||
va_start(ap, query);
|
||||
|
||||
sqlca.sqlcode = 0;
|
||||
copiedquery = strdup(query);
|
||||
|
||||
type = va_arg(ap, enum ECPGttype);
|
||||
|
||||
/*
|
||||
* Now, if the type is one of the fill in types then we take the argument
|
||||
* and enter that in the string at the first %s position. Then if there
|
||||
* are any more fill in types we fill in at the next and so on.
|
||||
*/
|
||||
while (type != ECPGt_EOIT)
|
||||
{
|
||||
void * value = NULL;
|
||||
short varcharsize;
|
||||
short size;
|
||||
short arrsize;
|
||||
|
||||
char * newcopy;
|
||||
char * mallocedval = NULL;
|
||||
char * tobeinserted = NULL;
|
||||
char * p;
|
||||
char buff[20];
|
||||
|
||||
/* Some special treatment is needed for records since we want their
|
||||
contents to arrive in a comma-separated list on insert (I think). */
|
||||
|
||||
value = va_arg(ap, void *);
|
||||
varcharsize = va_arg(ap, short);
|
||||
size = va_arg(ap, short);
|
||||
arrsize = va_arg(ap, short);
|
||||
|
||||
switch (type) {
|
||||
case ECPGt_char:
|
||||
case ECPGt_short:
|
||||
case ECPGt_int:
|
||||
sprintf(buff, "%d", *(int*)value);
|
||||
tobeinserted = buff;
|
||||
break;
|
||||
|
||||
case ECPGt_unsigned_char:
|
||||
case ECPGt_unsigned_short:
|
||||
case ECPGt_unsigned_int:
|
||||
sprintf(buff, "%d", *(unsigned int*)value);
|
||||
tobeinserted = buff;
|
||||
break;
|
||||
|
||||
case ECPGt_long:
|
||||
sprintf(buff, "%ld", *(long*)value);
|
||||
tobeinserted = buff;
|
||||
break;
|
||||
|
||||
case ECPGt_unsigned_long:
|
||||
sprintf(buff, "%ld", *(unsigned long*)value);
|
||||
tobeinserted = buff;
|
||||
break;
|
||||
|
||||
case ECPGt_float:
|
||||
sprintf(buff, "%.14g", *(float*)value);
|
||||
tobeinserted = buff;
|
||||
break;
|
||||
|
||||
case ECPGt_double:
|
||||
sprintf(buff, "%.14g", *(double*)value);
|
||||
tobeinserted = buff;
|
||||
break;
|
||||
|
||||
case ECPGt_varchar:
|
||||
case ECPGt_varchar2:
|
||||
{
|
||||
struct ECPGgeneric_varchar * var =
|
||||
(struct ECPGgeneric_varchar*)value;
|
||||
|
||||
newcopy = (char *)malloc(var->len + 1);
|
||||
strncpy(newcopy, var->arr, var->len);
|
||||
newcopy[var->len] = '\0';
|
||||
|
||||
mallocedval = (char *)malloc(2 * strlen(newcopy) + 3);
|
||||
strcpy(mallocedval, "'");
|
||||
strcat(mallocedval, quote_postgres(newcopy));
|
||||
strcat(mallocedval, "'");
|
||||
|
||||
free(newcopy);
|
||||
|
||||
tobeinserted = mallocedval;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Not implemented yet */
|
||||
register_error(-1, "Unsupported type %s on line %d.",
|
||||
ECPGtype_name(type), lineno);
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Now tobeinserted points to an area that is to be inserted at
|
||||
the first %s
|
||||
*/
|
||||
newcopy = (char *)malloc(strlen(copiedquery)
|
||||
+ strlen(tobeinserted)
|
||||
+ 1);
|
||||
strcpy(newcopy, copiedquery);
|
||||
if ((p = strstr(newcopy, ";;")) == NULL)
|
||||
{
|
||||
/* We have an argument but we dont have the matched up string
|
||||
in the string
|
||||
*/
|
||||
register_error(-1, "Too many arguments line %d.", lineno);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(p, tobeinserted);
|
||||
/* The strange thing in the second argument is the rest of the
|
||||
string from the old string */
|
||||
strcat(newcopy,
|
||||
copiedquery
|
||||
+ ( p - newcopy )
|
||||
+ 2 /* Length of ;; */);
|
||||
}
|
||||
|
||||
/* Now everything is safely copied to the newcopy. Lets free the
|
||||
oldcopy and let the copiedquery get the value from the newcopy.
|
||||
*/
|
||||
if (mallocedval != NULL)
|
||||
{
|
||||
free(mallocedval);
|
||||
mallocedval = NULL;
|
||||
}
|
||||
|
||||
free(copiedquery);
|
||||
copiedquery = newcopy;
|
||||
|
||||
type = va_arg(ap, enum ECPGttype);
|
||||
}
|
||||
|
||||
/* Check if there are unmatched things left. */
|
||||
if (strstr(copiedquery, ";;") != NULL)
|
||||
{
|
||||
register_error(-1, "Too few arguments line %d.", lineno);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Now then request is built. */
|
||||
|
||||
if (committed)
|
||||
{
|
||||
if ((results = PQexec (simple_connection, "begin")) == NULL) {
|
||||
register_error(-1, "Error starting transaction line %d.", lineno);
|
||||
return false;
|
||||
}
|
||||
PQclear (results);
|
||||
committed = 0;
|
||||
}
|
||||
|
||||
ECPGlog("ECPGdo line %d: QUERY: %s\n", lineno, copiedquery);
|
||||
results = PQexec(simple_connection, copiedquery);
|
||||
free(copiedquery);
|
||||
|
||||
if (results == NULL)
|
||||
{
|
||||
ECPGlog("ECPGdo line %d: error: %s", lineno,
|
||||
PQerrorMessage(simple_connection));
|
||||
register_error(-1, "Postgres error: %s line %d.",
|
||||
PQerrorMessage(simple_connection), lineno);
|
||||
}
|
||||
else switch(PQresultStatus(results))
|
||||
{
|
||||
int m,n,x;
|
||||
|
||||
case PGRES_TUPLES_OK:
|
||||
/* XXX Cheap Hack. For now, we see only the last group
|
||||
* of tuples. This is clearly not the right
|
||||
* way to do things !!
|
||||
*/
|
||||
|
||||
m = PQnfields(results);
|
||||
n = PQntuples(results);
|
||||
|
||||
if (n < 1)
|
||||
{
|
||||
ECPGlog("ECPGdo lineno %d: Incorrect number of matches: %d\n",
|
||||
lineno, n);
|
||||
register_error(1, "Data not found line %d.", lineno);
|
||||
break;
|
||||
}
|
||||
|
||||
if (n > 1)
|
||||
{
|
||||
ECPGlog("ECPGdo line %d: Incorrect number of matches: %d\n",
|
||||
lineno, n);
|
||||
register_error(-1, "To many matches line %d.", lineno);
|
||||
break;
|
||||
}
|
||||
|
||||
status = true;
|
||||
|
||||
for (x = 0; x < m && status; x++)
|
||||
{
|
||||
void * value = NULL;
|
||||
short varcharsize;
|
||||
short size;
|
||||
short arrsize;
|
||||
|
||||
char *pval = PQgetvalue(results,0,x);
|
||||
/*long int * res_int;
|
||||
char ** res_charstar;
|
||||
char * res_char;
|
||||
int res_len;*/
|
||||
char * scan_length;
|
||||
|
||||
ECPGlog("ECPGdo line %d: RESULT: %s\n", lineno, pval ? pval : "");
|
||||
|
||||
/* No the pval is a pointer to the value. */
|
||||
/* We will have to decode the value */
|
||||
type = va_arg(ap, enum ECPGttype);
|
||||
value = va_arg(ap, void *);
|
||||
varcharsize = va_arg(ap, short);
|
||||
size = va_arg(ap, short);
|
||||
arrsize = va_arg(ap, short);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
long res;
|
||||
unsigned long ures;
|
||||
double dres;
|
||||
|
||||
case ECPGt_char:
|
||||
case ECPGt_short:
|
||||
case ECPGt_int:
|
||||
case ECPGt_long:
|
||||
if (pval)
|
||||
{
|
||||
res = strtol(pval, &scan_length, 10);
|
||||
if (*scan_length != '\0') /* Garbage left */
|
||||
{
|
||||
register_error(-1, "Not correctly formatted int type: %s line %d.",
|
||||
pval, lineno);
|
||||
status = false;
|
||||
res = 0L;
|
||||
}
|
||||
}
|
||||
else
|
||||
res = 0L;
|
||||
|
||||
/* Again?! Yes */
|
||||
switch (type)
|
||||
{
|
||||
case ECPGt_char:
|
||||
*(char *)value = (char)res;
|
||||
break;
|
||||
case ECPGt_short:
|
||||
*(short *)value = (short)res;
|
||||
break;
|
||||
case ECPGt_int:
|
||||
*(int *)value = (int)res;
|
||||
break;
|
||||
case ECPGt_long:
|
||||
*(long *)value = res;
|
||||
break;
|
||||
default:
|
||||
/* Cannot happen */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case ECPGt_unsigned_char:
|
||||
case ECPGt_unsigned_short:
|
||||
case ECPGt_unsigned_int:
|
||||
case ECPGt_unsigned_long:
|
||||
if (pval)
|
||||
{
|
||||
ures = strtoul(pval, &scan_length, 10);
|
||||
if (*scan_length != '\0') /* Garbage left */
|
||||
{
|
||||
register_error(-1, "Not correctly formatted unsigned type: %s line %d.",
|
||||
pval, lineno);
|
||||
status = false;
|
||||
ures = 0L;
|
||||
}
|
||||
}
|
||||
else
|
||||
ures = 0L;
|
||||
|
||||
/* Again?! Yes */
|
||||
switch (type)
|
||||
{
|
||||
case ECPGt_unsigned_char:
|
||||
*(unsigned char *)value = (unsigned char)ures;
|
||||
break;
|
||||
case ECPGt_unsigned_short:
|
||||
*(unsigned short *)value = (unsigned short)ures;
|
||||
break;
|
||||
case ECPGt_unsigned_int:
|
||||
*(unsigned int *)value = (unsigned int)ures;
|
||||
break;
|
||||
case ECPGt_unsigned_long:
|
||||
*(unsigned long *)value = ures;
|
||||
break;
|
||||
default:
|
||||
/* Cannot happen */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case ECPGt_float:
|
||||
case ECPGt_double:
|
||||
if (pval)
|
||||
{
|
||||
dres = strtod(pval, &scan_length);
|
||||
if (*scan_length != '\0') /* Garbage left */
|
||||
{
|
||||
register_error(-1, "Not correctly formatted floating point type: %s line %d.",
|
||||
pval, lineno);
|
||||
status = false;
|
||||
dres = 0.0;
|
||||
}
|
||||
}
|
||||
else
|
||||
dres = 0.0;
|
||||
|
||||
/* Again?! Yes */
|
||||
switch (type)
|
||||
{
|
||||
case ECPGt_float:
|
||||
*(float *)value = (float)res;
|
||||
break;
|
||||
case ECPGt_double:
|
||||
*(double *)value = res;
|
||||
break;
|
||||
default:
|
||||
/* Cannot happen */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case ECPGt_varchar:
|
||||
{
|
||||
struct ECPGgeneric_varchar * var =
|
||||
(struct ECPGgeneric_varchar*)value;
|
||||
|
||||
strncpy(var->arr, pval, varcharsize);
|
||||
var->len = strlen(pval);
|
||||
if (var->len > varcharsize)
|
||||
var->len = varcharsize;
|
||||
}
|
||||
break;
|
||||
|
||||
case ECPGt_EORT:
|
||||
ECPGlog("ECPGdo line %d: Too few arguments.\n", lineno);
|
||||
register_error(-1, "Too few arguments line %d.", lineno);
|
||||
status = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
register_error(-1, "Unsupported type %s on line %d.",
|
||||
ECPGtype_name(type), lineno);
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
type = va_arg(ap, enum ECPGttype);
|
||||
|
||||
if (status && type != ECPGt_EORT)
|
||||
{
|
||||
register_error(-1, "Too many arguments line %d.", lineno);
|
||||
return false;
|
||||
}
|
||||
|
||||
PQclear(results);
|
||||
break;
|
||||
case PGRES_EMPTY_QUERY:
|
||||
/* do nothing */
|
||||
register_error(-1, "Empty query line %d.", lineno);
|
||||
break;
|
||||
case PGRES_COMMAND_OK:
|
||||
status = true;
|
||||
ECPGlog("ECPGdo line %d Ok: %s\n", lineno, PQcmdStatus(results));
|
||||
break;
|
||||
case PGRES_NONFATAL_ERROR:
|
||||
case PGRES_FATAL_ERROR:
|
||||
case PGRES_BAD_RESPONSE:
|
||||
ECPGlog("ECPGdo line %d: Error: %s",
|
||||
lineno, PQerrorMessage(simple_connection));
|
||||
register_error(-1, "Error: %s line %d.",
|
||||
PQerrorMessage(simple_connection), lineno);
|
||||
break;
|
||||
case PGRES_COPY_OUT:
|
||||
ECPGlog("ECPGdo line %d: Got PGRES_COPY_OUT ... tossing.\n", lineno);
|
||||
PQendcopy(results->conn);
|
||||
break;
|
||||
case PGRES_COPY_IN:
|
||||
ECPGlog("ECPGdo line %d: Got PGRES_COPY_IN ... tossing.\n", lineno);
|
||||
PQendcopy(results->conn);
|
||||
break;
|
||||
default:
|
||||
ECPGlog("ECPGdo line %d: Got something else, postgres error.\n",
|
||||
lineno);
|
||||
register_error(-1, "Postgres error line %d.", lineno);
|
||||
break;
|
||||
}
|
||||
|
||||
/* check for asynchronous returns */
|
||||
notify = PQnotifies(simple_connection);
|
||||
if (notify) {
|
||||
ECPGlog("ECPGdo line %d: ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
|
||||
lineno, notify->relname, notify->be_pid);
|
||||
free(notify);
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ECPGcommit(int lineno)
|
||||
{
|
||||
PGresult *res;
|
||||
|
||||
ECPGlog("ECPGcommit line %d\n", lineno);
|
||||
if ((res = PQexec (simple_connection, "end")) == NULL) {
|
||||
register_error(-1, "Error committing line %d.", lineno);
|
||||
return (FALSE);
|
||||
}
|
||||
PQclear (res);
|
||||
committed = 1;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
bool
|
||||
ECPGrollback(int lineno)
|
||||
{
|
||||
PGresult *res;
|
||||
|
||||
ECPGlog("ECPGrollback line %d\n", lineno);
|
||||
if ((res = PQexec (simple_connection, "abort")) == NULL) {
|
||||
register_error(-1, "Error rolling back line %d.", lineno);
|
||||
return (FALSE);
|
||||
}
|
||||
PQclear (res);
|
||||
committed = 1;
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
ECPGsetdb(PGconn * newcon)
|
||||
{
|
||||
ECPGfinish();
|
||||
simple_connection = newcon;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ECPGconnect(const char * dbname)
|
||||
{
|
||||
char * name = strdup(dbname);
|
||||
ECPGlog("ECPGconnect: opening database %s\n", name);
|
||||
|
||||
sqlca.sqlcode = 0;
|
||||
|
||||
ECPGsetdb(PQsetdb(NULL, NULL, NULL, NULL, name));
|
||||
|
||||
free(name);
|
||||
name = NULL;
|
||||
|
||||
if (PQstatus(simple_connection) == CONNECTION_BAD)
|
||||
{
|
||||
ECPGfinish();
|
||||
ECPGlog("ECPGconnect: could not open database %s\n", dbname);
|
||||
register_error(-1, "ECPGconnect: could not open database %s.", dbname);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ECPGstatus()
|
||||
{
|
||||
return PQstatus(simple_connection) != CONNECTION_BAD;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ECPGfinish()
|
||||
{
|
||||
if (simple_connection != NULL)
|
||||
{
|
||||
ECPGlog("ECPGfinish: finishing.\n");
|
||||
PQfinish(simple_connection);
|
||||
}
|
||||
else
|
||||
ECPGlog("ECPGfinish: called an extra time.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ECPGdebug(int n)
|
||||
{
|
||||
simple_debug = n;
|
||||
ECPGlog("ECPGdebug: set to %d\n", simple_debug);
|
||||
}
|
||||
|
||||
void
|
||||
ECPGlog(const char * format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
if (simple_debug)
|
||||
{
|
||||
char * f = (char *) malloc(strlen(format) + 100);
|
||||
|
||||
sprintf(f, "[%d]: %s", getpid(), format);
|
||||
|
||||
va_start(ap, format);
|
||||
vfprintf(stderr, f, ap);
|
||||
va_end(ap);
|
||||
|
||||
free(f);
|
||||
}
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
POSTGRESTOP=@POSTGRESERVER@
|
||||
POSTGRES_BIN=$(POSTGRESTOP)/bin
|
||||
POSTGRES_LIB=$(POSTGRESTOP)/lib
|
||||
|
||||
CC=@CC@
|
||||
LEX=@LEX@
|
||||
LEXLIB=@LEXLIB@
|
||||
YACC=@YACC@
|
||||
|
||||
|
||||
CFLAGS=-I../include -O2 -g -Wall
|
||||
|
||||
all:: ecpg
|
||||
|
||||
clean::
|
||||
rm -f *.o core a.out ecpg y.tab.h y.tab.c *~
|
||||
|
||||
install:: all
|
||||
install -c -d -m755 $(POSTGRES_LIB)/ecpg
|
||||
install -c -m555 preproc $(POSTGRES_LIB)/ecpg
|
||||
install -c -m555 ecpg $(POSTGRES_BIN)
|
||||
|
||||
uninstall::
|
||||
rm -f $(POSTGRES_BIN)/ecpg
|
||||
rm -f $(POSTGRES_LIB)/ecpg/preproc
|
||||
|
||||
# Rule that really do something.
|
||||
ecpg: y.tab.o pgc.o type.o ecpg.o
|
||||
$(CC) -g -O2 -Wall -o ecpg y.tab.o pgc.o type.o ecpg.o -L../lib -lecpg $(LEXLIB)
|
||||
|
||||
y.tab.h y.tab.c: preproc.y
|
||||
$(YACC) -d $<
|
||||
|
||||
y.tab.o : y.tab.h ../include/ecpgtype.h
|
||||
type.o : ../include/ecpgtype.h
|
||||
pgc.o : ../include/ecpgtype.h
|
@ -1,31 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
INFILE=
|
||||
OUTFILE=
|
||||
|
||||
for arg
|
||||
do
|
||||
case "$arg" in
|
||||
iname=*)
|
||||
INFILE=`expr substr $arg 7 1000`
|
||||
;;
|
||||
oname=*)
|
||||
OUTFILE=`expr substr $arg 7 1000`
|
||||
;;
|
||||
*)
|
||||
echo Wrong argument $arg
|
||||
exit 1;
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -n "$INFILE" -a -n "$OUTFILE" ]
|
||||
then
|
||||
exec @POSTGRESERVER@/lib/ecpg/preproc < $INFILE > $OUTFILE
|
||||
else
|
||||
echo Missing arguments.
|
||||
echo usage: $0 iname=file oname=outfile
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
exit 0;
|
@ -1,6 +0,0 @@
|
||||
test2: test2.c
|
||||
gcc -g -I ../include -I ../../../libpq -o test2 test2.c ../lib/libecpg.a ../../../libpq/libpq.a -lcrypt
|
||||
test2.c: test2.pgc
|
||||
../preproc/ecpg test2.pgc
|
||||
clean:
|
||||
/bin/rm test2 test2.c
|
Binary file not shown.
14
src/interfaces/ecpg/test/Makefile
Normal file
14
src/interfaces/ecpg/test/Makefile
Normal file
@ -0,0 +1,14 @@
|
||||
all: test2 perftest
|
||||
|
||||
test2: test2.c
|
||||
gcc -g -I ../include -I ../../../libpq -o test2 test2.c ../lib/libecpg.a ../../../libpq/libpq.a -lcrypt
|
||||
test2.c: test2.pgc
|
||||
../preproc/ecpg test2.pgc
|
||||
|
||||
perftest: perftest.c
|
||||
gcc -g -I ../include -I ../../../libpq -o perftest perftest.c ../lib/libecpg.a ../../../libpq/libpq.a -lcrypt
|
||||
perftest.c: perftest.pgc
|
||||
../preproc/ecpg perftest.pgc
|
||||
|
||||
clean:
|
||||
/bin/rm test2 test2.c perftest perftest.c
|
72
src/interfaces/ecpg/test/perftest.pgc
Normal file
72
src/interfaces/ecpg/test/perftest.pgc
Normal file
@ -0,0 +1,72 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
exec sql include sqlca;
|
||||
|
||||
#define SQLCODE sqlca.sqlcode
|
||||
|
||||
void
|
||||
db_error (char *msg)
|
||||
{
|
||||
sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml] = '\0';
|
||||
printf ("%s: db error %s\n", msg, sqlca.sqlerrm.sqlerrmc);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
exec sql begin declare section;
|
||||
long i;
|
||||
exec sql end declare section;
|
||||
struct timeval tvs, tve;
|
||||
|
||||
gettimeofday(&tvs, NULL);
|
||||
|
||||
exec sql connect 'mm';
|
||||
if (SQLCODE)
|
||||
db_error ("connect");
|
||||
|
||||
exec sql create table perftest(number int4, ascii char16);
|
||||
if (SQLCODE)
|
||||
db_error ("create t");
|
||||
|
||||
exec sql create unique index number on perftest(number);
|
||||
if (SQLCODE)
|
||||
db_error ("create i");
|
||||
|
||||
for (i = 0;i < 1407; i++)
|
||||
{
|
||||
exec sql begin declare section;
|
||||
char text[16];
|
||||
exec sql end declare section;
|
||||
|
||||
sprintf(text, "%ld", i);
|
||||
exec sql insert into perftest(number, ascii) values (:i, :text);
|
||||
if (SQLCODE)
|
||||
db_error ("insert");
|
||||
|
||||
exec sql commit;
|
||||
if (SQLCODE)
|
||||
db_error ("commit");
|
||||
}
|
||||
|
||||
exec sql drop index number;
|
||||
if (SQLCODE)
|
||||
db_error ("drop i");
|
||||
|
||||
exec sql drop table perftest;
|
||||
if (SQLCODE)
|
||||
db_error ("drop t");
|
||||
|
||||
exec sql commit;
|
||||
if (SQLCODE)
|
||||
db_error ("commit");
|
||||
|
||||
gettimeofday(&tve, NULL);
|
||||
|
||||
printf("I needed %ld seconds and %ld microseconds for this test\n", tve.tv_sec - tvs.tv_sec, tve.tv_usec - tvs.tv_usec);
|
||||
|
||||
return (0);
|
||||
}
|
50
src/interfaces/ecpg/test/test2.pgc
Normal file
50
src/interfaces/ecpg/test/test2.pgc
Normal file
@ -0,0 +1,50 @@
|
||||
exec sql include sqlca;
|
||||
|
||||
#define SQLCODE sqlca.sqlcode
|
||||
|
||||
void
|
||||
db_error (char *msg)
|
||||
{
|
||||
sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml] = '\0';
|
||||
printf ("%s: db error %s\n", msg, sqlca.sqlerrm.sqlerrmc);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
exec sql begin declare section;
|
||||
varchar text[8];
|
||||
int count;
|
||||
double control;
|
||||
exec sql end declare section;
|
||||
|
||||
exec sql connect 'mm';
|
||||
if (SQLCODE)
|
||||
db_error ("connect");
|
||||
|
||||
exec sql declare cur cursor for
|
||||
select text, control, count from test;
|
||||
if (SQLCODE) db_error ("declare");
|
||||
|
||||
exec sql open cur;
|
||||
if (SQLCODE)
|
||||
db_error ("open");
|
||||
|
||||
while (1) {
|
||||
exec sql fetch in cur into :text, :control, :count;
|
||||
if (SQLCODE)
|
||||
break;
|
||||
printf ("%8.8s %d %f\n", text.arr, count, control);
|
||||
}
|
||||
|
||||
if (SQLCODE < 0)
|
||||
db_error ("fetch");
|
||||
|
||||
exec sql close cur;
|
||||
if (SQLCODE) db_error ("close");
|
||||
exec sql commit;
|
||||
if (SQLCODE) db_error ("commit");
|
||||
|
||||
return (0);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user