summaryrefslogtreecommitdiff
path: root/src/interfaces/ecpg/lib/ecpglib.c
diff options
context:
space:
mode:
authorMichael Meskes2000-03-07 15:11:03 +0000
committerMichael Meskes2000-03-07 15:11:03 +0000
commit5a197810c09da06a772c235a6bba68290745d74c (patch)
treedd0053c6d2c99e6f9dc980a350623b30f3ae9496 /src/interfaces/ecpg/lib/ecpglib.c
parentad3db67e5311590d42b8c5fce2a8ee2116678923 (diff)
*** empty log message ***
Diffstat (limited to 'src/interfaces/ecpg/lib/ecpglib.c')
-rw-r--r--src/interfaces/ecpg/lib/ecpglib.c1261
1 files changed, 0 insertions, 1261 deletions
diff --git a/src/interfaces/ecpg/lib/ecpglib.c b/src/interfaces/ecpg/lib/ecpglib.c
deleted file mode 100644
index fddb36c3caa..00000000000
--- a/src/interfaces/ecpg/lib/ecpglib.c
+++ /dev/null
@@ -1,1261 +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 <[email protected]>
- on Feb. 5th, 1998 */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdarg.h>
-#include <string.h>
-#include <ctype.h>
-#include <locale.h>
-
-#include <libpq/pqcomm.h>
-#include <ecpgtype.h>
-#include <ecpglib.h>
-#include <sqlca.h>
-#include <sql3types.h>
-
-/* variables visible to the programs */
-static struct sqlca sqlca_init =
-{
- {'S', 'Q', 'L', 'C', 'A', ' ', ' ', ' '},
- sizeof(struct sqlca),
- 0,
- {0, {0}},
- {'N', 'O', 'T', ' ', 'S', 'E', 'T', ' '},
- {0, 0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0, 0, 0, 0}
-};
-
-struct sqlca sqlca =
-{
- {'S', 'Q', 'L', 'C', 'A', ' ', ' ', ' '},
- sizeof(struct sqlca),
- 0,
- {0, {0}},
- {'N', 'O', 'T', ' ', 'S', 'E', 'T', ' '},
- {0, 0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0, 0, 0, 0}
-};
-
-static struct connection
-{
- char *name;
- PGconn *connection;
- bool committed;
- int autocommit;
- struct connection *next;
-} *all_connections = NULL, *actual_connection = NULL;
-
-struct variable
-{
- enum ECPGttype type;
- void *value;
- void *pointer;
- long varcharsize;
- long arrsize;
- long offset;
- enum ECPGttype ind_type;
- void *ind_value;
- long ind_varcharsize;
- long ind_arrsize;
- long ind_offset;
- struct variable *next;
-};
-
-struct auto_mem *auto_allocs;
-
-static int simple_debug = 0;
-static FILE *debugstream = NULL;
-
-static struct connection *
-get_connection(const char *connection_name)
-{
- struct connection *con = all_connections;
-
- if (connection_name == NULL || strcmp(connection_name, "CURRENT") == 0)
- return actual_connection;
-
- for (; con && strcmp(connection_name, con->name) != 0; con = con->next);
- if (con)
- return con;
- else
- return NULL;
-}
-
-static bool
-ecpg_init(const struct connection *con, const char * connection_name, const int lineno)
-{
- memcpy((char *) &sqlca, (char *) &sqlca_init, sizeof(sqlca));
- if (con == NULL)
- {
- ECPGraise(lineno, ECPG_NO_CONN, connection_name ? connection_name : "NULL");
- return (false);
- }
-
- auto_allocs = NULL;
-
- return (true);
-}
-
-static void
-ecpg_finish(struct connection * act)
-{
- if (act != NULL)
- {
- ECPGlog("ecpg_finish: finishing %s.\n", act->name);
- PQfinish(act->connection);
- /* remove act from the list */
- if (act == all_connections)
- all_connections = act->next;
- else
- {
- struct connection *con;
-
- for (con = all_connections; con->next && con->next != act; con = con->next);
- if (con->next)
- con->next = act->next;
- }
-
- if (actual_connection == act)
- actual_connection = all_connections;
-
- free(act->name);
- free(act);
- }
- else
- ECPGlog("ecpg_finish: called an extra time.\n");
-}
-
-static void
-add_mem(void *ptr, int lineno)
-{
- struct auto_mem *am = (struct auto_mem *) ecpg_alloc(sizeof(struct auto_mem), lineno);
-
- am->next = auto_allocs;
- auto_allocs = am;
-}
-
-/* This function returns a newly malloced string that has the \
- in the argument quoted with \ and the ' quote with ' as SQL92 says.
- */
-static
-char *
-quote_postgres(char *arg, int lineno)
-{
- char *res = (char *) ecpg_alloc(2 * strlen(arg) + 3, lineno);
- int i,
- ri = 0;
-
- if (!res)
- return (res);
-
- res[ri++] = '\'';
- for (i = 0; arg[i]; i++, ri++)
- {
- switch (arg[i])
- {
- case '\'':
- res[ri++] = '\'';
- break;
- case '\\':
- res[ri++] = '\\';
- break;
- default:
- ;
- }
-
- res[ri] = arg[i];
- }
- res[ri++] = '\'';
- res[ri] = '\0';
-
- return res;
-}
-
-/*
- * create a list of variables
- * The variables are listed with input variables preceeding outputvariables
- * The end of each group is marked by an end marker.
- * per variable we list:
- * type - as defined in ecpgtype.h
- * value - where to store the data
- * varcharsize - length of string in case we have a stringvariable, else 0
- * arraysize - 0 for pointer (we don't know the size of the array),
- * 1 for simple variable, size for arrays
- * offset - offset between ith and (i+1)th entry in an array,
- * normally that means sizeof(type)
- * ind_type - type of indicator variable
- * ind_value - pointer to indicator variable
- * ind_varcharsize - empty
- * ind_arraysize - arraysize of indicator array
- * ind_offset - indicator offset
- */
-static bool
-create_statement(int lineno, struct connection * connection, struct statement ** stmt, char *query, va_list ap)
-{
- struct variable **list = &((*stmt)->inlist);
- enum ECPGttype type;
-
- if (!(*stmt = (struct statement *) ecpg_alloc(sizeof(struct statement), lineno)))
- return false;
-
- (*stmt)->command = query;
- (*stmt)->connection = connection;
- (*stmt)->lineno = lineno;
-
- list = &((*stmt)->inlist);
-
- type = va_arg(ap, enum ECPGttype);
-
- while (type != ECPGt_EORT)
- {
- if (type == ECPGt_EOIT)
- list = &((*stmt)->outlist);
- else
- {
- struct variable *var,
- *ptr;
-
- if (!(var = (struct variable *) ecpg_alloc(sizeof(struct variable), lineno)))
- return false;
-
- var->type = type;
- var->pointer = va_arg(ap, void *);
-
- /* if variable is NULL, the statement hasn't been prepared */
- if (var->pointer == NULL)
- {
- ECPGlog("create_statement: invalid statement name\n");
- ECPGraise(lineno, ECPG_INVALID_STMT, NULL);
- free(var);
- return false;
- }
-
- var->varcharsize = va_arg(ap, long);
- var->arrsize = va_arg(ap, long);
- var->offset = va_arg(ap, long);
-
- if (var->arrsize == 0 || var->varcharsize == 0)
- var->value = *((void **) (var->pointer));
- else
- var->value = var->pointer;
-
- var->ind_type = va_arg(ap, enum ECPGttype);
- var->ind_value = va_arg(ap, void *);
- var->ind_varcharsize = va_arg(ap, long);
- var->ind_arrsize = va_arg(ap, long);
- var->ind_offset = va_arg(ap, long);
- var->next = NULL;
-
- for (ptr = *list; ptr && ptr->next; ptr = ptr->next);
-
- if (ptr == NULL)
- *list = var;
- else
- ptr->next = var;
- }
-
- type = va_arg(ap, enum ECPGttype);
- }
-
- return (true);
-}
-
-static void
-free_variable(struct variable * var)
-{
- struct variable *var_next;
-
- if (var == (struct variable *) NULL)
- return;
- var_next = var->next;
- free(var);
-
- while (var_next)
- {
- var = var_next;
- var_next = var->next;
- free(var);
- }
-}
-
-static void
-free_statement(struct statement * stmt)
-{
- if (stmt == (struct statement *) NULL)
- return;
- free_variable(stmt->inlist);
- free_variable(stmt->outlist);
- free(stmt);
-}
-
-static char *
-next_insert(char *text)
-{
- char *ptr = text;
- bool string = false;
-
- for (; *ptr != '\0' && (*ptr != '?' || string); ptr++)
- if (*ptr == '\'' && *(ptr-1) != '\\')
- string = string ? false : true;
-
- return (*ptr == '\0') ? NULL : ptr;
-}
-
-static bool
-ECPGexecute(struct statement * stmt)
-{
- bool status = false;
- char *copiedquery;
- PGresult *results, *query;
- PGnotify *notify;
- struct variable *var;
-
- copiedquery = ecpg_strdup(stmt->command, stmt->lineno);
-
- /*
- * 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.
- */
- var = stmt->inlist;
- while (var)
- {
- 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).
- */
-
- buff[0] = '\0';
-
- /* check for null value and set input buffer accordingly */
- switch (var->ind_type)
- {
- case ECPGt_short:
- case ECPGt_unsigned_short:
- if (*(short *) var->ind_value < 0)
- strcpy(buff, "null");
- break;
- case ECPGt_int:
- case ECPGt_unsigned_int:
- if (*(int *) var->ind_value < 0)
- strcpy(buff, "null");
- break;
- case ECPGt_long:
- case ECPGt_unsigned_long:
- if (*(long *) var->ind_value < 0L)
- strcpy(buff, "null");
- break;
- default:
- break;
- }
-
- if (*buff == '\0')
- {
- switch (var->type)
- {
- int element;
-
- case ECPGt_short:
- if (!(mallocedval = ecpg_alloc(var->arrsize * 20, stmt->lineno)))
- return false;
-
- sprintf(mallocedval, "%s", (var->arrsize > 1) ? "'{" : "");
-
- for (element = 0; element < var->arrsize; element++)
- sprintf(mallocedval + strlen(mallocedval), "%d,", ((short *) var->value)[element]);
-
- sprintf(mallocedval + strlen(mallocedval) - 1, "%s", (var->arrsize > 1) ? "}'" : "");
-
- tobeinserted = mallocedval;
- break;
-
- case ECPGt_int:
- if (!(mallocedval = ecpg_alloc(var->arrsize * 20, stmt->lineno)))
- return false;
-
- sprintf(mallocedval, "%s", (var->arrsize > 1) ? "'{" : "");
-
- for (element = 0; element < var->arrsize; element++)
- sprintf(mallocedval + strlen(mallocedval), "%d,", ((int *) var->value)[element]);
-
- sprintf(mallocedval + strlen(mallocedval) - 1, "%s", (var->arrsize > 1) ? "}'" : "");
-
- tobeinserted = mallocedval;
- break;
-
- case ECPGt_unsigned_short:
- if (!(mallocedval = ecpg_alloc(var->arrsize * 20, stmt->lineno)))
- return false;
-
- sprintf(mallocedval, "%s", (var->arrsize > 1) ? "'{" : "");
-
- for (element = 0; element < var->arrsize; element++)
- sprintf(mallocedval + strlen(mallocedval), "%d,", ((unsigned short *) var->value)[element]);
-
- sprintf(mallocedval + strlen(mallocedval) - 1, "%s", (var->arrsize > 1) ? "}'" : "");
-
- tobeinserted = mallocedval;
- break;
-
- case ECPGt_unsigned_int:
- if (!(mallocedval = ecpg_alloc(var->arrsize * 20, stmt->lineno)))
- return false;
-
- sprintf(mallocedval, "%s", (var->arrsize > 1) ? "'{" : "");
-
- for (element = 0; element < var->arrsize; element++)
- sprintf(mallocedval + strlen(mallocedval), "%d,", ((unsigned int *) var->value)[element]);
-
- sprintf(mallocedval + strlen(mallocedval) - 1, "%s", (var->arrsize > 1) ? "}'" : "");
-
- tobeinserted = mallocedval;
- break;
-
- case ECPGt_long:
- if (!(mallocedval = ecpg_alloc(var->arrsize * 20, stmt->lineno)))
- return false;
-
- sprintf(mallocedval, "%s", (var->arrsize > 1) ? "'{" : "");
-
- for (element = 0; element < var->arrsize; element++)
- sprintf(mallocedval + strlen(mallocedval), "%ld,", ((long *) var->value)[element]);
-
- sprintf(mallocedval + strlen(mallocedval) - 1, "%s", (var->arrsize > 1) ? "}'" : "");
-
- tobeinserted = mallocedval;
- break;
-
- case ECPGt_unsigned_long:
- if (!(mallocedval = ecpg_alloc(var->arrsize * 20, stmt->lineno)))
- return false;
-
- sprintf(mallocedval, "%s", (var->arrsize > 1) ? "'{" : "");
-
- for (element = 0; element < var->arrsize; element++)
- sprintf(mallocedval + strlen(mallocedval), "%ld,", ((unsigned long *) var->value)[element]);
-
- sprintf(mallocedval + strlen(mallocedval) - 1, "%s", (var->arrsize > 1) ? "}'" : "");
-
- tobeinserted = mallocedval;
- break;
-
- case ECPGt_float:
- if (!(mallocedval = ecpg_alloc(var->arrsize * 20, stmt->lineno)))
- return false;
-
- sprintf(mallocedval, "%s", (var->arrsize > 1) ? "'{" : "");
-
- for (element = 0; element < var->arrsize; element++)
- sprintf(mallocedval + strlen(mallocedval), "%.14g,", ((float *) var->value)[element]);
-
- sprintf(mallocedval + strlen(mallocedval) - 1, "%s", (var->arrsize > 1) ? "}'" : "");
-
- tobeinserted = mallocedval;
- break;
-
- case ECPGt_double:
- if (!(mallocedval = ecpg_alloc(var->arrsize * 20, stmt->lineno)))
- return false;
-
- sprintf(mallocedval, "%s", (var->arrsize > 1) ? "'{" : "");
-
- for (element = 0; element < var->arrsize; element++)
- sprintf(mallocedval + strlen(mallocedval), "%.14g,", ((double *) var->value)[element]);
-
- sprintf(mallocedval + strlen(mallocedval) - 1, "%s", (var->arrsize > 1) ? "}'" : "");
-
- tobeinserted = mallocedval;
- break;
-
- case ECPGt_bool:
- if (!(mallocedval = ecpg_alloc(var->arrsize * 20, stmt->lineno)))
- return false;
-
- sprintf(mallocedval, "%s", (var->arrsize > 1) ? "'{" : "");
-
- for (element = 0; element < var->arrsize; element++)
- sprintf(mallocedval + strlen(mallocedval), "%c,", (((char *) var->value)[element]) ? 't' : 'f');
-
- sprintf(mallocedval + strlen(mallocedval) - 1, "%s", (var->arrsize > 1) ? "}'" : "");
-
- tobeinserted = mallocedval;
- break;
-
- case ECPGt_char:
- case ECPGt_unsigned_char:
- {
- /* set slen to string length if type is char * */
- int slen = (var->varcharsize == 0) ? strlen((char *) var->value) : var->varcharsize;
-
- if (!(newcopy = ecpg_alloc(slen + 1, stmt->lineno)))
- return false;
-
- strncpy(newcopy, (char *) var->value, slen);
- newcopy[slen] = '\0';
-
- mallocedval = quote_postgres(newcopy, stmt->lineno);
- if (!mallocedval)
- return false;
-
- free(newcopy);
-
- tobeinserted = mallocedval;
- }
- break;
- case ECPGt_char_variable:
- {
- int slen = strlen((char *) var->value);
-
- if (!(mallocedval = ecpg_alloc(slen + 1, stmt->lineno)))
- return false;
-
- strncpy(mallocedval, (char *) var->value, slen);
- mallocedval[slen] = '\0';
-
- tobeinserted = mallocedval;
- }
- break;
- case ECPGt_varchar:
- {
- struct ECPGgeneric_varchar *variable =
- (struct ECPGgeneric_varchar *) (var->value);
-
- if (!(newcopy = (char *) ecpg_alloc(variable->len + 1, stmt->lineno)))
- return false;
-
- strncpy(newcopy, variable->arr, variable->len);
- newcopy[variable->len] = '\0';
-
- mallocedval = quote_postgres(newcopy, stmt->lineno);
- if (!mallocedval)
- return false;
-
- free(newcopy);
-
- tobeinserted = mallocedval;
- }
- break;
-
- default:
- /* Not implemented yet */
- ECPGraise(stmt->lineno, ECPG_UNSUPPORTED, ECPGtype_name(var->type));
- return false;
- break;
- }
- }
- else
- tobeinserted = buff;
-
- /*
- * Now tobeinserted points to an area that is to be inserted at
- * the first %s
- */
- if (!(newcopy = (char *) ecpg_alloc(strlen(copiedquery) + strlen(tobeinserted) + 1, stmt->lineno)))
- return false;
-
- strcpy(newcopy, copiedquery);
- if ((p = next_insert(newcopy)) == NULL)
- {
-
- /*
- * We have an argument but we dont have the matched up string
- * in the string
- */
- ECPGraise(stmt->lineno, ECPG_TOO_MANY_ARGUMENTS, NULL);
- 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)
- + sizeof("?") - 1 /* don't count the '\0' */ );
- }
-
- /*
- * Now everything is safely copied to the newcopy. Lets free the
- * oldcopy and let the copiedquery get the var->value from the
- * newcopy.
- */
- if (mallocedval != NULL)
- {
- free(mallocedval);
- mallocedval = NULL;
- }
-
- free(copiedquery);
- copiedquery = newcopy;
-
- var = var->next;
- }
-
- /* Check if there are unmatched things left. */
- if (next_insert(copiedquery) != NULL)
- {
- ECPGraise(stmt->lineno, ECPG_TOO_FEW_ARGUMENTS, NULL);
- return false;
- }
-
- /* Now the request is built. */
-
- if (stmt->connection->committed && !stmt->connection->autocommit)
- {
- if ((results = PQexec(stmt->connection->connection, "begin transaction")) == NULL)
- {
- ECPGraise(stmt->lineno, ECPG_TRANS, NULL);
- return false;
- }
- PQclear(results);
- stmt->connection->committed = false;
- }
-
- ECPGlog("ECPGexecute line %d: QUERY: %s on connection %s\n", stmt->lineno, copiedquery, stmt->connection->name);
- results = PQexec(stmt->connection->connection, copiedquery);
- free(copiedquery);
-
- if (results == NULL)
- {
- ECPGlog("ECPGexecute line %d: error: %s", stmt->lineno,
- PQerrorMessage(stmt->connection->connection));
- ECPGraise(stmt->lineno, ECPG_PGSQL, PQerrorMessage(stmt->connection->connection));
- }
- else
- {
- var = stmt->outlist;
- switch (PQresultStatus(results))
- {
- int nfields,
- ntuples,
- act_tuple,
- act_field,
- isarray;
-
- case PGRES_TUPLES_OK:
- nfields = PQnfields(results);
- sqlca.sqlerrd[2] = ntuples = PQntuples(results);
- status = true;
-
- if (ntuples < 1)
- {
- ECPGlog("ECPGexecute line %d: Incorrect number of matches: %d\n",
- stmt->lineno, ntuples);
- ECPGraise(stmt->lineno, ECPG_NOT_FOUND, NULL);
- status = false;
- break;
- }
-
- for (act_field = 0; act_field < nfields && status; act_field++)
- {
- char *array_query;
-
- if (var == NULL)
- {
- ECPGlog("ECPGexecute line %d: Too few arguments.\n", stmt->lineno);
- ECPGraise(stmt->lineno, ECPG_TOO_FEW_ARGUMENTS, NULL);
- return (false);
- }
-
- array_query = (char *)ecpg_alloc(strlen("select typelem from pg_type where oid=") + 11, stmt -> lineno);
- sprintf(array_query, "select typelem from pg_type where oid=%d", PQftype(results, act_field));
- query = PQexec(stmt->connection->connection, array_query);
- isarray = 0;
- if (PQresultStatus(query) == PGRES_TUPLES_OK) {
- isarray = atol((char *)PQgetvalue(query, 0, 0));
- if (ECPGDynamicType(PQftype(results, act_field)) == SQL3_CHARACTER ||
- ECPGDynamicType(PQftype(results, act_field)) == SQL3_CHARACTER_VARYING)
- {
- /* arrays of character strings are not yet implemented */
- isarray = false;
- }
- ECPGlog("ECPGexecute line %d: TYPE database: %d C: %d array: %s\n", stmt->lineno, PQftype(results, act_field), var->type, isarray ? "yes" : "no");
- }
- PQclear(query);
-
- if (!isarray)
- {
- /*
- * if we don't have enough space, we cannot read all
- * tuples
- */
- if ((var->arrsize > 0 && ntuples > var->arrsize) || (var->ind_arrsize > 0 && ntuples > var->ind_arrsize))
- {
- ECPGlog("ECPGexecute line %d: Incorrect number of matches: %d don't fit into array of %d\n",
- stmt->lineno, ntuples, var->arrsize);
- ECPGraise(stmt->lineno, ECPG_TOO_MANY_MATCHES, NULL);
- status = false;
- break;
- }
- }
- else
- {
- /*
- * since we read an array, the variable has to be
- * an array too
- */
- if (var->arrsize == 0)
- {
- ECPGlog("ECPGexecute line %d: variable is not an array\n");
- ECPGraise(stmt->lineno, ECPG_NO_ARRAY, NULL);
- status = false;
- break;
- }
- }
-
- /*
- * allocate memory for NULL pointers
- */
- if ((var->arrsize == 0 || var->varcharsize == 0) && var->value == NULL)
- {
- int len = 0;
-
- switch (var->type)
- {
- case ECPGt_char:
- case ECPGt_unsigned_char:
- var->varcharsize = 0;
- /* check strlen for each tuple */
- for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
- {
- int len = strlen(PQgetvalue(results, act_tuple, act_field)) + 1;
-
- if (len > var->varcharsize)
- var->varcharsize = len;
- }
- var->offset *= var->varcharsize;
- len = var->offset * ntuples;
- break;
- case ECPGt_varchar:
- len = ntuples * (var->varcharsize + sizeof(int));
- break;
- default:
- len = var->offset * ntuples;
- break;
- }
- var->value = (void *) ecpg_alloc(len, stmt->lineno);
- *((void **) var->pointer) = var->value;
- add_mem(var->value, stmt->lineno);
- }
-
- for (act_tuple = 0; act_tuple < ntuples && status; act_tuple++)
- {
- if (!get_data(results, act_tuple, act_field, stmt->lineno,
- var->type, var->ind_type, var->value,
- var->ind_value, var->varcharsize, var->offset, isarray))
- status = false;
- }
- var = var->next;
- }
-
- if (status && var != NULL)
- {
- ECPGraise(stmt->lineno, ECPG_TOO_MANY_ARGUMENTS, NULL);
- status = false;
- }
-
- break;
- case PGRES_EMPTY_QUERY:
- /* do nothing */
- ECPGraise(stmt->lineno, ECPG_EMPTY, NULL);
- break;
- case PGRES_COMMAND_OK:
- status = true;
- sqlca.sqlerrd[1] = atol(PQoidStatus(results));
- sqlca.sqlerrd[2] = atol(PQcmdTuples(results));
- ECPGlog("ECPGexecute line %d Ok: %s\n", stmt->lineno, PQcmdStatus(results));
- break;
- case PGRES_NONFATAL_ERROR:
- case PGRES_FATAL_ERROR:
- case PGRES_BAD_RESPONSE:
- ECPGlog("ECPGexecute line %d: Error: %s",
- stmt->lineno, PQerrorMessage(stmt->connection->connection));
- ECPGraise(stmt->lineno, ECPG_PGSQL, PQerrorMessage(stmt->connection->connection));
- status = false;
- break;
- case PGRES_COPY_OUT:
- ECPGlog("ECPGexecute line %d: Got PGRES_COPY_OUT ... tossing.\n", stmt->lineno);
- PQendcopy(stmt->connection->connection);
- break;
- case PGRES_COPY_IN:
- ECPGlog("ECPGexecute line %d: Got PGRES_COPY_IN ... tossing.\n", stmt->lineno);
- PQendcopy(stmt->connection->connection);
- break;
- default:
- ECPGlog("ECPGexecute line %d: Got something else, postgres error.\n",
- stmt->lineno);
- ECPGraise(stmt->lineno, ECPG_PGSQL, PQerrorMessage(stmt->connection->connection));
- status = false;
- break;
- }
- PQclear(results);
- }
-
- /* check for asynchronous returns */
- notify = PQnotifies(stmt->connection->connection);
- if (notify)
- {
- ECPGlog("ECPGexecute line %d: ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
- stmt->lineno, notify->relname, notify->be_pid);
- free(notify);
- }
-
- return status;
-}
-
-bool
-ECPGdo(int lineno, const char *connection_name, char *query, ...)
-{
- va_list args;
- struct statement *stmt;
- struct connection *con = get_connection(connection_name);
- bool status=true;
- char *locale = setlocale(LC_NUMERIC, NULL);
-
- /* Make sure we do NOT honor the locale for numeric input/output */
- /* since the database wants teh standard decimal point */
- setlocale(LC_NUMERIC, "C");
-
- if (!ecpg_init(con, connection_name, lineno))
- {
- setlocale(LC_NUMERIC, locale);
- return(false);
- }
-
- va_start(args, query);
- if (create_statement(lineno, con, &stmt, query, args) == false)
- {
- setlocale(LC_NUMERIC, locale);
- return (false);
- }
- va_end(args);
-
- /* are we connected? */
- if (con == NULL || con->connection == NULL)
- {
- free_statement(stmt);
- ECPGlog("ECPGdo: not connected to %s\n", con->name);
- ECPGraise(lineno, ECPG_NOT_CONN, NULL);
- setlocale(LC_NUMERIC, locale);
- return false;
- }
-
- status = ECPGexecute(stmt);
- free_statement(stmt);
-
- /* and reset locale value so our application is not affected */
- setlocale(LC_NUMERIC, locale);
- return (status);
-}
-
-bool
-ECPGstatus(int lineno, const char *connection_name)
-{
- struct connection *con = get_connection(connection_name);
-
- if (!ecpg_init(con, connection_name, lineno))
- return(false);
-
- /* are we connected? */
- if (con->connection == NULL)
- {
- ECPGlog("ECPGdo: not connected to %s\n", con->name);
- ECPGraise(lineno, ECPG_NOT_CONN, NULL);
- return false;
- }
-
- return (true);
-}
-
-bool
-ECPGtrans(int lineno, const char *connection_name, const char *transaction)
-{
- PGresult *res;
- struct connection *con = get_connection(connection_name);
-
- if (!ecpg_init(con, connection_name, lineno))
- return(false);
-
- ECPGlog("ECPGtrans line %d action = %s connection = %s\n", lineno, transaction, con->name);
-
- /* if we have no connection we just simulate the command */
- if (con && con->connection)
- {
- if ((res = PQexec(con->connection, transaction)) == NULL)
- {
- ECPGraise(lineno, ECPG_TRANS, NULL);
- return FALSE;
- }
- PQclear(res);
- }
-
- if (strcmp(transaction, "commit") == 0 || strcmp(transaction, "rollback") == 0)
- {
- con->committed = true;
-
- /* deallocate all prepared statements */
- if (!ECPGdeallocate_all(lineno))
- return false;
- }
-
- return true;
-}
-
-bool
-ECPGsetcommit(int lineno, const char *mode, const char *connection_name)
-{
- struct connection *con = get_connection(connection_name);
- PGresult *results;
-
- if (!ecpg_init(con, connection_name, lineno))
- return(false);
-
- ECPGlog("ECPGsetcommit line %d action = %s connection = %s\n", lineno, mode, con->name);
-
- if (con->autocommit == true && strncmp(mode, "off", strlen("off")) == 0)
- {
- if (con->committed)
- {
- if ((results = PQexec(con->connection, "begin transaction")) == NULL)
- {
- ECPGraise(lineno, ECPG_TRANS, NULL);
- return false;
- }
- PQclear(results);
- con->committed = false;
- }
- con->autocommit = false;
- }
- else if (con->autocommit == false && strncmp(mode, "on", strlen("on")) == 0)
- {
- if (!con->committed)
- {
- if ((results = PQexec(con->connection, "commit")) == NULL)
- {
- ECPGraise(lineno, ECPG_TRANS, NULL);
- return false;
- }
- PQclear(results);
- con->committed = true;
- }
- con->autocommit = true;
- }
-
- return true;
-}
-
-bool
-ECPGsetconn(int lineno, const char *connection_name)
-{
- struct connection *con = get_connection(connection_name);
-
- if (!ecpg_init(con, connection_name, lineno))
- return(false);
-
- actual_connection = con;
- return true;
-}
-
-bool
-ECPGconnect(int lineno, const char *dbname, const char *user, const char *passwd, const char *connection_name, int autocommit)
-{
- struct connection *this;
-
-
- memcpy((char *) &sqlca, (char *) &sqlca_init, sizeof(sqlca));
-
- if ((this = (struct connection *) ecpg_alloc(sizeof(struct connection), lineno)) == NULL)
- return false;
-
- if (dbname == NULL && connection_name == NULL)
- connection_name = "DEFAULT";
-
- /* add connection to our list */
- if (connection_name != NULL)
- this->name = ecpg_strdup(connection_name, lineno);
- else
- this->name = ecpg_strdup(dbname, lineno);
-
- 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 : "<DEFAULT>", user ? "for user " : "", user ? user : "");
-
- this->connection = PQsetdbLogin(NULL, NULL, NULL, NULL, dbname, user, passwd);
-
- if (PQstatus(this->connection) == CONNECTION_BAD)
- {
- ecpg_finish(this);
- ECPGlog("connect: could not open database %s %s%s in line %d\n", dbname ? dbname : "<DEFAULT>", user ? "for user " : "", user ? user : "", lineno);
- ECPGraise(lineno, ECPG_CONNECT, dbname ? dbname : "<DEFAULT>");
- return false;
- }
-
- this->committed = true;
- this->autocommit = autocommit;
-
- return true;
-}
-
-bool
-ECPGdisconnect(int lineno, const char *connection_name)
-{
- struct connection *con;
-
- if (strcmp(connection_name, "ALL") == 0)
- {
- memcpy((char *) &sqlca, (char *) &sqlca_init, sizeof(sqlca));
- for (con = all_connections; con;)
- {
- struct connection *f = con;
-
- con = con->next;
- ecpg_finish(f);
- }
- }
- else
- {
- con = get_connection(connection_name);
-
- if (!ecpg_init(con, connection_name, lineno))
- return(false);
- else
- ecpg_finish(con);
- }
-
- 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);
-
- if (!f)
- return;
-
- sprintf(f, "[%d]: %s", (int) getpid(), format);
-
- va_start(ap, format);
- vfprintf(debugstream, f, ap);
- va_end(ap);
-
- free(f);
- }
-}
-
-/* dynamic SQL support routines
- *
- * Copyright (c) 2000, Christof Petig <[email protected]>
- *
- * $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/ecpglib.c,v 1.62 2000/03/03 14:39:26 meskes Exp $
- */
-
-PGconn *ECPG_internal_get_connection(char *name);
-
-extern struct descriptor
-{
- char *name;
- PGresult *result;
- struct descriptor *next;
-} *all_descriptors;
-
-// like ECPGexecute
-static bool execute_descriptor(int lineno,const char *query
- ,struct connection *con,PGresult **resultptr)
-{
- bool status = false;
- PGresult *results;
- PGnotify *notify;
-
- /* Now the request is built. */
-
- if (con->committed && !con->autocommit)
- {
- if ((results = PQexec(con->connection, "begin transaction")) == NULL)
- {
- ECPGraise(lineno, ECPG_TRANS, NULL);
- return false;
- }
- PQclear(results);
- con->committed = false;
- }
-
- ECPGlog("execute_descriptor line %d: QUERY: %s on connection %s\n", lineno, query, con->name);
- results = PQexec(con->connection, query);
-
- if (results == NULL)
- {
- ECPGlog("ECPGexecute line %d: error: %s", lineno,
- PQerrorMessage(con->connection));
- ECPGraise(lineno, ECPG_PGSQL, PQerrorMessage(con->connection));
- }
- else
- { *resultptr=results;
- switch (PQresultStatus(results))
- { int ntuples;
- case PGRES_TUPLES_OK:
- status = true;
- sqlca.sqlerrd[2] = ntuples = PQntuples(results);
- if (ntuples < 1)
- {
- ECPGlog("execute_descriptor line %d: Incorrect number of matches: %d\n",
- lineno, ntuples);
- ECPGraise(lineno, ECPG_NOT_FOUND, NULL);
- status = false;
- break;
- }
- break;
-#if 1 /* strictly these are not needed (yet) */
- case PGRES_EMPTY_QUERY:
- /* do nothing */
- ECPGraise(lineno, ECPG_EMPTY, NULL);
- break;
- case PGRES_COMMAND_OK:
- status = true;
- sqlca.sqlerrd[1] = atol(PQoidStatus(results));
- sqlca.sqlerrd[2] = atol(PQcmdTuples(results));
- ECPGlog("ECPGexecute line %d Ok: %s\n", lineno, PQcmdStatus(results));
- break;
- case PGRES_COPY_OUT:
- ECPGlog("ECPGexecute line %d: Got PGRES_COPY_OUT ... tossing.\n", lineno);
- PQendcopy(con->connection);
- break;
- case PGRES_COPY_IN:
- ECPGlog("ECPGexecute line %d: Got PGRES_COPY_IN ... tossing.\n", lineno);
- PQendcopy(con->connection);
- break;
-#else
- case PGRES_EMPTY_QUERY:
- case PGRES_COMMAND_OK:
- case PGRES_COPY_OUT:
- case PGRES_COPY_IN:
- break;
-#endif
- case PGRES_NONFATAL_ERROR:
- case PGRES_FATAL_ERROR:
- case PGRES_BAD_RESPONSE:
- ECPGlog("ECPGexecute line %d: Error: %s",
- lineno, PQerrorMessage(con->connection));
- ECPGraise(lineno, ECPG_PGSQL, PQerrorMessage(con->connection));
- status = false;
- break;
- default:
- ECPGlog("ECPGexecute line %d: Got something else, postgres error.\n",
- lineno);
- ECPGraise(lineno, ECPG_PGSQL, PQerrorMessage(con->connection));
- status = false;
- break;
- }
- }
-
- /* check for asynchronous returns */
- notify = PQnotifies(con->connection);
- if (notify)
- {
- ECPGlog("ECPGexecute line %d: ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
- lineno, notify->relname, notify->be_pid);
- free(notify);
- }
- return status;
-}
-
-/* like ECPGdo */
-static bool do_descriptor2(int lineno,const char *connection_name,
- PGresult **resultptr, const char *query)
-{
- struct connection *con = get_connection(connection_name);
- bool status=true;
- char *locale = setlocale(LC_NUMERIC, NULL);
-
- /* Make sure we do NOT honor the locale for numeric input/output */
- /* since the database wants teh standard decimal point */
- setlocale(LC_NUMERIC, "C");
-
- if (!ecpg_init(con, connection_name, lineno))
- { setlocale(LC_NUMERIC, locale);
- return(false);
- }
-
- /* are we connected? */
- if (con == NULL || con->connection == NULL)
- {
- ECPGlog("do_descriptor2: not connected to %s\n", con->name);
- ECPGraise(lineno, ECPG_NOT_CONN, NULL);
- setlocale(LC_NUMERIC, locale);
- return false;
- }
-
- status = execute_descriptor(lineno,query,con,resultptr);
-
- /* and reset locale value so our application is not affected */
- setlocale(LC_NUMERIC, locale);
- return (status);
-}
-
-bool ECPGdo_descriptor(int line,const char *connection,
- const char *descriptor,const char *query)
-{
- struct descriptor *i;
- for (i=all_descriptors;i!=NULL;i=i->next)
- { if (!strcmp(descriptor,i->name))
- {
- bool status;
-
- /* free previous result */
- if (i->result) PQclear(i->result);
- i->result=NULL;
-
- status=do_descriptor2(line,connection,&i->result,query);
-
- if (!i->result) PQmakeEmptyPGresult(NULL, 0);
- return (status);
- }
- }
-
- ECPGraise(line, ECPG_UNKNOWN_DESCRIPTOR, descriptor);
- return false;
-}