From dc07184b5d954629649fd4251f98cd655ef01d27 Mon Sep 17 00:00:00 2001 From: eknauel Date: Wed, 25 Sep 2002 15:58:30 +0000 Subject: [PATCH] + support for SQLBrowseConnect() + finalizers for connection-handles, environment-handles and statement-handles + finalizers need more testing! --- scsh/odbc/odbc-bindcol.scm | 3 +- scsh/odbc/odbc.c | 271 ++++++++++++++++++++----------------- scsh/odbc/odbc.h | 62 +++++---- scsh/odbc/odbc.scm | 76 +++++++++-- 4 files changed, 246 insertions(+), 166 deletions(-) diff --git a/scsh/odbc/odbc-bindcol.scm b/scsh/odbc/odbc-bindcol.scm index 3a003d6..652b6ac 100644 --- a/scsh/odbc/odbc-bindcol.scm +++ b/scsh/odbc/odbc-bindcol.scm @@ -27,7 +27,7 @@ (lambda () (display "lookup char") (newline) - (bindcol-lookup-binding-char handle column-no))) + (bindcol-lookup-binding-char handle column-no))) ((or (equal? target-type sql-type-c-long) (equal? target-type sql-type-c-short)) (lambda () @@ -51,4 +51,3 @@ - diff --git a/scsh/odbc/odbc.c b/scsh/odbc/odbc.c index 4346e01..5eedf4d 100644 --- a/scsh/odbc/odbc.c +++ b/scsh/odbc/odbc.c @@ -16,9 +16,8 @@ s48_value odbc_alloc_environment_handle() SQLHENV henv; SQLRETURN retval; - ODBC_DEBUG_PRINTF_1("odbc_alloc_environment\n"); - retval = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv); + ODBC_DEBUG_PRINTF_2("odbc_alloc_environment(): %x\n", henv); switch (retval) { @@ -48,12 +47,10 @@ void odbc_sql_set_env_attr(SQLHENV env_handle) SQLRETURN retval; - ODBC_DEBUG_PRINTF_1("odbc_set_environment\n"); - - retval = SQLSetEnvAttr(env_handle, - SQL_ATTR_ODBC_VERSION, + retval = SQLSetEnvAttr(env_handle, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0); - + ODBC_DEBUG_PRINTF_2("odbc_set_environment() %x\n", env_handle); + switch (retval) { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: @@ -85,11 +82,10 @@ s48_value odbc_alloc_connection_handle(s48_value env_handle) { SQLRETURN retval; SQLHENV envh; - ODBC_DEBUG_PRINTF_1("odbc_alloc_connection_handle\n"); - envh = (SQLHENV) s48_extract_integer(env_handle); retval = SQLAllocHandle(SQL_HANDLE_DBC, envh, &hdbc); + ODBC_DEBUG_PRINTF_3("odbc_alloc_connection_handle() %x %x\n", envh, hdbc); switch (retval) { @@ -122,11 +118,10 @@ s48_value odbc_alloc_statement_handle(s48_value conn_handle) { SQLRETURN retval; SQLHANDLE ch; - ODBC_DEBUG_PRINTF_1("odbc_alloc_statement_handle\n"); - ch = (SQLHANDLE) s48_extract_integer(conn_handle); retval = SQLAllocHandle(SQL_HANDLE_STMT, ch, &hstmt); + ODBC_DEBUG_PRINTF_3("odbc_alloc_statement_handle() %x %x\n", ch, hstmt); switch (retval) { @@ -163,13 +158,13 @@ s48_value odbc_sql_connect(s48_value connection_handle, SQLCHAR *dsn, *user, *auth; SQLRETURN retval; - ODBC_DEBUG_PRINTF_1("odbc_sql_connect\n"); - dsn = (SQLCHAR *) s48_extract_string(ds_name); user = (SQLCHAR *) s48_extract_string(user_name); auth = (SQLCHAR *) s48_extract_string(authentication); ch = (SQLHDBC) s48_extract_integer(connection_handle); + ODBC_DEBUG_PRINTF_5("odbc_sql_connect() %x '%s' '%s' '%s'\n", + ch, dsn, user,auth); retval = SQLConnect(ch, dsn, SQL_NTS, user, SQL_NTS, @@ -179,7 +174,7 @@ s48_value odbc_sql_connect(s48_value connection_handle, { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: { - return S48_TRUE; + return s48_enter_integer(retval); } case SQL_ERROR: { @@ -197,6 +192,61 @@ s48_value odbc_sql_connect(s48_value connection_handle, } } +s48_value odbc_sql_browse_connect(s48_value conn_handle, s48_value conn_string) +{ + SQLHDBC ch; + SQLCHAR *buffer = NULL; + SQLRETURN retval; + SQLSMALLINT buffer_needed, buffer_len; + + ch = (SQLHDBC) s48_extract_integer(conn_handle); + ODBC_DEBUG_PRINTF_3("odbc_sql_browse_connect() %x '%s'\n", ch, s48_extract_string(conn_string)); + buffer_len = ODBC_RETVAL_BUFFER_INITIAL_SIZE; + + for (;;) + { + odbc_sql_alloc((void **) &buffer, buffer_len, sizeof(SQLCHAR)); + + retval = SQLBrowseConnect(ch, (SQLCHAR *) s48_extract_string(conn_string), + (SQLSMALLINT) S48_STRING_LENGTH(conn_string), + buffer, buffer_len, &buffer_needed); + + if (ODBC_SUCCESS(retval) && (buffer_needed > buffer_len)) + buffer_len = buffer_needed+1; + else + break; + } + + switch (retval) + { + case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: + { + s48_value res = s48_enter_string(buffer); + free(buffer); + return res; + } + case SQL_ERROR: + { + ODBC_RAISE_EXCEPTION("SQLBrowseConnect returned SQL_ERROR"); + break; + } + case SQL_INVALID_HANDLE: + { + ODBC_RAISE_EXCEPTION("SQLBrowseConnect got invalid handle"); + break; + } + case SQL_NEED_DATA: + { + return s48_enter_integer(SQL_NEED_DATA); + } + default: + { + ODBC_RAISE_EXCEPTION("SQLBrowseConnect returned unknown error code"); + break; + } + } +} + /* * * PART 2 @@ -241,9 +291,7 @@ s48_value odbc_sql_data_sources(s48_value env_handle) first = more_items = 1; while (more_items) { - printf("Calling SQLDataSources() server_name_len: %d driver_descr_len: %d\n", - sizeof(SQLCHAR)*server_name_len, - sizeof(SQLCHAR)*driver_descr_len); + retval = SQLDataSources(eh, (first ? SQL_FETCH_FIRST : SQL_FETCH_NEXT), server_name, sizeof(SQLCHAR)*server_name_len, &server_name_needed, @@ -255,16 +303,14 @@ s48_value odbc_sql_data_sources(s48_value env_handle) if (server_name_needed > server_name_len) { - ODBC_DEBUG_PRINTF_1("realloc() server_name\n"); - printf("needed: %d\n", server_name_needed); + ODBC_DEBUG_PRINTF_2("realloc() server_name %d\n", server_name_needed); server_name_len = server_name_needed+1; server_name = (SQLCHAR *) realloc(server_name, (size_t) server_name_len); redo_call = 1; } if (driver_descr_needed > driver_descr_len) { - ODBC_DEBUG_PRINTF_1("realloc() driver_desrc\n"); - printf("needed: %d\n", driver_descr_needed); + ODBC_DEBUG_PRINTF_2("realloc() driver_descr %d\n", driver_descr_needed+1); driver_descr_len = driver_descr_needed+1; driver_descr = (SQLCHAR *) realloc(driver_descr, (size_t) driver_descr_len); redo_call = 1; @@ -285,7 +331,6 @@ s48_value odbc_sql_data_sources(s48_value env_handle) { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: { - printf("(cons '%s' '%s')\n", server_name, driver_descr); result = s48_cons(s48_cons(s48_enter_string(server_name), s48_enter_string(driver_descr)), result); @@ -450,7 +495,6 @@ s48_value odbc_sql_get_info_string(s48_value conn_handle, s48_value info_key) { odbc_sql_alloc((void **) &buffer, buffer_len, sizeof(SQLCHAR)); - printf("SQLGetInfo(): buffer_len %d\n", buffer_len); retval = SQLGetInfo(ch, ik, buffer, buffer_len, &buffer_needed); if (ODBC_SUCCESS(retval) && (buffer_needed > buffer_len)) @@ -545,7 +589,7 @@ s48_value odbc_sql_get_type_info(s48_value stmt_handle, s48_value data_type) { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: { - return S48_TRUE; + return s48_enter_integer(retval); } case SQL_ERROR: { @@ -595,7 +639,7 @@ s48_value odbc_sql_set_connect_attr_int(s48_value conn_handle, { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: { - return S48_TRUE; + return s48_enter_integer(retval); } case SQL_ERROR: { @@ -636,7 +680,7 @@ s48_value odbc_sql_set_connect_attr_string(s48_value conn_handle, { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: { - return S48_TRUE; + return s48_enter_integer(retval); } case SQL_ERROR: { @@ -768,7 +812,7 @@ s48_value odbc_sql_set_env_attr_int(s48_value env_handle, { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: { - return S48_TRUE; + return s48_enter_integer(retval); } case SQL_ERROR: { @@ -810,7 +854,7 @@ s48_value odbc_sql_get_env_attr_int(s48_value env_handle, { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: { - return s48_extract_integer(val); + return s48_enter_integer(val); } case SQL_ERROR: { @@ -853,7 +897,7 @@ s48_value odbc_sql_set_stmt_attr_int(s48_value stmt_handle, { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: { - return S48_TRUE; + return s48_enter_integer(retval); } case SQL_ERROR: { @@ -894,7 +938,7 @@ s48_value odbc_sql_set_stmt_attr_string(s48_value stmt_handle, { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: { - return S48_TRUE; + return s48_enter_integer(retval); } case SQL_ERROR: { @@ -1153,7 +1197,7 @@ s48_value odbc_sql_prepare(s48_value stmt_handle, s48_value stmt_txt) switch (retval) { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: { - return S48_TRUE; + return s48_enter_integer(retval); } case SQL_INVALID_HANDLE: { @@ -1399,7 +1443,7 @@ s48_value odbc_sql_bind_parameter_exec_out(s48_value stmt_handle, { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: { - return S48_TRUE; + return s48_enter_integer(retval); } case SQL_ERROR: { @@ -1530,7 +1574,7 @@ s48_value odbc_sql_execute(s48_value stmt_handle) { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: { - return S48_TRUE; + return s48_enter_integer(retval); } case SQL_ERROR: { @@ -1567,28 +1611,21 @@ s48_value odbc_sql_execute_direct(s48_value stmt_handle, switch (retval) { - case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: + case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: + case SQL_NEED_DATA: case SQL_NO_DATA: { - return S48_TRUE; + return s48_enter_integer(retval); } case SQL_ERROR: { ODBC_RAISE_EXCEPTION("SQLExecDirect returned SQL_ERROR"); break; } - case SQL_NEED_DATA: - { - return SQL_NEED_DATA; - } case SQL_STILL_EXECUTING: { ODBC_RAISE_EXCEPTION("SQLExecDirect returned SQL_STILL_EXECUTING, not implemented yet"); break; } - case SQL_NO_DATA: - { - return SQL_NO_DATA; - } case SQL_INVALID_HANDLE: { ODBC_RAISE_EXCEPTION("SQLExecDirect got invalid handle"); @@ -1904,13 +1941,10 @@ s48_value odbc_sql_set_pos(s48_value stmt_handle, s48_value row_number, switch (retval) { - case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: - { - return S48_TRUE; - } + case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: case SQL_NEED_DATA: { - return s48_enter_integer(SQL_NEED_DATA); + return s48_enter_integer(retval); } case SQL_STILL_EXECUTING: { @@ -1953,12 +1987,9 @@ s48_value odbc_sql_bulk_operations(s48_value stmt_handle, s48_value operation) switch (retval) { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: - { - return S48_TRUE; - } case SQL_NEED_DATA: { - return s48_enter_integer(SQL_NEED_DATA); + return s48_enter_integer(retval); } case SQL_STILL_EXECUTING: { @@ -1999,12 +2030,9 @@ s48_value odbc_sql_more_results(s48_value stmt_handle) switch (retval) { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: - { - return S48_TRUE; - } case SQL_NO_DATA: { - return SQL_NO_DATA; + return s48_enter_integer(retval); } case SQL_STILL_EXECUTING: { @@ -2043,12 +2071,9 @@ s48_value odbc_sql_fetch(s48_value stmt_handle) switch (retval) { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: - { - return S48_TRUE; - } case SQL_NO_DATA: { - return s48_enter_integer(SQL_NO_DATA); + return s48_enter_integer(retval); } case SQL_STILL_EXECUTING: { @@ -2470,6 +2495,8 @@ void bindcol_unbind_colum(SQLHSTMT stmt_handle, SQLUSMALLINT column_no) StmtRecPtr stmt, prev_stmt; ColumnRecPtr col, prev_col; + ODBC_DEBUG_PRINTF_3("bindcol_unbind_colum() %x %d\n", stmt_handle, column_no); + prev_stmt = stmt = global_bindcol_list; while (stmt != NULL) { @@ -2483,6 +2510,7 @@ void bindcol_unbind_colum(SQLHSTMT stmt_handle, SQLUSMALLINT column_no) } if (col == NULL) s48_call_scheme(S48_SHARED_BINDING_REF(signal_unbound_column), 2, stmt_handle, column_no); + ODBC_DEBUG_PRINTF_2("bindcol_unbind_colum() free %x\n", col->col_buffer); free(col->col_buffer); prev_col->next = col->next; free(col); @@ -2496,20 +2524,24 @@ void bindcol_unbind_colum(SQLHSTMT stmt_handle, SQLUSMALLINT column_no) prev_stmt = stmt; stmt = stmt->next; } - s48_call_scheme(S48_SHARED_BINDING_REF(signal_unbound_column), 2, stmt_handle, column_no); + s48_call_scheme(S48_SHARED_BINDING_REF(signal_unbound_column), 2, + s48_enter_integer(stmt_handle), s48_enter_integer(column_no)); } -void bindcol_finalize_bindcols(SQLHSTMT stmt_handle) +s48_value bindcol_finalize_bindcols(s48_value stmt_handle) { + SQLHSTMT sh; StmtRecPtr stmt, prev_stmt; ColumnRecPtr col, prev_col, first_col; SQLRETURN retval; - ODBC_DEBUG_PRINTF_2("bindcol_finalize_bindcols() %x\n", stmt_handle); + sh = (SQLHSTMT) s48_extract_integer(stmt_handle); + ODBC_DEBUG_PRINTF_2("bindcol_finalize_bindcols() %x\n", sh); + prev_stmt = stmt = global_bindcol_list; while (stmt != NULL) { - if (stmt->stmt_handle == stmt_handle) + if (stmt->stmt_handle == sh) { /* a rather dumb approach... */ first_col = stmt->col_recs; @@ -2523,8 +2555,7 @@ void bindcol_finalize_bindcols(SQLHSTMT stmt_handle) /* this bindcol_rec is the last in chain */ SQLLEN dummy; - retval = SQLBindCol(stmt_handle, col->col_no, - col->target_type, + retval = SQLBindCol(sh, col->col_no, col->target_type, NULL, 0, &dummy); free(col->col_buffer); free(col); @@ -2537,6 +2568,7 @@ void bindcol_finalize_bindcols(SQLHSTMT stmt_handle) } stmt = stmt->next; } + return S48_UNSPECIFIC; } /* @@ -2549,7 +2581,7 @@ void bindcol_finalize_bindcols(SQLHSTMT stmt_handle) */ /* Returns a list of columns and associated privileges for one or more tables */ -void odbc_sql_column_privileges(s48_value stmt_handle, s48_value catalog_name, +s48_value odbc_sql_column_privileges(s48_value stmt_handle, s48_value catalog_name, s48_value schema_name, s48_value table_name, s48_value column_name) { @@ -2575,7 +2607,7 @@ void odbc_sql_column_privileges(s48_value stmt_handle, s48_value catalog_name, { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: { - return; + return s48_enter_integer(retval); } case SQL_STILL_EXECUTING: { @@ -2601,9 +2633,9 @@ void odbc_sql_column_privileges(s48_value stmt_handle, s48_value catalog_name, } /* Returns the list of column names in a specified table */ -void odbc_sql_columns(s48_value stmt_handle, s48_value catalog_name, - s48_value schema_name, s48_value table_name, - s48_value column_name) +s48_value odbc_sql_columns(s48_value stmt_handle, s48_value catalog_name, + s48_value schema_name, s48_value table_name, + s48_value column_name) { SQLHSTMT sh; SQLCHAR *catalog, *schema, *table, *column; @@ -2627,7 +2659,7 @@ void odbc_sql_columns(s48_value stmt_handle, s48_value catalog_name, { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: { - return; + return s48_enter_integer(retval); } case SQL_STILL_EXECUTING: { @@ -2654,10 +2686,10 @@ void odbc_sql_columns(s48_value stmt_handle, s48_value catalog_name, /* Returns a list of columns names that make up foreign keys, if the exist for a specified table */ -void odbc_sql_foreign_keys(s48_value stmt_handle, s48_value pk_catalog_name, - s48_value pk_schema_name, s48_value pk_table_name, - s48_value fk_catalog_name, s48_value fk_schema_name, - s48_value fk_table_name) +s48_value odbc_sql_foreign_keys(s48_value stmt_handle, s48_value pk_catalog_name, + s48_value pk_schema_name, s48_value pk_table_name, + s48_value fk_catalog_name, s48_value fk_schema_name, + s48_value fk_table_name) { SQLHSTMT sh; SQLCHAR *pk_catalog, *pk_schema, *pk_table; @@ -2686,7 +2718,7 @@ void odbc_sql_foreign_keys(s48_value stmt_handle, s48_value pk_catalog_name, { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: { - return; + return s48_enter_integer(retval); } case SQL_STILL_EXECUTING: { @@ -2712,8 +2744,8 @@ void odbc_sql_foreign_keys(s48_value stmt_handle, s48_value pk_catalog_name, } /* Returns the list of column names that make up the primary key for a table */ -void odbc_sql_primary_keys(s48_value stmt_handle, s48_value catalog_name, - s48_value schema_name, s48_value table_name) +s48_value odbc_sql_primary_keys(s48_value stmt_handle, s48_value catalog_name, + s48_value schema_name, s48_value table_name) { SQLHSTMT sh; SQLCHAR *catalog, *schema, *table; @@ -2735,7 +2767,7 @@ void odbc_sql_primary_keys(s48_value stmt_handle, s48_value catalog_name, { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: { - return; + return s48_enter_integer(retval); } case SQL_STILL_EXECUTING: { @@ -2762,9 +2794,9 @@ void odbc_sql_primary_keys(s48_value stmt_handle, s48_value catalog_name, /* Returns the list of input and output parameters, as well as the columns that make up the result set for the specified procedures */ -void odbc_sql_procedure_columns(s48_value stmt_handle, s48_value catalog_name, - s48_value schema_name, s48_value proc_name, - s48_value column_name) +s48_value odbc_sql_procedure_columns(s48_value stmt_handle, s48_value catalog_name, + s48_value schema_name, s48_value proc_name, + s48_value column_name) { SQLHSTMT sh; SQLCHAR *catalog, *schema, *proc, *column; @@ -2788,7 +2820,7 @@ void odbc_sql_procedure_columns(s48_value stmt_handle, s48_value catalog_name, { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: { - return; + return s48_enter_integer(retval); } case SQL_STILL_EXECUTING: { @@ -2814,8 +2846,8 @@ void odbc_sql_procedure_columns(s48_value stmt_handle, s48_value catalog_name, } /* Returns the list of procedure names stored in a specific data source. */ -void odbc_sql_procedures(s48_value stmt_handle, s48_value catalog_name, - s48_value schema_name, s48_value proc_name) +s48_value odbc_sql_procedures(s48_value stmt_handle, s48_value catalog_name, + s48_value schema_name, s48_value proc_name) { SQLHSTMT sh; SQLCHAR *catalog, *schema, *proc; @@ -2837,7 +2869,7 @@ void odbc_sql_procedures(s48_value stmt_handle, s48_value catalog_name, { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: { - return; + return s48_enter_integer(retval); } case SQL_STILL_EXECUTING: { @@ -2865,10 +2897,10 @@ void odbc_sql_procedures(s48_value stmt_handle, s48_value catalog_name, /* Returns information about the optimal set of columns that uniquely identifies a row in a specified table, or the columns that are automatically updated when any value in the row is updated by a transaction */ -void odbc_sql_special_columns(s48_value stmt_handle, s48_value identifier_type, - s48_value catalog_name, s48_value schema_name, - s48_value table_name, s48_value scope, - s48_value nullable) +s48_value odbc_sql_special_columns(s48_value stmt_handle, s48_value identifier_type, + s48_value catalog_name, s48_value schema_name, + s48_value table_name, s48_value scope, + s48_value nullable) { SQLHSTMT sh; SQLCHAR *catalog, *schema, *table; @@ -2895,7 +2927,7 @@ void odbc_sql_special_columns(s48_value stmt_handle, s48_value identifier_type, { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: { - return; + return s48_enter_integer(retval); } case SQL_STILL_EXECUTING: { @@ -2922,9 +2954,9 @@ void odbc_sql_special_columns(s48_value stmt_handle, s48_value identifier_type, /* Returns statistics about a single table and the list of indexes associated with the table */ -void odbc_sql_statistics(s48_value stmt_handle, s48_value catalog_name, - s48_value schema_name, s48_value table_name, - s48_value unique, s48_value reserved) +s48_value odbc_sql_statistics(s48_value stmt_handle, s48_value catalog_name, + s48_value schema_name, s48_value table_name, + s48_value unique, s48_value reserved) { SQLHSTMT sh; SQLCHAR *catalog, *schema, *table; @@ -2950,7 +2982,7 @@ void odbc_sql_statistics(s48_value stmt_handle, s48_value catalog_name, { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: { - return; + return s48_enter_integer(retval); } case SQL_STILL_EXECUTING: { @@ -2976,8 +3008,8 @@ void odbc_sql_statistics(s48_value stmt_handle, s48_value catalog_name, } /* Returns a list of tables and the privileges associated with each table */ -void odbc_sql_table_privileges(s48_value stmt_handle, s48_value catalog_name, - s48_value schema_name, s48_value table_name) +s48_value odbc_sql_table_privileges(s48_value stmt_handle, s48_value catalog_name, + s48_value schema_name, s48_value table_name) { SQLHSTMT sh; SQLCHAR *catalog, *schema, *table; @@ -2999,7 +3031,7 @@ void odbc_sql_table_privileges(s48_value stmt_handle, s48_value catalog_name, { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: { - return; + return s48_enter_integer(retval); } case SQL_STILL_EXECUTING: { @@ -3025,9 +3057,9 @@ void odbc_sql_table_privileges(s48_value stmt_handle, s48_value catalog_name, } /* Returns the list of table names stored in a specific data source */ -void odbc_sql_tables(s48_value stmt_handle, s48_value catalog_name, - s48_value schema_name, s48_value table_name, - s48_value table_type) +s48_value odbc_sql_tables(s48_value stmt_handle, s48_value catalog_name, + s48_value schema_name, s48_value table_name, + s48_value table_type) { SQLHSTMT sh; SQLCHAR *catalog, *schema, *tablen, *tablet; @@ -3045,7 +3077,7 @@ void odbc_sql_tables(s48_value stmt_handle, s48_value catalog_name, { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: { - return; + return s48_enter_integer(retval); } case SQL_STILL_EXECUTING: { @@ -3099,7 +3131,7 @@ s48_value odbc_sql_free_statement(s48_value stmt_handle, s48_value option) { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: { - return S48_TRUE; + return s48_enter_integer(retval); } case SQL_ERROR: { @@ -3133,7 +3165,7 @@ s48_value odbc_sql_close_cursor(s48_value stmt_handle) switch (retval) { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: { - return S48_TRUE; + return s48_enter_integer(retval); } case SQL_ERROR: { @@ -3167,7 +3199,7 @@ s48_value odbc_sql_cancel(s48_value stmt_handle) switch (retval) { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: { - return S48_TRUE; + return s48_enter_integer(retval); } case SQL_ERROR: { @@ -3191,7 +3223,6 @@ s48_value odbc_sql_cancel(s48_value stmt_handle) s48_value odbc_sql_endtran(s48_value handle_type, s48_value handle, s48_value completion_type) { - SQLSMALLINT ht, ct; SQLHANDLE h; SQLRETURN retval; @@ -3208,7 +3239,7 @@ s48_value odbc_sql_endtran(s48_value handle_type, s48_value handle, { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: { - return S48_TRUE; + return s48_enter_integer(retval); } case SQL_ERROR: { @@ -3243,16 +3274,16 @@ s48_value odbc_sql_disconnect(s48_value conn_handle) SQLHDBC ch; SQLRETURN retval; - ODBC_DEBUG_PRINTF_1("odbc_sql_disconnect\n"); - ch = (SQLHDBC) s48_extract_integer(conn_handle); + ODBC_DEBUG_PRINTF_2("odbc_sql_disconnect() %x\n", ch); + retval = SQLDisconnect(ch); switch (retval) { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: { - return S48_TRUE; + return s48_enter_integer(retval); } case SQL_ERROR: { @@ -3275,23 +3306,21 @@ s48_value odbc_sql_disconnect(s48_value conn_handle) /* Free a handle */ s48_value odbc_sql_free_handle(s48_value handle_type, s48_value handle) { - SQLSMALLINT ht; SQLHANDLE h; SQLRETURN retval; - ODBC_DEBUG_PRINTF_1("odbc_free_handle\n"); - ht = (SQLSMALLINT) s48_extract_integer(handle_type); h = (SQLHANDLE) s48_extract_integer(handle); + ODBC_DEBUG_PRINTF_3("odbc_sql_free_handle() %x %d\n", h, ht); retval = SQLFreeHandle(ht, h); switch (retval) { case SQL_SUCCESS: { - return S48_TRUE; + return s48_enter_integer(retval); } case SQL_ERROR: { @@ -3608,16 +3637,12 @@ void odbc_sql_alloc(void **buffer, size_t buffer_len, size_t type_len) { if (*buffer == NULL) { -#ifdef ODBC_DEBUG_MSGS - printf("calloc %d %d\n", buffer_len+1, type_len); -#endif + ODBC_DEBUG_PRINTF_3("calloc %d %d\n", buffer_len+1, type_len); *buffer = (void *) calloc(buffer_len+1, type_len); } else { -#ifdef ODBC_DEBUG_MSGS - printf("realloc %d\n", buffer_len*type_len); -#endif + ODBC_DEBUG_PRINTF_2("realloc %d\n", buffer_len*type_len); *buffer = (void *) realloc(*buffer, buffer_len*type_len); } @@ -3662,6 +3687,7 @@ void s48_init_odbc(void) S48_EXPORT_FUNCTION(odbc_alloc_connection_handle); S48_EXPORT_FUNCTION(odbc_alloc_statement_handle); S48_EXPORT_FUNCTION(odbc_sql_connect); + S48_EXPORT_FUNCTION(odbc_sql_browse_connect); /* PART 2 */ S48_EXPORT_FUNCTION(odbc_sql_data_sources); @@ -3735,4 +3761,7 @@ void s48_init_odbc(void) /* PART 11 */ S48_EXPORT_FUNCTION(odbc_sql_get_diag_recs); + + /* misc functions */ + S48_EXPORT_FUNCTION(bindcol_finalize_bindcols); } diff --git a/scsh/odbc/odbc.h b/scsh/odbc/odbc.h index c752d74..2c20e95 100644 --- a/scsh/odbc/odbc.h +++ b/scsh/odbc/odbc.h @@ -145,7 +145,7 @@ s48_value bindcol_lookup_binding_int(s48_value stmt_handle, s48_value column_no) s48_value bindcol_lookup_binding_char(s48_value stmt_handle, s48_value column_no); void bindcol_bind_column(SQLHSTMT stmt_handle, SQLUSMALLINT column_no, ColumnRecPtr new_col); void bindcol_unbind_colum(SQLHSTMT stmt_handle, SQLUSMALLINT column_no); -void bindcol_finalize_bindcols(SQLHSTMT stmt_handle); +s48_value bindcol_finalize_bindcols(s48_value stmt_handle); s48_value odbc_sql_bindcol(s48_value stmt_handle, s48_value column_no, s48_value target_type, s48_value buffer_len); @@ -178,6 +178,8 @@ s48_value odbc_sql_connect(s48_value connection_handle, s48_value user_name, s48_value authentication); +s48_value odbc_sql_browse_connect(s48_value conn_handle, s48_value conn_string); + /* * * PART 2 @@ -355,58 +357,58 @@ s48_value odbc_sql_col_attribute(s48_value stmt_handle, s48_value column_number, */ /* Returns a list of columns and associated privileges for one or more tables */ -void odbc_sql_column_privileges(s48_value stmt_handle, s48_value catalog_name, - s48_value schema_name, s48_value table_name, - s48_value column_name); +s48_value odbc_sql_column_privileges(s48_value stmt_handle, s48_value catalog_name, + s48_value schema_name, s48_value table_name, + s48_value column_name); /* Returns the list of column names in a specified table */ -void odbc_sql_columns(s48_value stmt_handle, s48_value catalog_name, - s48_value schema_name, s48_value table_name, - s48_value column_name); +s48_value odbc_sql_columns(s48_value stmt_handle, s48_value catalog_name, + s48_value schema_name, s48_value table_name, + s48_value column_name); /* Returns a list of columns names that make up foreign keys, if the exist for a specified table */ -void odbc_sql_foreign_keys(s48_value stmt_handle, s48_value pk_catalog_name, - s48_value pk_schema_name, s48_value pk_table_name, - s48_value fk_catalog_name, s48_value fk_schema_name, - s48_value fk_table_name); +s48_value odbc_sql_foreign_keys(s48_value stmt_handle, s48_value pk_catalog_name, + s48_value pk_schema_name, s48_value pk_table_name, + s48_value fk_catalog_name, s48_value fk_schema_name, + s48_value fk_table_name); /* Returns the list of column names that make up the primary key for a table */ -void odbc_sql_primary_keys(s48_value stmt_handle, s48_value catalog_name, - s48_value schema_name, s48_value table_name); +s48_value odbc_sql_primary_keys(s48_value stmt_handle, s48_value catalog_name, + s48_value schema_name, s48_value table_name); /* Returns the list of input and output parameters, as well as the columns that make up the result set for the specified procedures */ -void odbc_sql_procedure_columns(s48_value stmt_handle, s48_value catalog_name, - s48_value schema_name, s48_value proc_name, - s48_value column_name); +s48_value odbc_sql_procedure_columns(s48_value stmt_handle, s48_value catalog_name, + s48_value schema_name, s48_value proc_name, + s48_value column_name); /* Returns the list of procedure names stored in a specific data source. */ -void odbc_sql_procedures(s48_value stmt_handle, s48_value catalog_name, - s48_value schema_name, s48_value proc_name); +s48_value odbc_sql_procedures(s48_value stmt_handle, s48_value catalog_name, + s48_value schema_name, s48_value proc_name); /* Returns information about the optimal set of columns that uniquely identifies a row in a specified table, or the columns that are automatically updated when any value in the row is updated by a transaction */ -void odbc_sql_special_columns(s48_value stmt_handle, s48_value identifier_type, - s48_value catalog_name, s48_value schema_name, - s48_value table_name, s48_value scope, - s48_value nullable); +s48_value odbc_sql_special_columns(s48_value stmt_handle, s48_value identifier_type, + s48_value catalog_name, s48_value schema_name, + s48_value table_name, s48_value scope, + s48_value nullable); /* Returns statistics about a single table and the list of indexes associated with the table */ -void odbc_sql_statistics(s48_value stmt_handle, s48_value catalog_name, - s48_value schema_name, s48_value table_name, - s48_value unique, s48_value reserved); +s48_value odbc_sql_statistics(s48_value stmt_handle, s48_value catalog_name, + s48_value schema_name, s48_value table_name, + s48_value unique, s48_value reserved); /* Returns a list of tables and the privileges associated with each table */ -void odbc_sql_table_privileges(s48_value stmt_handle, s48_value catalog_name, - s48_value schema_name, s48_value table_name); +s48_value odbc_sql_table_privileges(s48_value stmt_handle, s48_value catalog_name, + s48_value schema_name, s48_value table_name); /* Returns the list of table names stored in a specific data source */ -void odbc_sql_tables(s48_value stmt_handle, s48_value catalog_name, - s48_value schema_name, s48_value table_name, - s48_value table_type); +s48_value odbc_sql_tables(s48_value stmt_handle, s48_value catalog_name, + s48_value schema_name, s48_value table_name, + s48_value table_type); /* * diff --git a/scsh/odbc/odbc.scm b/scsh/odbc/odbc.scm index 660c578..7329b12 100644 --- a/scsh/odbc/odbc.scm +++ b/scsh/odbc/odbc.scm @@ -7,16 +7,19 @@ (define-exported-binding "environment-handle" :environment-handle) (define-record-type connection-handle :connection-handle - (really-make-connection-handle handle) + (really-make-connection-handle handle environment connected?) connection-handle? - (handle connection-handle-handle)) + (handle connection-handle-handle) + (environment connection-handle-environment) + (connected? connection-handle-connected? set-connection-handle-connected?!)) (define-exported-binding "connection-handle" :connection-handle) (define-record-type statement-handle :statement-handle - (really-make-statement-handle handle) + (really-make-statement-handle handle connection) statement-handle? - (handle statement-handle-handle)) + (handle statement-handle-handle) + (connection statement-handle-connection)) (define-exported-binding "statement-handle" :statement-handle) @@ -436,7 +439,9 @@ ;;; PART 1 (define (odbc-alloc-environment-handle) - (really-make-environment-handle (odbc-alloc-environment-handle-internal))) + (let ((env-handle (really-make-environment-handle (odbc-alloc-environment-handle-internal)))) + (add-finalizer! env-handle odbc-sql-free-handle) + env-handle)) (import-lambda-definition odbc-alloc-environment-handle-internal () @@ -444,31 +449,67 @@ (define (odbc-alloc-connection-handle env-handle) (check-arg environment-handle? env-handle odbc-alloc-connection-handle) - (really-make-connection-handle - (odbc-alloc-connection-handle-internal (environment-handle-handle env-handle)))) + (let ((conn-handle (really-make-connection-handle + (odbc-alloc-connection-handle-internal + (environment-handle-handle env-handle)) env-handle #f))) + (add-finalizer! conn-handle free-connection-handle) + conn-handle)) (import-lambda-definition odbc-alloc-connection-handle-internal (env-handle) "odbc_alloc_connection_handle") +;;; maybe we should raise a warning like "implicit connect" here? +(define (free-connection-handle conn-handle) + (if (connection-handle-connected? conn-handle) + (odbc-sql-disconnect conn-handle)) + (odbc-sql-free-handle conn-handle)) + (define (odbc-alloc-statement-handle conn-handle) (check-arg connection-handle? conn-handle odbc-alloc-statement-handle) - (really-make-statement-handle - (odbc-alloc-statement-handle-internal (connection-handle-handle conn-handle)))) + (let ((stmt-handle (really-make-statement-handle + (odbc-alloc-statement-handle-internal + (connection-handle-handle conn-handle)) + conn-handle))) + (add-finalizer! stmt-handle free-statement-handle) + stmt-handle)) + +(define (free-statement-handle stmt-handle) + (bindcol-finalize-bindcols (statement-handle-handle stmt-handle)) + (odbc-sql-free-handle stmt-handle)) + (import-lambda-definition odbc-alloc-statement-handle-internal (db-handle) "odbc_alloc_statement_handle") +(import-lambda-definition bindcol-finalize-bindcols + (stmt-handle) + "bindcol_finalize_bindcols") + (define (odbc-sql-connect conn-handle server-name user-name auth) (check-arg connection-handle? conn-handle odbc-sql-connect) - (odbc-sql-connect-internal (connection-handle-handle conn-handle) - server-name user-name auth)) + (let ((return-value (odbc-sql-connect-internal + (connection-handle-handle conn-handle) + server-name user-name auth))) + (if (odbc-call-successful? return-value) + (set-connection-handle-connected?! conn-handle #t)) + return-value)) (import-lambda-definition odbc-sql-connect-internal (conn-handle server-name user-name auth) "odbc_sql_connect") +(define (odbc-sql-browse-connect conn-handle connection-string) + (check-arg connection-handle? conn-handle odbc-sql-browse-connect) + (odbc-sql-browse-connect-internal (connection-handle-handle conn-handle) + connection-string)) + +(import-lambda-definition odbc-sql-browse-connect-internal + (conn-handle connection-string) + "odbc_sql_browse_connect") + + ;;; PART 2 (define (odbc-sql-data-sources env-handle) @@ -930,7 +971,11 @@ (define (odbc-sql-disconnect conn-handle) (check-arg connection-handle? conn-handle odbc-sql-disconnect) - (odbc-sql-disconnect-internal (connection-handle-handle conn-handle))) + (let ((return-value (odbc-sql-disconnect-internal + (connection-handle-handle conn-handle)))) + (if (odbc-call-successful? return-value) + (set-connection-handle-connected?! conn-handle #f)) + return-value)) (import-lambda-definition odbc-sql-disconnect-internal (conn-handle) @@ -952,4 +997,9 @@ (import-lambda-definition odbc-sql-get-diag-recs-internal (handle-type handle) - "odbc_sql_get_diag_recs") \ No newline at end of file + "odbc_sql_get_diag_recs") + +;;; misc stuff +(define (odbc-call-successful? odbc-return-value) + (or (equal? odbc-return-value sql-success) + (equal? odbc-return-value sql-success-with-info)))