diff --git a/src/modules/Odbc/odbc.c b/src/modules/Odbc/odbc.c index ac7db85307ad355b64b275f0d2b1bc0394880e39..5e74d8525312f6a81a45c31314b929ff26d13240 100644 --- a/src/modules/Odbc/odbc.c +++ b/src/modules/Odbc/odbc.c @@ -1,5 +1,5 @@ /* - * $Id: odbc.c,v 1.8 1998/05/29 19:04:45 grubba Exp $ + * $Id: odbc.c,v 1.9 1998/05/31 15:40:31 grubba Exp $ * * Pike interface to ODBC compliant databases. * @@ -15,7 +15,7 @@ #endif /* HAVE_CONFIG_H */ #include "global.h" -RCSID("$Id: odbc.c,v 1.8 1998/05/29 19:04:45 grubba Exp $"); +RCSID("$Id: odbc.c,v 1.9 1998/05/31 15:40:31 grubba Exp $"); #include "interpret.h" #include "object.h" @@ -38,6 +38,8 @@ RCSID("$Id: odbc.c,v 1.8 1998/05/29 19:04:45 grubba Exp $"); struct program *odbc_program = NULL; +HENV odbc_henv = SQL_NULL_HENV; + /* * Functions */ @@ -54,7 +56,7 @@ static INLINE void odbc_check_error(const char *fun, const char *msg, RETCODE code, void (*clean)(void)) { if ((code != SQL_SUCCESS) && (code != SQL_SUCCESS_WITH_INFO)) { - odbc_error(fun, msg, PIKE_ODBC, PIKE_ODBC->hstmt, code, clean); + odbc_error(fun, msg, PIKE_ODBC, SQL_NULL_HSTMT, code, clean); } } @@ -68,7 +70,7 @@ void odbc_error(const char *fun, const char *msg, SWORD errmsg_len = 0; SDWORD native_error; - _code = SQLError(odbc->henv, odbc->hdbc, hstmt, errcode, &native_error, + _code = SQLError(odbc_henv, odbc->hdbc, hstmt, errcode, &native_error, errmsg, SQL_MAX_MESSAGE_LENGTH-1, &errmsg_len); errmsg[errmsg_len] = '\0'; @@ -85,19 +87,29 @@ void odbc_error(const char *fun, const char *msg, switch(_code) { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: - error("%s():%s: %d:%s:%s\n", fun, msg, code, errcode, errmsg); + error("%s(): %s:\n" + "%d:%s:%s\n", + fun, msg, code, errcode, errmsg); break; case SQL_ERROR: - error("%s():%s: SQLError failed (%d:SQL_ERROR)\n", fun, msg, code); + error("%s(): %s:\n" + "SQLError failed (%d:SQL_ERROR)\n", + fun, msg, code); break; case SQL_NO_DATA_FOUND: - error("%s():%s: SQLError failed (%d:SQL_NO_DATA_FOUND)\n", fun, msg, code); + error("%s(): %s:\n" + "SQLError failed (%d:SQL_NO_DATA_FOUND)\n", + fun, msg, code); break; case SQL_INVALID_HANDLE: - error("%s():%s: SQLError failed (%d:SQL_INVALID_HANDLE)\n", fun, msg, code); + error("%s(): %s:\n" + "SQLError failed (%d:SQL_INVALID_HANDLE)\n", + fun, msg, code); break; default: - error("%s():%s: SQLError failed (%d:%d)\n", fun, msg, code, _code); + error("%s(): %s:\n" + "SQLError failed (%d:%d)\n", + fun, msg, code, _code); break; } } @@ -114,24 +126,6 @@ static void clean_last_error(void) } } -static void clean_henv(void) -{ - HENV henv = PIKE_ODBC->henv; - PIKE_ODBC->henv = SQL_NULL_HENV; - odbc_check_error("odbc_error", "Freeing HENV", - SQLFreeEnv(henv), clean_last_error); -} - -static void clean_hdbc(void) -{ - HDBC hdbc = PIKE_ODBC->hdbc; - PIKE_ODBC->hdbc = SQL_NULL_HDBC; - odbc_check_error("odbc_error", "Disconnecting HDBC", - SQLDisconnect(hdbc), clean_henv); - odbc_check_error("odbc_error", "Freeing HDBC", - SQLFreeConnect(hdbc), clean_henv); -} - /* * Glue functions */ @@ -140,34 +134,31 @@ static void init_odbc_struct(struct object *o) { RETCODE code; - PIKE_ODBC->henv = SQL_NULL_HENV; PIKE_ODBC->hdbc = SQL_NULL_HDBC; - PIKE_ODBC->hstmt = SQL_NULL_HSTMT; - PIKE_ODBC->last_error = NULL; PIKE_ODBC->affected_rows = 0; + PIKE_ODBC->flags = 0; + PIKE_ODBC->last_error = NULL; odbc_check_error("init_odbc_struct", "ODBC initialization failed", - SQLAllocEnv(&(PIKE_ODBC->henv)), 0); - - odbc_check_error("init_odbc_struct", "ODBC initialization failed", - SQLAllocConnect(PIKE_ODBC->henv, &(PIKE_ODBC->hdbc)), - clean_henv); + SQLAllocConnect(odbc_henv, &(PIKE_ODBC->hdbc)), NULL); } static void exit_odbc_struct(struct object *o) { - RETCODE code; - HENV henv = PIKE_ODBC->henv; HDBC hdbc = PIKE_ODBC->hdbc; - PIKE_ODBC->hdbc = SQL_NULL_HDBC; - odbc_check_error("exit_odbc_struct", "ODBC disconnect failed", - SQLDisconnect(hdbc), clean_henv); - odbc_check_error("exit_odbc_struct", "Freeing ODBC connection failed", - SQLFreeConnect(hdbc), clean_henv); - PIKE_ODBC->henv = SQL_NULL_HENV; - odbc_check_error("exit_odbc_struct", "Freeing ODBC environment failed", - SQLFreeEnv(henv), clean_last_error); + if (hdbc != SQL_NULL_HDBC) { + if (PIKE_ODBC->flags & PIKE_ODBC_CONNECTED) { + PIKE_ODBC->flags &= ~PIKE_ODBC_CONNECTED; + odbc_check_error("odbc_error", "Disconnecting HDBC", + SQLDisconnect(hdbc), (void (*)(void))exit_odbc_struct); + /* NOTE: Potential recursion above! */ + } + PIKE_ODBC->hdbc = SQL_NULL_HDBC; + odbc_check_error("odbc_error", "Freeing HDBC", + SQLFreeConnect(hdbc), clean_last_error); + } + clean_last_error(); } /* @@ -209,11 +200,18 @@ static void f_create(INT32 args) if (!server) { server = make_shared_string(""); } + if (PIKE_ODBC->flags & PIKE_ODBC_CONNECTED) { + PIKE_ODBC->flags &= ~PIKE_ODBC_CONNECTED; + /* Disconnect old hdbc */ + odbc_check_error("odbc->create", "Disconnecting HDBC", + SQLDisconnect(PIKE_ODBC->hdbc), NULL); + } odbc_check_error("odbc->create", "Connect failed", SQLConnect(PIKE_ODBC->hdbc, (unsigned char *)server->str, server->len, (unsigned char *)user->str, user->len, (unsigned char *)pwd->str, pwd->len), NULL); + PIKE_ODBC->flags |= PIKE_ODBC_CONNECTED; pop_n_elems(args); } @@ -223,19 +221,15 @@ static void f_affected_rows(INT32 args) push_int(PIKE_ODBC->affected_rows); } -static void f_insert_id(INT32 args) -{ - /**********************************************/ -} - static void f_select_db(INT32 args) { /**********************************************/ } -void free_hstmt(HSTMT hstmt) +/* Needed since free_string() can be a macro */ +static void odbc_free_string(struct pike_string *s) { - SQLFreeStmt(hstmt, SQL_DROP); /* Ignore return value. */ + free_string(s); } static void f_big_query(INT32 args) @@ -243,50 +237,54 @@ static void f_big_query(INT32 args) ONERROR ebuf; HSTMT hstmt = SQL_NULL_HSTMT; struct pike_string *q = NULL; +#ifdef DEBUG + struct svalue *save_sp = sp + 1 - args; +#endif /* DEBUG */ get_all_args("odbc->big_query", args, "%S", &q); - odbc_check_error("odbc->big_query", "Statement allocation failed", - SQLAllocStmt(PIKE_ODBC->hdbc, &hstmt), NULL); - PIKE_ODBC->hstmt = hstmt; + add_ref(q); + SET_ONERROR(ebuf, odbc_free_string, q); - SET_ONERROR(ebuf, free_hstmt, hstmt); - - odbc_check_error("odbc->big_query", "Query failed", - SQLExecDirect(hstmt, (unsigned char *)q->str, - q->len), NULL); pop_n_elems(args); - odbc_check_error("odbc->big_query", "Couldn't get the number of fields", - SQLNumResultCols(hstmt, &(PIKE_ODBC->num_fields)), NULL); + clean_last_error(); - odbc_check_error("odbc->big_query", "Couldn't get the number of rows", - SQLRowCount(hstmt, &(PIKE_ODBC->affected_rows)), NULL); + /* Allocate the statement (result) object */ + ref_push_object(fp->current_object); + push_object(clone_object(odbc_result_program, 1)); - if (PIKE_ODBC->num_fields) { - /* PIKE_ODBC->hstmt=hstmt; */ - ref_push_object(fp->current_object); + UNSET_ONERROR(ebuf); - push_object(clone_object(odbc_result_program, 1)); + /* Potential return value is now in place */ - /* hstmt is now handled by the result program. */ - UNSET_ONERROR(ebuf); - } else { - odbc_check_error("odbc->big_query", "Couldn't commit query", - SQLTransact(PIKE_ODBC->henv, PIKE_ODBC->hdbc, - SQL_COMMIT), NULL); + PIKE_ODBC->affected_rows = 0; - UNSET_ONERROR(ebuf); + /* Do the actual query */ + push_string(q); + apply(sp[-2].u.object, "execute", 1); + + if (sp[-1].type != T_INT) { + error("odbc->big_query(): Unexpected return value from " + "odbc_result->execute().\n"); + } - /* hstmt is still handled by us. */ - if (hstmt != SQL_NULL_HSTMT) { - PIKE_ODBC->hstmt = SQL_NULL_HSTMT; - odbc_check_error("odbc->big_query", "Freeing of HSTMT failed", - SQLFreeStmt(hstmt, SQL_DROP), NULL); - } + if (!sp[-1].u.integer) { + pop_n_elems(2); /* Zap the result object too */ + + odbc_check_error("odbc->big_query", "Couldn't commit query", + SQLTransact(odbc_henv, PIKE_ODBC->hdbc, SQL_COMMIT), + NULL); push_int(0); + } else { + pop_stack(); /* Keep the result object */ } +#ifdef DEBUG + if (sp != save_sp) { + fatal("Stack error in odbc->big_query().\n"); + } +#endif /* DEBUG */ } static void f_create_db(INT32 args) @@ -319,20 +317,28 @@ static void f_reload(INT32 args) void pike_module_init(void) { #ifdef HAVE_ODBC + RETCODE err = SQLAllocEnv(&odbc_henv); + + if (err != SQL_SUCCESS) { + error("odbc_module_init(): SQLAllocEnv() failed with code %08x\n", err); + } + start_new_program(); add_storage(sizeof(struct precompiled_odbc)); add_function("error", f_error, "function(void:int|string)", ID_PUBLIC); add_function("create", f_create, "function(string|void, string|void, string|void, string|void:void)", ID_PUBLIC); - add_function("affected_rows", f_affected_rows, "function(void:int)", ID_PUBLIC); - add_function("insert_id", f_insert_id, "function(void:int)", ID_PUBLIC); + add_function("select_db", f_select_db, "function(string:void)", ID_PUBLIC); add_function("big_query", f_big_query, "function(string:int|object)", ID_PUBLIC); + add_function("affected_rows", f_affected_rows, "function(void:int)", ID_PUBLIC); + /* NOOP's: */ add_function("create_db", f_create_db, "function(string:void)", ID_PUBLIC); add_function("drop_db", f_drop_db, "function(string:void)", ID_PUBLIC); add_function("shutdown", f_shutdown, "function(void:void)", ID_PUBLIC); add_function("reload", f_reload, "function(void:void)", ID_PUBLIC); #if 0 + add_function("insert_id", f_insert_id, "function(void:int)", ID_PUBLIC); add_function("statistics", f_statistics, "function(void:string)", ID_PUBLIC); add_function("server_info", f_server_info, "function(void:string)", ID_PUBLIC); add_function("host_info", f_host_info, "function(void:string)", ID_PUBLIC); @@ -365,6 +371,15 @@ void pike_module_exit(void) free_program(odbc_program); odbc_program = NULL; } + + if (odbc_henv != SQL_NULL_HENV) { + RETCODE err = SQLFreeEnv(odbc_henv); + odbc_henv = SQL_NULL_HENV; + + if ((err != SQL_SUCCESS) && (err != SQL_SUCCESS_WITH_INFO)) { + error("odbc_module_exit(): SQLFreeEnv() failed with code %08x\n", err); + } + } #endif /* HAVE_ODBC */ } diff --git a/src/modules/Odbc/odbc_result.c b/src/modules/Odbc/odbc_result.c index 4bc8ef496a0353f41368c4fccffed099ee485fde..10e22f26eb36c0338b0b704186e496b50f9ad9f2 100644 --- a/src/modules/Odbc/odbc_result.c +++ b/src/modules/Odbc/odbc_result.c @@ -1,5 +1,5 @@ /* - * $Id: odbc_result.c,v 1.8 1998/04/20 18:53:43 grubba Exp $ + * $Id: odbc_result.c,v 1.9 1998/05/31 15:40:33 grubba Exp $ * * Pike interface to ODBC compliant databases * @@ -17,7 +17,7 @@ #ifdef HAVE_ODBC #include "global.h" -RCSID("$Id: odbc_result.c,v 1.8 1998/04/20 18:53:43 grubba Exp $"); +RCSID("$Id: odbc_result.c,v 1.9 1998/05/31 15:40:33 grubba Exp $"); #include "interpret.h" #include "object.h" @@ -31,10 +31,13 @@ RCSID("$Id: odbc_result.c,v 1.8 1998/04/20 18:53:43 grubba Exp $"); #include "array.h" #include "builtin_functions.h" #include "pike_memory.h" +#include "pike_macros.h" #include "module_support.h" #include "precompiled_odbc.h" +#define ODBC_DEBUG + /* * Globals */ @@ -104,16 +107,14 @@ static void exit_res_struct(struct object *o) static void odbc_fix_fields(void) { int i; - struct odbc_field_info { - int type; /* Pike-type */ - int size; - } *odbc_fields = alloca(sizeof(struct odbc_field_info)*PIKE_ODBC_RES->num_fields); + unsigned long *odbc_field_sizes = alloca(sizeof(unsigned long) * + PIKE_ODBC_RES->num_fields); size_t buf_size = 1024; unsigned char *buf = alloca(buf_size); int membuf_size = 0; char *membuf = NULL; - if ((!buf)||(!odbc_fields)) { + if ((!buf)||(!odbc_field_sizes)) { error("odbc_fix_fields(): Out of memory\n"); } @@ -144,8 +145,16 @@ static void odbc_fix_fields(void) error("odbc_fix_fields(): Out of memory\n"); } } - odbc_fields[i].type = T_STRING; - odbc_fields[i].size = precision+1; +#ifdef ODBC_DEBUG + fprintf(stderr, "ODBC:odbc_fix_fields():\n" + "name:%s\n" + "sql_type:%d\n" + "precision:%ld\n" + "scale:%d\n" + "nullable:%d\n", + buf, sql_type, precision, scale, nullable); +#endif /* ODBC_DEBUG */ + odbc_field_sizes[i] = precision+1; /* Create the mapping */ push_text("name"); push_string(make_shared_binary_string((char *)buf, name_len)); @@ -156,44 +165,48 @@ static void odbc_fix_fields(void) break; case SQL_DATE: push_text("date"); - odbc_fields[i].size = 7; + odbc_field_sizes[i] = 12; break; case SQL_DECIMAL: push_text("decimal"); - odbc_fields[i].size += 2; + odbc_field_sizes[i] += 2; break; case SQL_DOUBLE: push_text("double"); - /* odbc_fields[i].size = 8; */ - /* odbc_fields[i].type = T_FLOAT; */ break; case SQL_INTEGER: push_text("integer"); - /* odbc_fields[i].size = 4; */ - /* odbc_fields[i].type = T_INT; */ break; case SQL_LONGVARBINARY: push_text("long blob"); + if (odbc_field_sizes[i] > 0x100000) { + /* Don't allocate more than 1M */ + odbc_field_sizes[i] = 0x100000; + } break; case SQL_LONGVARCHAR: push_text("var string"); + if (odbc_field_sizes[i] > 0x100000) { + /* Don't allocate more than 1M */ + odbc_field_sizes[i] = 0x100000; + } break; case SQL_REAL: push_text("float"); - /* odbc_fields[i].size = 4; */ - /* odbc_fields[i].type = T_FLOAT; */ break; case SQL_SMALLINT: push_text("short"); - /* odbc_fields[i].size = 4; */ - /* odbc_fields[i].type = T_INT; */ break; case SQL_TIMESTAMP: push_text("time"); - odbc_fields[i].size = 22 + scale; + odbc_field_sizes[i] = 22 + scale; break; case SQL_VARCHAR: push_text("var string"); + if (odbc_field_sizes[i] > 0x100000) { + /* Don't allocate more than 1M */ + odbc_field_sizes[i] = 0x100000; + } break; default: push_text("unknown"); @@ -217,10 +230,10 @@ static void odbc_fix_fields(void) f_aggregate_mapping(5*2); /* Align to longlong-word size */ - odbc_fields[i].size += 7; - odbc_fields[i].size &= ~7; + odbc_field_sizes[i] += 7; + odbc_field_sizes[i] &= ~7; - membuf_size += odbc_fields[i].size; + membuf_size += odbc_field_sizes[i]; } f_aggregate(PIKE_ODBC_RES->num_fields); @@ -237,35 +250,14 @@ static void odbc_fix_fields(void) * Now it's time to bind the columns */ for (i=0; i < PIKE_ODBC_RES->num_fields; i++) { - PIKE_ODBC_RES->field_info[i].type = odbc_fields[i].type; PIKE_ODBC_RES->field_info[i].buf = membuf; - PIKE_ODBC_RES->field_info[i].size = odbc_fields[i].size; + PIKE_ODBC_RES->field_info[i].size = odbc_field_sizes[i]; - switch(odbc_fields[i].type) { - case T_STRING: - odbc_check_error("odbc_fix_fields", "Couldn't bind string field", - SQLBindCol(PIKE_ODBC_RES->hstmt, i+1, - SQL_C_CHAR, membuf, odbc_fields[i].size, - &PIKE_ODBC_RES->field_info[i].len), NULL); - break; - case T_INT: - odbc_check_error("odbc_fix_fields", "Couldn't bind integer field", - SQLBindCol(PIKE_ODBC_RES->hstmt, i+1, - SQL_C_SLONG, membuf, odbc_fields[i].size, - &PIKE_ODBC_RES->field_info[i].len), NULL); - break; - case T_FLOAT: - odbc_check_error("odbc_fix_fields", "Couldn't bind float field", - SQLBindCol(PIKE_ODBC_RES->hstmt, i+1, - SQL_C_DOUBLE, membuf, odbc_fields[i].size, - &PIKE_ODBC_RES->field_info[i].len), NULL); - break; - default: - error("odbc_fix_fields(): Internal error: Unhandled type:%d\n", - odbc_fields[i].type); - break; - } - membuf += odbc_fields[i].size; + odbc_check_error("odbc_fix_fields", "Couldn't bind string field", + SQLBindCol(PIKE_ODBC_RES->hstmt, i+1, + SQL_C_CHAR, membuf, odbc_field_sizes[i], + &PIKE_ODBC_RES->field_info[i].len), NULL); + membuf += odbc_field_sizes[i]; } } @@ -276,6 +268,8 @@ static void odbc_fix_fields(void) /* void create(object(odbc)) */ static void f_create(INT32 args) { + HSTMT hstmt = SQL_NULL_HSTMT; + if (!args) { error("Too few arguments to odbc_result()\n"); } @@ -285,23 +279,41 @@ static void f_create(INT32 args) odbc_program)))) { error("Bad argument 1 to odbc_result()\n"); } - add_ref(PIKE_ODBC_RES->obj = sp[-args].u.object); - PIKE_ODBC_RES->hstmt = PIKE_ODBC_RES->odbc->hstmt; - PIKE_ODBC_RES->odbc->hstmt = SQL_NULL_HSTMT; - - pop_n_elems(args); - - if (PIKE_ODBC_RES->hstmt == SQL_NULL_HSTMT) { - free_object(PIKE_ODBC_RES->obj); - PIKE_ODBC_RES->odbc = NULL; - PIKE_ODBC_RES->obj = NULL; - error("odbc_result(): No result to clone\n"); + + odbc_check_error("odbc_result", "Statement allocation failed", + SQLAllocStmt(PIKE_ODBC_RES->odbc->hdbc, &hstmt), NULL); + PIKE_ODBC_RES->hstmt = hstmt; +} + +static void f_execute(INT32 args) +{ + struct pike_string *q = NULL; + HSTMT hstmt = PIKE_ODBC_RES->hstmt; + + get_all_args("odbc_result->execute", args, "%S", &q); + + odbc_check_error("odbc_result->execute", "Query failed", + SQLExecDirect(hstmt, (unsigned char *)q->str, q->len), + NULL); + + odbc_check_error("odbc_result->execute", "Couldn't get the number of fields", + SQLNumResultCols(hstmt, &(PIKE_ODBC_RES->num_fields)), + NULL); + + odbc_check_error("odbc_result->execute", "Couldn't get the number of rows", + SQLRowCount(hstmt, &(PIKE_ODBC_RES->num_rows)), NULL); + + PIKE_ODBC_RES->odbc->affected_rows = PIKE_ODBC_RES->num_rows; + + if (PIKE_ODBC_RES->num_fields) { + odbc_fix_fields(); } - PIKE_ODBC_RES->num_fields = PIKE_ODBC_RES->odbc->num_fields; - PIKE_ODBC_RES->num_rows = PIKE_ODBC_RES->odbc->affected_rows; - - odbc_fix_fields(); + + pop_n_elems(args); + + /* Result */ + push_int(PIKE_ODBC_RES->num_fields); } /* int num_rows() */ @@ -345,22 +357,8 @@ static void f_fetch_row(INT32 args) for (i=0; i < PIKE_ODBC_RES->num_fields; i++) { if (PIKE_ODBC_RES->field_info[i].len != SQL_NULL_DATA) { - switch (PIKE_ODBC_RES->field_info[i].type) { - case T_INT: - push_int(*((int *)PIKE_ODBC_RES->field_info[i].buf)); - break; - case T_FLOAT: - push_float(*((double *)PIKE_ODBC_RES->field_info[i].buf)); - break; - case T_STRING: - push_string(make_shared_binary_string(PIKE_ODBC_RES->field_info[i].buf, - PIKE_ODBC_RES->field_info[i].len)); - break; - default: - error("odbc->fetch_row(): Internal error: Unknown type (%d)\n", - PIKE_ODBC_RES->field_info[i].type); - break; - } + push_string(make_shared_binary_string(PIKE_ODBC_RES->field_info[i].buf, + PIKE_ODBC_RES->field_info[i].len)); } else { /* NULL */ push_int(0); @@ -407,8 +405,14 @@ void init_odbc_res_programs(void) start_new_program(); add_storage(sizeof(struct precompiled_odbc_result)); + + map_variable("_odbc", "object", 0, + OFFSETOF(precompiled_odbc_result, obj), T_OBJECT); + map_variable("_fields", "array(mapping(string:mixed))", 0, + OFFSETOF(precompiled_odbc_result, fields), T_ARRAY); add_function("create", f_create, "function(object:void)", ID_PUBLIC); + add_function("execute", f_execute, "function(string:int)", ID_PUBLIC); add_function("num_rows", f_num_rows, "function(void:int)", ID_PUBLIC); add_function("num_fields", f_num_fields, "function(void:int)", ID_PUBLIC); #ifdef SUPPORT_FIELD_SEEK diff --git a/src/modules/Odbc/precompiled_odbc.h b/src/modules/Odbc/precompiled_odbc.h index d91f9d9828445478dc181472feb86df467420543..1eff0d3fbcc74ed210d4aee1ab4fd9bd7baa1d9d 100644 --- a/src/modules/Odbc/precompiled_odbc.h +++ b/src/modules/Odbc/precompiled_odbc.h @@ -1,5 +1,5 @@ /* - * $Id: precompiled_odbc.h,v 1.3 1997/11/02 22:19:35 grubba Exp $ + * $Id: precompiled_odbc.h,v 1.4 1998/05/31 15:40:34 grubba Exp $ * * Pike interface to ODBC compliant databases. * @@ -37,18 +37,15 @@ extern struct program *odbc_result_program; */ struct field_info { - int type; /* Pike-type */ SDWORD len; int size; /* Size of buffer */ void *buf; }; struct precompiled_odbc { - HENV henv; HDBC hdbc; - HSTMT hstmt; - SWORD num_fields; - SDWORD affected_rows; + int affected_rows; + unsigned int flags; struct pike_string *last_error; }; @@ -56,8 +53,8 @@ struct precompiled_odbc_result { struct object *obj; struct precompiled_odbc *odbc; HSTMT hstmt; - int num_fields; - int num_rows; + SWORD num_fields; + SDWORD num_rows; struct array *fields; struct field_info *field_info; }; @@ -69,6 +66,9 @@ struct precompiled_odbc_result { #define PIKE_ODBC ((struct precompiled_odbc *)(fp->current_storage)) #define PIKE_ODBC_RES ((struct precompiled_odbc_result *)(fp->current_storage)) +/* Flags */ +#define PIKE_ODBC_CONNECTED 1 + /* * Prototypes */