diff --git a/src/interfaces/ecpg/ChangeLog b/src/interfaces/ecpg/ChangeLog index 647f649438a..82d28b80bc5 100644 --- a/src/interfaces/ecpg/ChangeLog +++ b/src/interfaces/ecpg/ChangeLog @@ -933,5 +933,12 @@ Mon Sep 4 14:10:38 PDT 2000 Mon Sep 18 13:55:11 PDT 2000 - Added int8 support based on a patch by Martijn Schoemaker + +Mit Sep 20 12:40:27 PDT 2000 + + - Added patch by Christof Petig to process + backend NOTICEs. + - Added patch by Christof Petig to cache + type information. - Set ecpg version to 2.8.0. - Set library version to 3.2.0. diff --git a/src/interfaces/ecpg/include/ecpgerrno.h b/src/interfaces/ecpg/include/ecpgerrno.h index 2a826988be5..58e70a0752b 100644 --- a/src/interfaces/ecpg/include/ecpgerrno.h +++ b/src/interfaces/ecpg/include/ecpgerrno.h @@ -43,4 +43,19 @@ #define ECPG_TRANS -401 #define ECPG_CONNECT -402 +/* backend notices, starting at 600 */ +#define ECPG_NOTICE_UNRECOGNIZED -600 + /* NOTICE: (transaction aborted): queries ignored until END */ + /* NOTICE: current transaction is aborted, queries ignored until end of transaction block */ +#define ECPG_NOTICE_QUERY_IGNORED -601 + /* NOTICE: PerformPortalClose: portal "*" not found */ +#define ECPG_NOTICE_UNKNOWN_PORTAL -602 + /* NOTICE: BEGIN: already a transaction in progress */ +#define ECPG_NOTICE_IN_TRANSACTION -603 + /* NOTICE: AbortTransaction and not in in-progress state */ + /* NOTICE: COMMIT: no transaction in progress */ +#define ECPG_NOTICE_NO_TRANSACTION -604 + /* NOTICE: BlankPortalAssignName: portal * already exists */ +#define ECPG_NOTICE_PORTAL_EXISTS -605 + #endif /* !_ECPG_ERROR_H */ diff --git a/src/interfaces/ecpg/include/sqlca.h b/src/interfaces/ecpg/include/sqlca.h index da1fdee4f35..9bc958a1af7 100644 --- a/src/interfaces/ecpg/include/sqlca.h +++ b/src/interfaces/ecpg/include/sqlca.h @@ -22,23 +22,22 @@ extern "C" long sqlerrd[6]; /* Element 0: empty */ /* 1: OID of processed tuple if applicable */ - /* 2: number of rows processed */ - /* after an INSERT, UPDATE or */ - /* DELETE statement */ + /* 2: number of rows processed */ + /* after an INSERT, UPDATE or */ + /* DELETE statement */ /* 3: empty */ /* 4: empty */ /* 5: empty */ char sqlwarn[8]; - /* Element 0: set to 'W' if at least one other is 'W' */ - /* 1: if 'W' at least one character string */ - /* value was truncated when it was */ - /* stored into a host variable. */ - /* 2: empty */ - /* 3: empty */ - /* 4: empty */ - /* 5: empty */ - /* 6: empty */ - /* 7: empty */ + /* Element 0: set to 'W' if at least one other is 'W' */ + /* 1: if 'W' at least one character string */ + /* value was truncated when it was */ + /* stored into a host variable. */ + /* 2: if 'W' a (hopefully) non-fatal notice occured */ /* 3: empty */ + /* 4: empty */ + /* 5: empty */ + /* 6: empty */ + /* 7: empty */ char sqlext[8]; }; diff --git a/src/interfaces/ecpg/lib/connect.c b/src/interfaces/ecpg/lib/connect.c index 416fcf17dd4..59a3f794851 100644 --- a/src/interfaces/ecpg/lib/connect.c +++ b/src/interfaces/ecpg/lib/connect.c @@ -27,6 +27,8 @@ ecpg_finish(struct connection * act) { if (act != NULL) { + struct ECPGtype_information_cache *cache, *ptr; + ECPGlog("ecpg_finish: finishing %s.\n", act->name); PQfinish(act->connection); @@ -45,6 +47,7 @@ ecpg_finish(struct connection * act) if (actual_connection == act) actual_connection = all_connections; + for (cache = act->cache_head; cache; ptr = cache, cache = cache->next, free(ptr)); free(act->name); free(act); } @@ -107,6 +110,120 @@ ECPGsetconn(int lineno, const char *connection_name) return true; } +static void +ECPGnoticeProcessor_raise(int code, const char *message) +{ + sqlca.sqlcode = code; + strncpy(sqlca.sqlerrm.sqlerrmc, message, sizeof(sqlca.sqlerrm.sqlerrmc)); + sqlca.sqlerrm.sqlerrmc[sizeof(sqlca.sqlerrm.sqlerrmc)-1]=0; + sqlca.sqlerrm.sqlerrml = strlen(sqlca.sqlerrm.sqlerrmc); + + // remove trailing newline + if (sqlca.sqlerrm.sqlerrml + && sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml-1]=='\n') + { + sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml-1]=0; + sqlca.sqlerrm.sqlerrml--; + } + + ECPGlog("raising sqlcode %d\n",code); +} + +/* + * I know this is a mess, but we can't redesign the backend + */ + +static void +ECPGnoticeProcessor(void *arg, const char *message) +{ + /* these notices raise an error */ + if (strncmp(message,"NOTICE: ",8)) + { + ECPGlog("ECPGnoticeProcessor: strange notice '%s'\n", message); + ECPGnoticeProcessor_raise(ECPG_NOTICE_UNRECOGNIZED, message); + return; + } + + message+=8; + while (*message==' ') message++; + ECPGlog("NOTICE: %s", message); + + /* NOTICE: (transaction aborted): queries ignored until END */ + /* NOTICE: current transaction is aborted, queries ignored until end of transaction block */ + if (strstr(message,"queries ignored") && strstr(message,"transaction") + && strstr(message,"aborted")) + { + ECPGnoticeProcessor_raise(ECPG_NOTICE_QUERY_IGNORED, message); + return; + } + + /* NOTICE: PerformPortalClose: portal "*" not found */ + if (!strncmp(message,"PerformPortalClose: portal",26) + && strstr(message+26,"not found")) + { + ECPGnoticeProcessor_raise(ECPG_NOTICE_UNKNOWN_PORTAL, message); + return; + } + + /* NOTICE: BEGIN: already a transaction in progress */ + if (!strncmp(message,"BEGIN: already a transaction in progress",40)) + { + ECPGnoticeProcessor_raise(ECPG_NOTICE_IN_TRANSACTION, message); + return; + } + + /* NOTICE: AbortTransaction and not in in-progress state */ + /* NOTICE: COMMIT: no transaction in progress */ + /* NOTICE: ROLLBACK: no transaction in progress */ + if (!strncmp(message,"AbortTransaction and not in in-progress state",45) + || !strncmp(message,"COMMIT: no transaction in progress",34) + || !strncmp(message,"ROLLBACK: no transaction in progress",36)) + { + ECPGnoticeProcessor_raise(ECPG_NOTICE_NO_TRANSACTION, message); + return; + } + + /* NOTICE: BlankPortalAssignName: portal * already exists */ + if (!strncmp(message,"BlankPortalAssignName: portal",29) + && strstr(message+29,"already exists")) + { + ECPGnoticeProcessor_raise(ECPG_NOTICE_PORTAL_EXISTS, message); + return; + } + + /* these are harmless - do nothing */ + /* NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index '*' for table '*' */ + /* NOTICE: ALTER TABLE ... ADD CONSTRAINT will create implicit trigger(s) for FOREIGN KEY check(s) */ + /* NOTICE: CREATE TABLE will create implicit sequence '*' for SERIAL column '*.*' */ + /* NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) */ + if ((!strncmp(message,"CREATE TABLE",12) || !strncmp(message,"ALTER TABLE",11)) + && strstr(message+11,"will create implicit")) + return; + + /* NOTICE: QUERY PLAN: */ + if (!strncmp(message,"QUERY PLAN:",11)) // do we really see these? + return; + + /* NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "*" */ + if (!strncmp(message,"DROP TABLE implicitly drops",27)) + return; + + /* NOTICE: Caution: DROP INDEX cannot be rolled back, so don't abort now */ + if (strstr(message,"cannot be rolled back")) + return; + + /* these and other unmentioned should set sqlca.sqlwarn[2] */ + /* NOTICE: The ':' operator is deprecated. Use exp(x) instead. */ + /* NOTICE: Rel *: Uninitialized page 0 - fixing */ + /* NOTICE: PortalHeapMemoryFree: * not in alloc set! */ + /* NOTICE: Too old parent tuple found - can't continue vc_repair_frag */ + /* NOTICE: identifier "*" will be truncated to "*" */ + /* NOTICE: InvalidateSharedInvalid: cache state reset */ + /* NOTICE: RegisterSharedInvalid: SI buffer overflow */ + sqlca.sqlwarn[2]='W'; + sqlca.sqlwarn[0]='W'; +} + bool ECPGconnect(int lineno, const char *dbname, const char *user, const char *passwd, const char *connection_name, int autocommit) { @@ -119,12 +236,14 @@ ECPGconnect(int lineno, const char *dbname, const char *user, const char *passwd 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); + + this->cache_head = NULL; if (all_connections == NULL) this->next = NULL; @@ -147,6 +266,8 @@ ECPGconnect(int lineno, const char *dbname, const char *user, const char *passwd this->committed = true; this->autocommit = autocommit; + + PQsetNoticeProcessor(this->connection,&ECPGnoticeProcessor,(void*)this); return true; } diff --git a/src/interfaces/ecpg/lib/descriptor.c b/src/interfaces/ecpg/lib/descriptor.c index 37423255336..3363381d90c 100644 --- a/src/interfaces/ecpg/lib/descriptor.c +++ b/src/interfaces/ecpg/lib/descriptor.c @@ -302,10 +302,10 @@ ECPGdeallocate_desc(int line, const char *name) bool ECPGallocate_desc(int line, const char *name) { - struct descriptor *new = (struct descriptor *) malloc(sizeof(struct descriptor)); + struct descriptor *new = (struct descriptor *) ecpg_alloc(sizeof(struct descriptor), line); new->next = all_descriptors; - new->name = malloc(strlen(name) + 1); + new->name = ecpg_alloc(strlen(name) + 1, line); new->result = PQmakeEmptyPGresult(NULL, 0); strcpy(new->name, name); all_descriptors = new; diff --git a/src/interfaces/ecpg/lib/execute.c b/src/interfaces/ecpg/lib/execute.c index 0741db622aa..762aab49c7e 100644 --- a/src/interfaces/ecpg/lib/execute.c +++ b/src/interfaces/ecpg/lib/execute.c @@ -15,6 +15,8 @@ #include #include +#include "pg_type.h" + #include "ecpgtype.h" #include "ecpglib.h" #include "ecpgerrno.h" @@ -252,13 +254,110 @@ next_insert(char *text) return (*ptr == '\0') ? NULL : ptr; } +/* + * push a value on the cache + */ + +static void +ECPGtypeinfocache_push(struct ECPGtype_information_cache **cache, int oid, bool isarray, int lineno) +{ + struct ECPGtype_information_cache *new_entry + = ecpg_alloc(sizeof(struct ECPGtype_information_cache), lineno); + new_entry->oid = oid; + new_entry->isarray = isarray; + new_entry->next = *cache; + *cache = new_entry; +} + +static bool +ECPGis_type_an_array(int type,const struct statement * stmt,const struct variable *var) +{ + char *array_query; + int isarray = 0; + PGresult *query; + struct ECPGtype_information_cache *cache_entry; + + if ((stmt->connection->cache_head)==NULL) + { + /* populate cache with well known types to speed things up */ + ECPGtypeinfocache_push(&(stmt->connection->cache_head), BOOLOID, false, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), BYTEAOID, true, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), CHAROID, false, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), NAMEOID, true, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), INT8OID, false, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), INT2OID, false, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), INT2VECTOROID, true, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), INT4OID, false, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), REGPROCOID, false, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), TEXTOID, true, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), OIDOID, false, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), TIDOID, false, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), XIDOID, false, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), CIDOID, false, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), OIDVECTOROID, true, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), POINTOID, true, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), LSEGOID, true, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), PATHOID, true, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), BOXOID, true, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), POLYGONOID, false, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), LINEOID, true, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), FLOAT4OID, false, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), FLOAT8OID, false, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), ABSTIMEOID, false, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), RELTIMEOID, false, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), TINTERVALOID, false, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), UNKNOWNOID, true, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), CIRCLEOID, false, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), CASHOID, false, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), INETOID, false, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), CIDROID, false, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), BPCHAROID, false, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), VARCHAROID, false, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), DATEOID, false, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), TIMEOID, false, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), TIMESTAMPOID, false, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), INTERVALOID, false, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), TIMETZOID, false, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), ZPBITOID, false, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), VARBITOID, false, stmt->lineno); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), NUMERICOID, false, stmt->lineno); + } + + for (cache_entry = (stmt->connection->cache_head);cache_entry != NULL;cache_entry=cache_entry->next) + { + if (cache_entry->oid==type) + return cache_entry->isarray; + } + + 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", type); + query = PQexec(stmt->connection->connection, array_query); + if (PQresultStatus(query) == PGRES_TUPLES_OK) + { + isarray = atol((char *) PQgetvalue(query, 0, 0)); + if (ECPGDynamicType(type) == SQL3_CHARACTER || + ECPGDynamicType(type) == 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, type, var->type, isarray ? "yes" : "no"); + ECPGtypeinfocache_push(&(stmt->connection->cache_head), type, isarray, stmt->lineno); + } + PQclear(query); + return isarray; +} + static bool ECPGexecute(struct statement * stmt) { bool status = false; char *copiedquery; - PGresult *results, - *query; + PGresult *results; PGnotify *notify; struct variable *var; @@ -700,8 +799,6 @@ ECPGexecute(struct statement * stmt) 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); @@ -709,26 +806,7 @@ ECPGexecute(struct statement * stmt) 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); + isarray = ECPGis_type_an_array(PQftype(results, act_field), stmt, var); if (!isarray) { @@ -911,7 +989,7 @@ ECPGdo(int lineno, const char *connection_name, char *query,...) * * Copyright (c) 2000, Christof Petig * - * $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/execute.c,v 1.8 2000/09/19 11:47:13 meskes Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/execute.c,v 1.9 2000/09/20 13:25:51 meskes Exp $ */ PGconn *ECPG_internal_get_connection(char *name); diff --git a/src/interfaces/ecpg/lib/extern.h b/src/interfaces/ecpg/lib/extern.h index db2f3a7d419..780fc933bb8 100644 --- a/src/interfaces/ecpg/lib/extern.h +++ b/src/interfaces/ecpg/lib/extern.h @@ -21,6 +21,17 @@ struct ECPGgeneric_varchar char arr[1]; }; +/* + * type information cache + */ + +struct ECPGtype_information_cache +{ + struct ECPGtype_information_cache *next; + int oid; + bool isarray; +}; + /* structure to store one statement */ struct statement { @@ -36,7 +47,8 @@ struct connection { char *name; PGconn *connection; - bool committed; - int autocommit; + bool committed; + int autocommit; + struct ECPGtype_information_cache *cache_head; struct connection *next; }; diff --git a/src/interfaces/ecpg/lib/pg_type.h b/src/interfaces/ecpg/lib/pg_type.h new file mode 100644 index 00000000000..e265de3b0c4 --- /dev/null +++ b/src/interfaces/ecpg/lib/pg_type.h @@ -0,0 +1,72 @@ +/*------------------------------------------------------------------------- + * + * pg_type.h + * definition of the system "type" relation (pg_type) + * along with the relation's initial contents. + * + * + * Portions Copyright (c) 1996-2000, PostgreSQL, Inc + * Portions Copyright (c) 1994, Regents of the University of California + * + * $Id: pg_type.h,v 1.1 2000/09/20 13:25:51 meskes Exp $ + * + * NOTES + * the genbki.sh script reads this file and generates .bki + * information from the DATA() statements. + * + *------------------------------------------------------------------------- + */ +#ifndef PG_TYPE_H +#define PG_TYPE_H + +/* ---------------- + * initial contents of pg_type + * ---------------- + */ + +/* keep the following ordered by OID so that later changes can be made easier*/ + +/* OIDS 1 - 99 */ +#define BOOLOID 16 +#define BYTEAOID 17 +#define CHAROID 18 +#define NAMEOID 19 +#define INT8OID 20 +#define INT2OID 21 +#define INT2VECTOROID 22 +#define INT4OID 23 +#define REGPROCOID 24 +#define TEXTOID 25 +#define OIDOID 26 +#define TIDOID 27 +#define XIDOID 28 +#define CIDOID 29 +#define OIDVECTOROID 30 +#define POINTOID 600 +#define LSEGOID 601 +#define PATHOID 602 +#define BOXOID 603 +#define POLYGONOID 604 +#define LINEOID 628 +#define FLOAT4OID 700 +#define FLOAT8OID 701 +#define ABSTIMEOID 702 +#define RELTIMEOID 703 +#define TINTERVALOID 704 +#define UNKNOWNOID 705 +#define CIRCLEOID 718 +#define CASHOID 790 +#define INETOID 869 +#define CIDROID 650 +#define BPCHAROID 1042 +#define VARCHAROID 1043 +#define DATEOID 1082 +#define TIMEOID 1083 +#define TIMESTAMPOID 1184 +#define INTERVALOID 1186 +#define TIMETZOID 1266 +#define ZPBITOID 1560 +#define VARBITOID 1562 +#define NUMERICOID 1700 + +#endif /* PG_TYPE_H */ diff --git a/src/interfaces/ecpg/lib/typename.c b/src/interfaces/ecpg/lib/typename.c index c66ed7709dd..a638c7d7666 100644 --- a/src/interfaces/ecpg/lib/typename.c +++ b/src/interfaces/ecpg/lib/typename.c @@ -3,6 +3,7 @@ #include "ecpglib.h" #include "extern.h" #include "sql3types.h" +#include "pg_type.h" /* * This function is used to generate the correct type names. @@ -12,7 +13,7 @@ ECPGtype_name(enum ECPGttype typ) { switch (typ) { - case ECPGt_char: + case ECPGt_char: return "char"; case ECPGt_unsigned_char: return "unsigned char"; @@ -53,31 +54,18 @@ ECPGDynamicType(Oid type) { switch (type) { - case 16:return SQL3_BOOLEAN; /* bool */ - case 21: - return SQL3_SMALLINT; /* int2 */ - case 23: - return SQL3_INTEGER;/* int4 */ - case 25: - return SQL3_CHARACTER; /* text */ - case 700: - return SQL3_REAL; /* float4 */ - case 701: - return SQL3_DOUBLE_PRECISION; /* float8 */ - case 1042: - return SQL3_CHARACTER; /* bpchar */ - case 1043: - return SQL3_CHARACTER_VARYING; /* varchar */ - case 1082: - return SQL3_DATE_TIME_TIMESTAMP; /* date */ - case 1083: - return SQL3_DATE_TIME_TIMESTAMP; /* time */ - case 1184: - return SQL3_DATE_TIME_TIMESTAMP; /* datetime */ - case 1296: - return SQL3_DATE_TIME_TIMESTAMP; /* timestamp */ - case 1700: - return SQL3_NUMERIC;/* numeric */ + case BOOLOID: return SQL3_BOOLEAN; /* bool */ + case INT2OID: return SQL3_SMALLINT; /* int2 */ + case INT4OID: return SQL3_INTEGER;/* int4 */ + case TEXTOID: return SQL3_CHARACTER; /* text */ + case FLOAT4OID: return SQL3_REAL; /* float4 */ + case FLOAT8OID: return SQL3_DOUBLE_PRECISION; /* float8 */ + case BPCHAROID: return SQL3_CHARACTER; /* bpchar */ + case VARCHAROID: return SQL3_CHARACTER_VARYING; /* varchar */ + case DATEOID: return SQL3_DATE_TIME_TIMESTAMP; /* date */ + case TIMEOID: return SQL3_DATE_TIME_TIMESTAMP; /* time */ + case TIMESTAMPOID: return SQL3_DATE_TIME_TIMESTAMP; /* datetime */ + case NUMERICOID: return SQL3_NUMERIC;/* numeric */ default: return -type; } diff --git a/src/interfaces/ecpg/test/Makefile b/src/interfaces/ecpg/test/Makefile index 0b9135a5afb..9a6614a4087 100644 --- a/src/interfaces/ecpg/test/Makefile +++ b/src/interfaces/ecpg/test/Makefile @@ -1,9 +1,10 @@ -all: test1 test2 test3 test4 perftest dyntest dyntest2 +all: test1 test2 test3 test4 perftest dyntest dyntest2 test_notice -LDFLAGS=-g -I /usr/local/pgsql/include -L/usr/local/pgsql/lib -lecpg -lpq +#LDFLAGS=-g -I /usr/local/pgsql/include -L/usr/local/pgsql/lib -lecpg -lpq +LDFLAGS=-g -I ../include -I /usr/include/postgresql -L /usr/lib -lecpg -lpq -ECPG=/usr/local/pgsql/bin/ecpg -I../include -#ECPG=../preproc/ecpg -I../include +#ECPG=/usr/local/pgsql/bin/ecpg -I../include +ECPG=../preproc/ecpg -I../include .SUFFIXES: .pgc .c @@ -14,6 +15,9 @@ test4: test4.c perftest: perftest.c dyntest: dyntest.c dyntest2: dyntest2.c +test_code100: test_code100.c +test_notice: test_notice.c +test_init: test_init.c .pgc.c: $(ECPG) $? diff --git a/src/interfaces/ecpg/test/test_code100.pgc b/src/interfaces/ecpg/test/test_code100.pgc new file mode 100644 index 00000000000..913d5175c06 --- /dev/null +++ b/src/interfaces/ecpg/test/test_code100.pgc @@ -0,0 +1,51 @@ +// $Id: test_code100.pgc,v 1.1 2000/09/20 13:25:52 meskes Exp $ + +exec sql include sqlca; +#include + +int main(int argc, char **argv) +{ exec sql begin declare section; + int index; + exec sql end declare section; + + + // ECPGdebug(1,stdout); + + exec sql connect to test; + if (sqlca.sqlcode) printf("%ld:%s\n",sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc); + + exec sql create table test ( + "index" numeric(3) primary key, + "payload" int4 NOT NULL); + if (sqlca.sqlcode) printf("%ld:%s\n",sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc); + exec sql commit work; + if (sqlca.sqlcode) printf("%ld:%s\n",sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc); + + for (index=0;index<10;++index) + { exec sql insert into test + (payload, index) + values (0, :index); + if (sqlca.sqlcode) printf("%ld:%s\n",sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc); + } + exec sql commit work; + if (sqlca.sqlcode) printf("%ld:%s\n",sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc); + + exec sql update test + set payload=payload+1 where index=-1; + if (sqlca.sqlcode!=100) printf("%ld:%s\n",sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc); + + exec sql delete from test where index=-1; + if (sqlca.sqlcode!=100) printf("%ld:%s\n",sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc); + + exec sql insert into test (select * from test where index=-1); + if (sqlca.sqlcode!=100) printf("%ld:%s\n",sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc); + + exec sql drop table test; + if (sqlca.sqlcode) printf("%ld:%s\n",sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc); + exec sql commit work; + if (sqlca.sqlcode) printf("%ld:%s\n",sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc); + + exec sql disconnect; + if (sqlca.sqlcode) printf("%ld:%s\n",sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc); + return 0; +} diff --git a/src/interfaces/ecpg/test/test_init.pgc b/src/interfaces/ecpg/test/test_init.pgc new file mode 100644 index 00000000000..86e6b6da848 --- /dev/null +++ b/src/interfaces/ecpg/test/test_init.pgc @@ -0,0 +1,61 @@ +exec sql include sqlca; + +int fa() { return 2; } +int fb(int x) { return x; } +int fc(const char *x) { return *x; } +int fd(const char *x,int i) { return (*x)*i; } +enum e { ENUM0, ENUM1 }; +int fe(enum e x) { return (int)x; } +struct sa { int member; }; + +void sqlmeldung(char *meldung, short trans) +{ +} + +#define NO 0 +#define YES 1 + +#ifdef _cplusplus +namespace N +{ static const int i=2; +}; +#endif + +int main() +{ struct sa x,*y; +exec sql begin declare section; +int a=2; +int b=2+2; +int d=x.member; +int g=fb(2); +int i=3^1; +int j=1?1:2; + +/*int e=y->member; /* compile error */ +/*int c=10>>2; /* compile error */ +/*bool h=2||1; /* compile error */ +exec sql end declare section; + +/* not working */ +int f=fa(); + +#ifdef _cplusplus +exec sql begin declare section; +int k=N::i; /* compile error */ +exec sql end declare section; +#endif + +exec sql whenever sqlerror do fa(); +exec sql select now(); +exec sql whenever sqlerror do fb(20); +exec sql select now(); +exec sql whenever sqlerror do fc("50"); +exec sql select now(); +exec sql whenever sqlerror do fd("50",1); +exec sql select now(); +exec sql whenever sqlerror do fe(ENUM0); +exec sql select now(); +/* ex ec sql whenever sqlerror do sqlmeldung(NULL,NO); */ +exec sql select now(); +return 0; +} diff --git a/src/interfaces/ecpg/test/test_notice b/src/interfaces/ecpg/test/test_notice new file mode 100755 index 00000000000..9d9506a83bc Binary files /dev/null and b/src/interfaces/ecpg/test/test_notice differ diff --git a/src/interfaces/ecpg/test/test_notice.pgc b/src/interfaces/ecpg/test/test_notice.pgc new file mode 100644 index 00000000000..db700294e21 --- /dev/null +++ b/src/interfaces/ecpg/test/test_notice.pgc @@ -0,0 +1,94 @@ +// $Id: test_notice.pgc,v 1.1 2000/09/20 13:25:52 meskes Exp $ + +exec sql include sqlca; + +#include + +void printwarning(void) +{ + if (sqlca.sqlwarn[0]) printf("sqlca.sqlwarn: %c",sqlca.sqlwarn[0]); + else return; + + if (sqlca.sqlwarn[1]) putchar('1'); + if (sqlca.sqlwarn[2]) putchar('2'); + + putchar('\n'); +} + +int main(int argc, char **argv) +{ + exec sql begin declare section; + int index,payload; + exec sql end declare section; + FILE *dbgs; + + /* actually this will print 'sql error' if a warning occurs */ + exec sql whenever sqlwarning do printwarning(); + + if ((dbgs = fopen("log", "w")) != NULL) + ECPGdebug(1, dbgs); + + exec sql connect to mm; + if (sqlca.sqlcode) printf("%d %ld:%s\n",__LINE__,sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc); + + exec sql create table test ( + "index" numeric(3) primary key, + "payload" int4 NOT NULL); + if (sqlca.sqlcode) printf("%d %ld:%s\n",__LINE__,sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc); + + exec sql commit work; + if (sqlca.sqlcode) printf("%d %ld:%s\n",__LINE__,sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc); + + exec sql begin work; + if (sqlca.sqlcode) printf("%d %ld:%s\n",__LINE__,sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc); + + exec sql begin work; + if (sqlca.sqlcode!=ECPG_NOTICE_IN_TRANSACTION) printf("%d %ld:%s\n",__LINE__,sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc); + + exec sql commit; + if (sqlca.sqlcode) printf("%d %ld:%s\n",__LINE__,sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc); + + exec sql commit; + if (sqlca.sqlcode!=ECPG_NOTICE_NO_TRANSACTION) printf("%d %ld:%s\n",__LINE__,sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc); + + exec sql rollback; + if (sqlca.sqlcode!=ECPG_NOTICE_NO_TRANSACTION) printf("%d %ld:%s\n",__LINE__,sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc); + + sqlca.sqlcode=0; + exec sql declare x cursor for select * from test; + if (sqlca.sqlcode) printf("%d %ld:%s\n",__LINE__,sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc); + + exec sql open x; + if (sqlca.sqlcode) printf("%d %ld:%s\n",__LINE__,sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc); + + exec sql open x; + if (sqlca.sqlcode!=ECPG_NOTICE_PORTAL_EXISTS) printf("%d %ld:%s\n",__LINE__,sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc); + + exec sql close x; + if (sqlca.sqlcode) printf("%d %ld:%s\n",__LINE__,sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc); + + exec sql close x; + if (sqlca.sqlcode!=ECPG_NOTICE_UNKNOWN_PORTAL) printf("%d %ld:%s\n",__LINE__,sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc); + + exec sql update test set nonexistent=2; + if (sqlca.sqlcode!=ECPG_PGSQL) printf("%d %ld:%s\n",__LINE__,sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc); + + exec sql select payload into :payload from test where index=1; + if (sqlca.sqlcode!=ECPG_NOTICE_QUERY_IGNORED) printf("%d %ld:%s\n",__LINE__,sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc); + + exec sql rollback; + if (sqlca.sqlcode) printf("%d %ld:%s\n",__LINE__,sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc); + + // this will raise a warning + exec sql drop table test; + if (sqlca.sqlcode) printf("%d %ld:%s\n",__LINE__,sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc); + exec sql commit work; + if (sqlca.sqlcode) printf("%d %ld:%s\n",__LINE__,sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc); + + exec sql disconnect; + if (sqlca.sqlcode) printf("%d %ld:%s\n",__LINE__,sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc); + + if (dbgs != NULL) + fclose(dbgs); + return 0; +}