diff --git a/scsh/odbc/odbc-bindcol.scm b/scsh/odbc/odbc-bindcol.scm new file mode 100644 index 0000000..3a003d6 --- /dev/null +++ b/scsh/odbc/odbc-bindcol.scm @@ -0,0 +1,54 @@ + +;;; condition to signal that the buffer was too small +(define-condition-type 'odbc-buffer-exceeded '(error)) +(define odbc-buffer-exceeded? + (condition-predicate 'odbc-buffer-exceeded)) + +(define (signal-buffer-exceeded buffer-needed buffer-contents) + (signal 'odbc-buffer-exceeded buffer-needed buffer-contents)) + +(define-exported-binding "signal-buffer-exceeded" signal-buffer-exceeded) + +;;; tried lookup for a column that is not bound +(define-condition-type 'odbc-unbound-column '(error)) +(define odbc-unbound-column? + (condition-predicate 'odbc-unbound-column)) + +(define (signal-unbound-column stmt-handle column-no) + (signal 'odbc-unbound-column stmt-handle column-no)) + +(define-exported-binding "signal-unbound-column" signal-unbound-column) + +(define (odbc-sql-bindcol stmt-handle column-no target-type buffer-len) + (check-arg statement-handle? stmt-handle odbc-sql-bindcol) + (let ((handle (statement-handle-handle stmt-handle))) + (odbc-sql-bindcol-internal handle column-no target-type buffer-len) + (cond ((equal? target-type sql-type-c-char) + (lambda () + (display "lookup char") + (newline) + (bindcol-lookup-binding-char handle column-no))) + ((or (equal? target-type sql-type-c-long) + (equal? target-type sql-type-c-short)) + (lambda () + (display "lookup int") + (newline) + (bindcol-lookup-binding-int handle column-no))) + (else + (error "Can't handle that datatype yet" target-type))))) + +(import-lambda-definition odbc-sql-bindcol-internal + (stmt-handle column-no target-type buffer-len) + "odbc_sql_bindcol") + +(import-lambda-definition bindcol-lookup-binding-int + (stmt-handle column-no) + "bindcol_lookup_binding_int") + +(import-lambda-definition bindcol-lookup-binding-char + (stmt-handle column-no) + "bindcol_lookup_binding_char") + + + + diff --git a/scsh/odbc/odbc.c b/scsh/odbc/odbc.c index 739bb4c..6663f63 100644 --- a/scsh/odbc/odbc.c +++ b/scsh/odbc/odbc.c @@ -16,7 +16,7 @@ s48_value odbc_alloc_environment_handle() SQLHENV henv; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_alloc_environment\n"); + ODBC_DEBUG_PRINTF_1("odbc_alloc_environment\n"); retval = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv); @@ -48,7 +48,7 @@ void odbc_sql_set_env_attr(SQLHENV env_handle) SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_set_environment\n"); + ODBC_DEBUG_PRINTF_1("odbc_set_environment\n"); retval = SQLSetEnvAttr(env_handle, SQL_ATTR_ODBC_VERSION, @@ -85,7 +85,7 @@ s48_value odbc_alloc_connection_handle(s48_value env_handle) { SQLRETURN retval; SQLHENV envh; - ODBC_DEBUG_PRINTF("odbc_alloc_connection_handle\n"); + ODBC_DEBUG_PRINTF_1("odbc_alloc_connection_handle\n"); envh = (SQLHENV) s48_extract_integer(env_handle); @@ -122,7 +122,7 @@ s48_value odbc_alloc_statement_handle(s48_value conn_handle) { SQLRETURN retval; SQLHANDLE ch; - ODBC_DEBUG_PRINTF("odbc_alloc_statement_handle\n"); + ODBC_DEBUG_PRINTF_1("odbc_alloc_statement_handle\n"); ch = (SQLHANDLE) s48_extract_integer(conn_handle); @@ -163,7 +163,7 @@ s48_value odbc_sql_connect(s48_value connection_handle, SQLCHAR *dsn, *user, *auth; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_connect\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_connect\n"); dsn = (SQLCHAR *) s48_extract_string(ds_name); user = (SQLCHAR *) s48_extract_string(user_name); @@ -223,7 +223,7 @@ s48_value odbc_sql_data_sources(s48_value env_handle) eh = (SQLHENV) s48_extract_integer(env_handle); - ODBC_DEBUG_PRINTF("odbc_sql_data_sources\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_data_sources\n"); server_name_len = driver_descr_len = ODBC_RETVAL_BUFFER_INITIAL_SIZE; server_name = (SQLCHAR *) calloc(server_name_len, sizeof(SQLCHAR)); @@ -236,7 +236,7 @@ s48_value odbc_sql_data_sources(s48_value env_handle) } redo_loop: - ODBC_DEBUG_PRINTF("redo_loop\n"); + ODBC_DEBUG_PRINTF_1("redo_loop\n"); result = S48_NULL; first = more_items = 1; @@ -255,7 +255,7 @@ s48_value odbc_sql_data_sources(s48_value env_handle) if (server_name_needed > server_name_len) { - ODBC_DEBUG_PRINTF("realloc() server_name\n"); + ODBC_DEBUG_PRINTF_1("realloc() server_name\n"); printf("needed: %d\n", server_name_needed); server_name_len = server_name_needed+1; server_name = (SQLCHAR *) realloc(server_name, (size_t) server_name_len); @@ -263,7 +263,7 @@ s48_value odbc_sql_data_sources(s48_value env_handle) } if (driver_descr_needed > driver_descr_len) { - ODBC_DEBUG_PRINTF("realloc() driver_desrc\n"); + ODBC_DEBUG_PRINTF_1("realloc() driver_desrc\n"); printf("needed: %d\n", driver_descr_needed); driver_descr_len = driver_descr_needed+1; driver_descr = (SQLCHAR *) realloc(driver_descr, (size_t) driver_descr_len); @@ -339,7 +339,7 @@ s48_value odbc_sql_drivers(s48_value env_handle) eh = (SQLHENV) s48_extract_integer(env_handle); - ODBC_DEBUG_PRINTF("odbc_sql_drivers\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_drivers\n"); result = S48_NULL; first = more_items = 0; @@ -398,7 +398,7 @@ s48_value odbc_sql_get_info_int(s48_value conn_handle, s48_value info_key) SQLUINTEGER info; SQLSMALLINT buffer_size; - ODBC_DEBUG_PRINTF("odbc_sql_get_info_int\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_get_info_int\n"); ch = (SQLHDBC) s48_extract_integer(conn_handle); ik = (SQLUSMALLINT) s48_extract_integer(info_key); @@ -440,7 +440,7 @@ s48_value odbc_sql_get_info_string(s48_value conn_handle, s48_value info_key) SQLCHAR *buffer = NULL; SQLSMALLINT buffer_needed, buffer_len; - ODBC_DEBUG_PRINTF("odbc_sql_get_info_string\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_get_info_string\n"); ch = (SQLHDBC) s48_extract_integer(conn_handle); ik = (SQLUSMALLINT) s48_extract_integer(info_key); @@ -495,7 +495,7 @@ s48_value odbc_sql_get_func_exists(s48_value conn_handle, s48_value fun_id) s48_value vec; int i; - ODBC_DEBUG_PRINTF("odbc_sql_func_exists\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_func_exists\n"); ch = (SQLHDBC) s48_extract_integer(conn_handle); fi = (SQLUSMALLINT) s48_extract_integer(fun_id); @@ -534,7 +534,7 @@ s48_value odbc_sql_get_type_info(s48_value stmt_handle, s48_value data_type) SQLSMALLINT dt; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_get_type_info\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_get_type_info\n"); sh = (SQLHSTMT) s48_extract_integer(stmt_handle); dt = (SQLSMALLINT) s48_extract_integer(data_type); @@ -583,7 +583,7 @@ s48_value odbc_sql_set_connect_attr_int(s48_value conn_handle, SQLUINTEGER val; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_set_connect_attr_int\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_set_connect_attr_int\n"); ch = (SQLHDBC) s48_extract_integer(conn_handle); attr = (SQLINTEGER) s48_extract_integer(attribute); @@ -624,7 +624,7 @@ s48_value odbc_sql_set_connect_attr_string(s48_value conn_handle, SQLCHAR *val; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_set_connect_attr_string\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_set_connect_attr_string\n"); ch = (SQLHDBC) s48_extract_integer(conn_handle); attr = (SQLINTEGER) s48_extract_integer(attribute); @@ -666,7 +666,7 @@ s48_value odbc_sql_get_connect_attr_string(s48_value conn_handle, SQLINTEGER buffer_needed, buffer_len; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_get_connect_attr_string\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_get_connect_attr_string\n"); buffer_len = ODBC_RETVAL_BUFFER_INITIAL_SIZE; @@ -717,7 +717,7 @@ s48_value odbc_sql_get_connect_attr_int(s48_value conn_handle, SQLINTEGER buffer_size; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_get_connect_attr_int\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_get_connect_attr_int\n"); retval = SQLGetConnectAttr(ch, attr, &buffer, sizeof(SQLUINTEGER), &buffer_size); @@ -756,7 +756,7 @@ s48_value odbc_sql_set_env_attr_int(s48_value env_handle, SQLUINTEGER val; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_set_env_attr\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_set_env_attr\n"); eh = (SQLHENV) s48_extract_integer(env_handle); attr = (SQLINTEGER) s48_extract_integer(attribute); @@ -798,7 +798,7 @@ s48_value odbc_sql_get_env_attr_int(s48_value env_handle, SQLUINTEGER val, str_len; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_get_env_attr_int\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_get_env_attr_int\n"); eh = (SQLHENV) s48_extract_integer(env_handle); attr = (SQLINTEGER) s48_extract_integer(attribute); @@ -841,7 +841,7 @@ s48_value odbc_sql_set_stmt_attr_int(s48_value stmt_handle, SQLUINTEGER val; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_get_stmt_attr_int\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_get_stmt_attr_int\n"); sh = (SQLHSTMT) s48_extract_integer(stmt_handle); attr = (SQLINTEGER) s48_extract_integer(attribute); @@ -882,7 +882,7 @@ s48_value odbc_sql_set_stmt_attr_string(s48_value stmt_handle, SQLCHAR *val; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_set_stmt_attr_string\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_set_stmt_attr_string\n"); sh = (SQLHSTMT) s48_extract_integer(stmt_handle); attr = (SQLINTEGER) s48_extract_integer(attribute); @@ -920,7 +920,7 @@ s48_value odbc_sql_get_stmt_attr_int(s48_value stmt_handle, s48_value attribute) SQLINTEGER attr, val, buf_size; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_get_stmt_attr_int\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_get_stmt_attr_int\n"); sh = (SQLHSTMT) s48_extract_integer(stmt_handle); attr = (SQLINTEGER) s48_extract_integer(attribute); @@ -960,7 +960,7 @@ s48_value odbc_sql_get_stmt_attr_string(s48_value stmt_handle, SQLCHAR *buffer = NULL; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_get_stmt_attr_string\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_get_stmt_attr_string\n"); buffer_len = ODBC_RETVAL_BUFFER_INITIAL_SIZE; @@ -1018,7 +1018,7 @@ s48_value odbc_sql_get_desc_field_int(s48_value desc_handle, s48_value rec_numbe SQLINTEGER value, buffer_len; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_get_desc_field_int\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_get_desc_field_int\n"); dh = (SQLHDESC) s48_extract_integer(desc_handle); rn = (SQLSMALLINT) s48_extract_integer(rec_number); @@ -1080,7 +1080,7 @@ s48_value odbc_sql_get_desc_field_string(s48_value desc_handle, s48_value rec_nu SQLINTEGER buffer_len, buffer_needed; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_get_desc_field_string\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_get_desc_field_string\n"); dh = (SQLHDESC) s48_extract_integer(desc_handle); rn = (SQLSMALLINT) s48_extract_integer(rec_number); @@ -1144,7 +1144,7 @@ s48_value odbc_sql_prepare(s48_value stmt_handle, s48_value stmt_txt) SQLCHAR *query; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_prepare\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_prepare\n"); sh = (SQLHSTMT) s48_extract_integer(stmt_handle); query = (SQLCHAR *) s48_extract_string(stmt_txt); @@ -1188,13 +1188,13 @@ s48_value odbc_sql_bind_parameter_exec_out(s48_value stmt_handle, SQLRETURN retval; unsigned int i; - ODBC_DEBUG_PRINTF("odbc_sql_bind_parameter_exec_out\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_bind_parameter_exec_out\n"); sh = (SQLHSTMT) s48_extract_integer(stmt_handle); /* bind parameters */ for (i = 0; i < S48_VECTOR_LENGTH(param_vals); i++) { - ODBC_DEBUG_PRINTF_ARG1("Binding parameter %d", i); + ODBC_DEBUG_PRINTF_2("Binding parameter %d", i); value_type = (SQLSMALLINT) s48_extract_integer(S48_CAR(S48_CDR(S48_VECTOR_REF(param_vals, i)))); @@ -1209,7 +1209,7 @@ s48_value odbc_sql_bind_parameter_exec_out(s48_value stmt_handle, SQLCHAR *value; SQLUINTEGER val_len; - ODBC_DEBUG_PRINTF("value_type is string\n"); + ODBC_DEBUG_PRINTF_1("value_type is string\n"); value = (SQLCHAR *) s48_extract_string(S48_CAR(S48_VECTOR_REF(param_vals, i))); val_len = @@ -1228,7 +1228,7 @@ s48_value odbc_sql_bind_parameter_exec_out(s48_value stmt_handle, SQLINTEGER value; SQLINTEGER cb_val; - ODBC_DEBUG_PRINTF("value_type integer\n"); + ODBC_DEBUG_PRINTF_1("value_type integer\n"); cb_val = 0; value = (SQLINTEGER) s48_extract_integer(S48_CAR(S48_VECTOR_REF(param_vals, i))); @@ -1263,7 +1263,7 @@ s48_value odbc_sql_bind_parameter_exec_out(s48_value stmt_handle, SQLREAL value; SQLINTEGER cb_val; - ODBC_DEBUG_PRINTF("value_type is float\n"); + ODBC_DEBUG_PRINTF_1("value_type is float\n"); cb_val = 0; value = (SQLREAL) S48_UNSAFE_EXTRACT_DOUBLE(S48_CAR(S48_VECTOR_REF(param_vals, i))); @@ -1280,7 +1280,7 @@ s48_value odbc_sql_bind_parameter_exec_out(s48_value stmt_handle, SQLDOUBLE value; SQLINTEGER cb_val; - ODBC_DEBUG_PRINTF("value_type is double\n"); + ODBC_DEBUG_PRINTF_1("value_type is double\n"); cb_val = 0; value = (SQLDOUBLE) S48_UNSAFE_EXTRACT_DOUBLE(S48_CAR(S48_VECTOR_REF(param_vals, i))); @@ -1297,7 +1297,7 @@ s48_value odbc_sql_bind_parameter_exec_out(s48_value stmt_handle, SQL_DATE_STRUCT value; SQLINTEGER cb_val; - ODBC_DEBUG_PRINTF("value_type is date\n"); + ODBC_DEBUG_PRINTF_1("value_type is date\n"); cb_val = 0; sql_date_record_to_struct(param_vals, &value); @@ -1313,7 +1313,7 @@ s48_value odbc_sql_bind_parameter_exec_out(s48_value stmt_handle, SQL_TIME_STRUCT value; SQLINTEGER cb_val; - ODBC_DEBUG_PRINTF("value_type is time\n"); + ODBC_DEBUG_PRINTF_1("value_type is time\n"); cb_val = 0; sql_time_record_to_struct(param_vals, &value); @@ -1329,7 +1329,7 @@ s48_value odbc_sql_bind_parameter_exec_out(s48_value stmt_handle, SQL_TIMESTAMP_STRUCT value; SQLINTEGER cb_val; - ODBC_DEBUG_PRINTF("value_type is timestamp\n"); + ODBC_DEBUG_PRINTF_1("value_type is timestamp\n"); cb_val = 0; sql_timestamp_record_to_struct(param_vals, &value); @@ -1369,7 +1369,7 @@ s48_value odbc_sql_bind_parameter_exec_out(s48_value stmt_handle, } } - ODBC_DEBUG_PRINTF("All parameters bound\n"); + ODBC_DEBUG_PRINTF_1("All parameters bound\n"); /* check the return value of SQLBindParameter */ if ((retval != SQL_SUCCESS) || (retval != SQL_SUCCESS_WITH_INFO)) { @@ -1389,7 +1389,7 @@ s48_value odbc_sql_bind_parameter_exec_out(s48_value stmt_handle, } } /* for */ - ODBC_DEBUG_PRINTF("Executing statement\n"); + ODBC_DEBUG_PRINTF_1("Executing statement\n"); /* execute statement */ @@ -1427,7 +1427,7 @@ s48_value odbc_sql_get_cursor_name(s48_value stmt_handle) SQLCHAR *buffer = NULL; SQLSMALLINT buffer_len, buffer_needed; - ODBC_DEBUG_PRINTF("odbc_sql_get_cursor_name\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_get_cursor_name\n"); sh = (SQLHSTMT) s48_extract_integer(stmt_handle); @@ -1475,7 +1475,7 @@ void odbc_sql_set_cursor_name(s48_value stmt_handle, s48_value cursorname) SQLCHAR *cn; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_set_cursor_name\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_set_cursor_name\n"); sh = (SQLHSTMT) s48_extract_integer(stmt_handle); cn = (SQLCHAR *) s48_extract_string(cursorname); @@ -1520,7 +1520,7 @@ s48_value odbc_sql_execute(s48_value stmt_handle) SQLHSTMT sh; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_execute\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_execute\n"); sh = (SQLHSTMT) s48_extract_integer(stmt_handle); @@ -1558,7 +1558,7 @@ s48_value odbc_sql_execute_direct(s48_value stmt_handle, SQLCHAR *query; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_execute_direct\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_execute_direct\n"); sh = (SQLHSTMT) s48_extract_integer(stmt_handle); query = (SQLCHAR *) s48_extract_string(stmt); @@ -1613,7 +1613,7 @@ s48_value odbc_sql_native_sql(s48_value conn_handle, s48_value stmt_txt) ch = (SQLHDBC) s48_extract_integer(conn_handle); stmt_in = (SQLCHAR *) s48_extract_string(stmt_txt); - ODBC_DEBUG_PRINTF("odbc_sql_native_sql\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_native_sql\n"); buffer_len = ODBC_RETVAL_BUFFER_INITIAL_SIZE; for (;;) @@ -1667,7 +1667,7 @@ s48_value odbc_sql_describe_param(s48_value stmt_handle, s48_value parameter_no) S48_DECLARE_GC_PROTECT(1); S48_GC_PROTECT_1(result); - ODBC_DEBUG_PRINTF("odbc_sql_describe_param\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_describe_param\n"); sh = (SQLHSTMT) s48_extract_integer(stmt_handle); pn = (SQLUSMALLINT) s48_extract_integer(parameter_no); @@ -1715,7 +1715,7 @@ s48_value odbc_sql_num_params(s48_value stmt_handle) SQLSMALLINT params; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_num_params\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_num_params\n"); sh = (SQLHSTMT) s48_extract_integer(stmt_handle); retval = SQLNumParams(sh, ¶ms); @@ -1765,7 +1765,7 @@ s48_value odbc_sql_row_count(s48_value stmt_handle) sh = (SQLHSTMT) s48_extract_integer(stmt_handle); - ODBC_DEBUG_PRINTF("odbc_sql_row_count\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_row_count\n"); retval = SQLRowCount(sh, &rowcount); @@ -1803,7 +1803,7 @@ s48_value odbc_sql_get_data(s48_value stmt_handle, SQLSMALLINT tt; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_get_data\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_get_data\n"); sh = (SQLHSTMT) s48_extract_integer(stmt_handle); cn = (SQLUSMALLINT) s48_extract_integer(column_number); @@ -1893,7 +1893,7 @@ s48_value odbc_sql_set_pos(s48_value stmt_handle, s48_value row_number, SQLUSMALLINT rn, op, lt; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_set_pos\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_set_pos\n"); sh = (SQLHSTMT) s48_extract_integer(stmt_handle); rn = (SQLUSMALLINT) s48_extract_integer(row_number); @@ -1943,7 +1943,7 @@ s48_value odbc_sql_bulk_operations(s48_value stmt_handle, s48_value operation) SQLUSMALLINT op; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_bulk_operations\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_bulk_operations\n"); sh = (SQLHSTMT) s48_extract_integer(stmt_handle); op = (SQLUSMALLINT) s48_extract_integer(operation); @@ -1990,7 +1990,7 @@ s48_value odbc_sql_more_results(s48_value stmt_handle) SQLHSTMT sh; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_more_results\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_more_results\n"); sh = (SQLHSTMT) s48_extract_integer(stmt_handle); @@ -2034,7 +2034,7 @@ s48_value odbc_sql_fetch(s48_value stmt_handle) SQLHSTMT sh; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_fetch\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_fetch\n"); sh = (SQLHSTMT) s48_extract_integer(stmt_handle); @@ -2082,7 +2082,7 @@ s48_value odbc_sql_num_result_cols(s48_value stmt_handle) sh = (SQLHSTMT) s48_extract_integer(stmt_handle); - ODBC_DEBUG_PRINTF("odbc_sql_num_result_cols\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_num_result_cols\n"); retval = SQLNumResultCols(sh, &numcols); @@ -2129,7 +2129,7 @@ s48_value odbc_sql_describe_col(s48_value stmt_handle, s48_value column_number) S48_DECLARE_GC_PROTECT(1); S48_GC_PROTECT_1(col_rec); - ODBC_DEBUG_PRINTF("odbc_sql_describe_col\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_describe_col\n"); sh = (SQLHSTMT) s48_extract_integer(stmt_handle); cn = (SQLSMALLINT) s48_extract_integer(column_number); @@ -2207,7 +2207,7 @@ s48_value odbc_sql_col_attribute(s48_value stmt_handle, s48_value column_number, S48_DECLARE_GC_PROTECT(1); S48_GC_PROTECT_1(res); - ODBC_DEBUG_PRINTF("odbc_sql_col_attribute\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_col_attribute\n"); sh = (SQLHSTMT) s48_extract_integer(stmt_handle); cn = (SQLUSMALLINT) s48_extract_integer(column_number); @@ -2260,12 +2260,291 @@ s48_value odbc_sql_col_attribute(s48_value stmt_handle, s48_value column_number, } } + +ColumnRecPtr bindcol_lookup_binding(SQLHSTMT stmt_handle, SQLUSMALLINT column_no) +{ + StmtRecPtr stmt; + ColumnRecPtr col; + + ODBC_DEBUG_PRINTF_3("bindcol_lookup_binding() %x %d\n", stmt_handle, column_no); + stmt = global_bindcol_list; + + while (stmt != NULL) + { + if (stmt->stmt_handle == stmt_handle) + { + col = stmt->col_recs; + while ((col != NULL) && (col->col_no != column_no)) + col = col->next; + return col; + } + col = col->next; + } + return NULL; +} + +s48_value bindcol_lookup_binding_int(s48_value stmt_handle, s48_value column_no) +{ + SQLHSTMT sh; + SQLSMALLINT cn; + ColumnRecPtr col; + + sh = (SQLHSTMT) s48_extract_integer(stmt_handle); + cn = (SQLSMALLINT) s48_extract_integer(column_no); + + ODBC_DEBUG_PRINTF_3("bindcol_lookup_binding_int() %x %d\n", sh, cn); + col = bindcol_lookup_binding(sh, cn); + + if (col == NULL) + s48_call_scheme(S48_SHARED_BINDING_REF(signal_unbound_column), 2, + stmt_handle, column_no); + else + { + ODBC_DEBUG_PRINTF_3("bindcol_lookup_binding_int(): %x %d\n", + col->col_buffer, *((SQLINTEGER *) col->col_buffer)); + return s48_enter_integer(*((SQLINTEGER *) col->col_buffer)); + } +} + +s48_value bindcol_lookup_binding_char(s48_value stmt_handle, s48_value column_no) +{ + ColumnRecPtr col; + + ODBC_DEBUG_PRINTF_3("bindcol_lookup_binding_char(): %x %d\n", stmt_handle, column_no); + col = bindcol_lookup_binding((SQLHSTMT) s48_extract_integer(stmt_handle), + (SQLUSMALLINT) s48_extract_integer(column_no)); + + if (col == NULL) + s48_call_scheme(S48_SHARED_BINDING_REF(signal_unbound_column), 2, stmt_handle, column_no); + else + { + ODBC_DEBUG_PRINTF_3("bindcol_lookup_binding_char(): %x %d\n", col->col_buffer, + (SQLCHAR *) col->col_buffer); + if (col->buffer_needed > col->buffer_len) + s48_call_scheme(S48_SHARED_BINDING_REF(signal_buffer_exceeded), 2, + s48_enter_integer(col->buffer_needed), + s48_enter_string((SQLCHAR *) col->col_buffer)); + else + return s48_enter_string((SQLCHAR *) col->col_buffer); + } +} + + +/* Semantics differs from original SQLBindCol(), due to the need of + bookkeeping a target buffer list in C. odbc_sql_bindcol() handles + column binding and rebinding, but not unbinding. To unbind a column + use bindcol_unbind_column() or bindcol_finalize_bindcols(). */ +s48_value odbc_sql_bindcol(s48_value stmt_handle, s48_value column_no, + s48_value target_type, s48_value buffer_len) +{ + SQLHSTMT sh; + SQLUSMALLINT cn; + SQLSMALLINT tt; + SQLLEN bl; + SQLRETURN retval; + ColumnRecPtr col = NULL; + + sh = (SQLHSTMT) s48_extract_integer(stmt_handle); + cn = (SQLUSMALLINT) s48_extract_integer(column_no); + tt = (SQLSMALLINT) s48_extract_integer(target_type); + bl = (SQLLEN) s48_extract_integer(buffer_len); + + ODBC_DEBUG_PRINTF_5("odbc_sql_bindcol() %x %d %d %d\n", sh, cn, tt, bl); + + /* try to look up ColumRec */ + col = bindcol_lookup_binding(sh, cn); + + if (col == NULL) + { + /* There is no binding for this stmt-handle/column-no yet */ + ODBC_DEBUG_PRINTF_1("odbc_sql_bindcol(): new binding\n"); + col = (ColumnRec *) malloc(sizeof(ColumnRec)); + if (col == NULL) + ODBC_RAISE_EXCEPTION("odbc_sql_bindcol(): Could not allocate buffer"); + + /* initialize it */ + col->col_no = cn; + col->target_type = tt; + col->buffer_len = bl; + col->buffer_needed = 0; + col->next = NULL; + + col->col_buffer = (void *) malloc(sizeof_sql_c_type_identifier(tt)*bl); + ODBC_DEBUG_PRINTF_3("odbc_sql_bindcol() malloc %x %d\n", + col->col_buffer, sizeof_sql_c_type_identifier(tt)*bl); + if (col->col_buffer == NULL) + ODBC_RAISE_EXCEPTION("odbc_sql_bindcol(): Could not allocate buffer"); + + /* store col in global_bindcol_list */ + bindcol_bind_column(sh, cn, col); + } + else + { + /* user wishes to rebind column for whatever reason */ + ODBC_DEBUG_PRINTF_1("odbc_sql_bindcol(): rebinding existing binding\n"); + + if (tt != col->target_type) + ODBC_RAISE_EXCEPTION("odbc_sql_bindcol(): While rebinding buffers: old/new target type do not match"); + + /* free the old buffer, allocate a new one */ + free(col->col_buffer); + col->col_buffer = (void *) malloc(sizeof_sql_c_type_identifier(tt)*bl); + ODBC_DEBUG_PRINTF_3("odbc_sql_bindcol() reallocate %x %d\n", col->col_buffer, + sizeof_sql_c_type_identifier(tt)*bl); + if (col->col_buffer == NULL) + ODBC_RAISE_EXCEPTION("odbc_sql_bindcol(): Could not allocate buffer"); + } + + /* at this point ColumRecPtr col has been created or updated, call SQLBindCol() */ + retval = SQLBindCol(sh, cn, tt, + col->col_buffer, sizeof_sql_c_type_identifier(tt)*bl, + &col->buffer_needed); + switch (retval) + { + case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: + { + return S48_UNSPECIFIC; + } + case SQL_ERROR: + { + ODBC_RAISE_EXCEPTION("SQLBindCol returned SQL_ERROR"); + break; + } + case SQL_INVALID_HANDLE: + { + ODBC_RAISE_EXCEPTION("SQLBindCol got invalid handle"); + break; + } + default: + { + ODBC_RAISE_EXCEPTION("SQLBindCol returned unknown error code"); + break; + } + } +} + +void bindcol_bind_column(SQLHSTMT stmt_handle, SQLUSMALLINT column_no, ColumnRecPtr new_col) +{ + StmtRecPtr stmt, prev_stmt, new_stmt; + ColumnRecPtr col, prev_col; + + ODBC_DEBUG_PRINTF_4("bindcol_bind_column() %x %d %x\n", stmt_handle, column_no, new_col); + prev_stmt = stmt = global_bindcol_list; + while (stmt != NULL) + { + if (stmt->stmt_handle == stmt_handle) + { + prev_col = col = stmt->col_recs; + while ((col != NULL) && (col->col_no != column_no)) + { + prev_col = col; + col = col->next; + } + if (col == NULL) + { + prev_col->next = new_col; + return; + } + } + prev_stmt = stmt; + stmt = stmt->next; + } + if (stmt == NULL) + { + ODBC_DEBUG_PRINTF_1("bindcol_bind_column() global_bindcol_list is empty\n"); + new_stmt = (StmtRecPtr) malloc(sizeof(StmtRec)); + if (new_stmt == NULL) + ODBC_RAISE_EXCEPTION("bindcol_bind_column(): Error allocating memory"); + new_stmt->next = NULL; + new_stmt->stmt_handle = stmt_handle; + new_stmt->col_recs = new_col; + if (global_bindcol_list == NULL) + global_bindcol_list = new_stmt; + else + prev_stmt->next = new_stmt; + } +} + +void bindcol_unbind_colum(SQLHSTMT stmt_handle, SQLUSMALLINT column_no) +{ + StmtRecPtr stmt, prev_stmt; + ColumnRecPtr col, prev_col; + + prev_stmt = stmt = global_bindcol_list; + while (stmt != NULL) + { + if (stmt->stmt_handle == stmt_handle) + { + prev_col = col = stmt->col_recs; + while ((col != NULL) && (col->col_no != column_no)) + { + prev_col = col; + col = col->next; + } + if (col == NULL) + s48_call_scheme(S48_SHARED_BINDING_REF(signal_unbound_column), 2, stmt_handle, column_no); + free(col->col_buffer); + prev_col->next = col->next; + free(col); + if (stmt->col_recs == NULL) + { + prev_stmt->next = stmt->next; + free(stmt); + } + return; + } + prev_stmt = stmt; + stmt = stmt->next; + } + s48_call_scheme(S48_SHARED_BINDING_REF(signal_unbound_column), 2, stmt_handle, column_no); +} + +void bindcol_finalize_bindcols(SQLHSTMT stmt_handle) +{ + StmtRecPtr stmt, prev_stmt; + ColumnRecPtr col, prev_col, first_col; + SQLRETURN retval; + + ODBC_DEBUG_PRINTF_2("bindcol_finalize_bindcols() %x\n", stmt_handle); + prev_stmt = stmt = global_bindcol_list; + while (stmt != NULL) + { + if (stmt->stmt_handle == stmt_handle) + { + /* a rather dumb approach... */ + first_col = stmt->col_recs; + while (first_col != NULL) + { + col = first_col; + while (col != NULL) + { + if (col->next == NULL) + { + /* this bindcol_rec is the last in chain */ + SQLLEN dummy; + + retval = SQLBindCol(stmt_handle, col->col_no, + col->target_type, + NULL, 0, &dummy); + free(col->col_buffer); + free(col); + prev_col->next = NULL; + } + prev_col = col; + col = col->next; + } + } + } + stmt = stmt->next; + } +} + /* * * PART 8 * * Obtaining information about the data source's - * system tables (catalog functions) + * system tables (catalog functxbions) * */ @@ -2278,7 +2557,7 @@ void odbc_sql_column_privileges(s48_value stmt_handle, s48_value catalog_name, SQLCHAR *catalog, *schema, *table, *column; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_column_privileges\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_column_privileges\n"); sh = (SQLHSTMT) s48_extract_integer(stmt_handle); catalog = (SQLCHAR *) s48_extract_string(catalog_name); @@ -2330,7 +2609,7 @@ void odbc_sql_columns(s48_value stmt_handle, s48_value catalog_name, SQLCHAR *catalog, *schema, *table, *column; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_columns\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_columns\n"); sh = (SQLHSTMT) s48_extract_integer(stmt_handle); catalog = (SQLCHAR *) s48_extract_string(catalog_name); @@ -2385,7 +2664,7 @@ void odbc_sql_foreign_keys(s48_value stmt_handle, s48_value pk_catalog_name, SQLCHAR *fk_catalog, *fk_schema, *fk_table; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_foreign_keys\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_foreign_keys\n"); sh = (SQLHSTMT) s48_extract_integer(stmt_handle); pk_catalog = (SQLCHAR *) s48_extract_string(pk_catalog_name); @@ -2440,7 +2719,7 @@ void odbc_sql_primary_keys(s48_value stmt_handle, s48_value catalog_name, SQLCHAR *catalog, *schema, *table; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_primary_keys\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_primary_keys\n"); sh = (SQLHSTMT) s48_extract_integer(stmt_handle); catalog = (SQLCHAR *) s48_extract_string(catalog_name); @@ -2491,7 +2770,7 @@ void odbc_sql_procedure_columns(s48_value stmt_handle, s48_value catalog_name, SQLCHAR *catalog, *schema, *proc, *column; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_procedure_columns\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_procedure_columns\n"); sh = (SQLHSTMT) s48_extract_integer(stmt_handle); catalog = (SQLCHAR *) s48_extract_string(catalog_name); @@ -2542,7 +2821,7 @@ void odbc_sql_procedures(s48_value stmt_handle, s48_value catalog_name, SQLCHAR *catalog, *schema, *proc; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_procedures\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_procedures\n"); sh = (SQLHSTMT) s48_extract_integer(stmt_handle); catalog = (SQLCHAR *) s48_extract_string(catalog_name); @@ -2596,7 +2875,7 @@ void odbc_sql_special_columns(s48_value stmt_handle, s48_value identifier_type, SQLSMALLINT s, n, it; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_special_columns\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_special_columns\n"); sh = (SQLHSTMT) s48_extract_integer(stmt_handle); it = (SQLSMALLINT) s48_extract_integer(identifier_type); @@ -2652,7 +2931,7 @@ void odbc_sql_statistics(s48_value stmt_handle, s48_value catalog_name, SQLSMALLINT u, r; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_statistics\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_statistics\n"); sh = (SQLHSTMT) s48_extract_integer(stmt_handle); catalog = (SQLCHAR *) s48_extract_string(catalog_name); @@ -2704,7 +2983,7 @@ void odbc_sql_table_privileges(s48_value stmt_handle, s48_value catalog_name, SQLCHAR *catalog, *schema, *table; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_table_privileges\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_table_privileges\n"); sh = (SQLHSTMT) s48_extract_integer(stmt_handle); catalog = (SQLCHAR *) s48_extract_string(catalog_name); @@ -2754,7 +3033,7 @@ void odbc_sql_tables(s48_value stmt_handle, s48_value catalog_name, SQLCHAR *catalog, *schema, *tablen, *tablet; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_tables\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_tables\n"); retval = SQLTables(sh, catalog, S48_STRING_LENGTH(catalog_name), @@ -2809,7 +3088,7 @@ s48_value odbc_sql_free_statement(s48_value stmt_handle, s48_value option) SQLUSMALLINT opt; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_free_statement\n"); + ODBC_DEBUG_PRINTF_1("odbc_free_statement\n"); sh = (SQLHSTMT) s48_extract_integer(stmt_handle); opt = (SQLUSMALLINT) s48_extract_integer(option); @@ -2846,7 +3125,7 @@ s48_value odbc_sql_close_cursor(s48_value stmt_handle) SQLHSTMT sh; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_close_cursor\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_close_cursor\n"); sh = (SQLHSTMT) s48_extract_integer(stmt_handle); retval = SQLCloseCursor(sh); @@ -2881,7 +3160,7 @@ s48_value odbc_sql_cancel(s48_value stmt_handle) SQLHSTMT sh; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_cancel\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_cancel\n"); retval = SQLCancel(sh); @@ -2917,7 +3196,7 @@ s48_value odbc_sql_endtran(s48_value handle_type, s48_value handle, SQLHANDLE h; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_endtran\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_endtran\n"); ht = (SQLSMALLINT) s48_extract_integer(handle_type); h = (SQLHANDLE) s48_extract_integer(handle); @@ -2964,7 +3243,7 @@ s48_value odbc_sql_disconnect(s48_value conn_handle) SQLHDBC ch; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_sql_disconnect\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_disconnect\n"); ch = (SQLHDBC) s48_extract_integer(conn_handle); retval = SQLDisconnect(ch); @@ -3001,7 +3280,7 @@ s48_value odbc_sql_free_handle(s48_value handle_type, s48_value handle) SQLHANDLE h; SQLRETURN retval; - ODBC_DEBUG_PRINTF("odbc_free_handle\n"); + ODBC_DEBUG_PRINTF_1("odbc_free_handle\n"); ht = (SQLSMALLINT) s48_extract_integer(handle_type); h = (SQLHANDLE) s48_extract_integer(handle); @@ -3059,7 +3338,7 @@ s48_value odbc_sql_get_diag_recs(s48_value handle_type, s48_value handle) h = (SQLHANDLE) s48_extract_integer(handle); res = S48_NULL; - ODBC_DEBUG_PRINTF("odbc_sql_get_diag_recs\n"); + ODBC_DEBUG_PRINTF_1("odbc_sql_get_diag_recs\n"); i = more_recs = 1; buffer_len = ODBC_RETVAL_BUFFER_INITIAL_SIZE; @@ -3291,6 +3570,40 @@ s48_value struct_to_sql_timestamp_record(SQL_TIMESTAMP_STRUCT *ts) return sql_timestamp; } +/* gets a C type identifier and returns the size of this type, + according to Appendix D of ODBC Programmer's reference */ +size_t sizeof_sql_c_type_identifier(SQLSMALLINT ctypeid) +{ + switch (ctypeid) + { + case SQL_C_CHAR: return sizeof(SQLCHAR); + case SQL_C_SSHORT: case SQL_C_SHORT: return sizeof(SQLSMALLINT); + case SQL_C_USHORT: return sizeof(SQLUSMALLINT); + case SQL_C_SLONG: return sizeof(SQLINTEGER); + case SQL_C_ULONG: return sizeof(SQLUINTEGER); + case SQL_C_FLOAT: return sizeof(SQLREAL); + case SQL_C_DOUBLE: return sizeof(SQLDOUBLE); + case SQL_C_BIT: return sizeof(SQLCHAR); + case SQL_C_STINYINT: return sizeof(SQLSCHAR); + case SQL_C_UTINYINT: return sizeof(SQLCHAR); +/* case SQL_SBIGINT: return sizeof(SQLBIGINT); */ +/* case SQL_UBIGINT: return sizeof(SQLUBIGINT); */ + case SQL_C_BINARY: return sizeof(SQLCHAR); + /* I don't know what to do with these types... */ +/* case SQL_C_BOOKMARK: return sizeof(BOOKMARK); */ +/* case SQL_C_VARBOOKMARK: return sizeof(SQLCHAR); */ + case SQL_C_TYPE_DATE: return sizeof(SQL_DATE_STRUCT); + case SQL_C_TYPE_TIME: return sizeof(SQL_TIME_STRUCT); + case SQL_C_TYPE_TIMESTAMP: return sizeof(SQL_TIMESTAMP_STRUCT); + case SQL_C_NUMERIC: return sizeof(SQL_NUMERIC_STRUCT); + /* case SQL_C_GUID: return sizeof(SQLGUID); */ + default: + ODBC_RAISE_EXCEPTION("Unknown c data type identifier"); + break; + } +} + + void odbc_sql_alloc(void **buffer, size_t buffer_len, size_t type_len) { if (*buffer == NULL) @@ -3327,6 +3640,23 @@ void s48_init_odbc(void) S48_GC_PROTECT_GLOBAL(odbc_parameter_record_type); odbc_column_record_type = s48_get_imported_binding("odbc-parameter"); + S48_GC_PROTECT_GLOBAL(signal_unbound_column); + signal_unbound_column = s48_get_imported_binding("signal-unbound-column"); + + S48_GC_PROTECT_GLOBAL(signal_buffer_exceeded); + signal_buffer_exceeded = s48_get_imported_binding("signal-buffer-exceeded"); + + S48_GC_PROTECT_GLOBAL(bindcol_buffer_record_type); + bindcol_buffer_record_type = s48_get_imported_binding("bindcol-buffer"); + + /* init global variables */ + global_bindcol_list = NULL; + + /* functions for SQLBindCol() */ + S48_EXPORT_FUNCTION(bindcol_lookup_binding_int); + S48_EXPORT_FUNCTION(bindcol_lookup_binding_char); + S48_EXPORT_FUNCTION(odbc_sql_bindcol); + /* PART 1 */ S48_EXPORT_FUNCTION(odbc_alloc_environment_handle); S48_EXPORT_FUNCTION(odbc_alloc_connection_handle); diff --git a/scsh/odbc/odbc.h b/scsh/odbc/odbc.h index e40b7f8..c752d74 100644 --- a/scsh/odbc/odbc.h +++ b/scsh/odbc/odbc.h @@ -1,8 +1,8 @@ #include "scheme48.h" - #include /* ODBC header files */ + #include #include @@ -32,13 +32,17 @@ #endif #ifdef ODBC_DEBUG_MSGS -#define ODBC_DEBUG_PRINTF(str) printf(str); -#define ODBC_DEBUG_PRINTF_ARG1(str, arg) printf(str, arg); -#define ODBC_DEBUG_PRINTF_ARG2(str, arg1, arg2) printf(str, arg1, arg2); +#define ODBC_DEBUG_PRINTF_1(str) printf(str); +#define ODBC_DEBUG_PRINTF_2(str, arg) printf(str, arg); +#define ODBC_DEBUG_PRINTF_3(str, arg1, arg2) printf(str, arg1, arg2); +#define ODBC_DEBUG_PRINTF_4(str, arg1, arg2, arg3) printf(str, arg1, arg2, arg3); +#define ODBC_DEBUG_PRINTF_5(str, arg1, arg2, arg3, arg4) printf(str, arg1, arg2, arg3, arg4); #else -#define ODBC_DEBUG_PRINTF(str) ; -#define ODBC_DEBUG_PRINTF_ARG1(str, arg) ; -#define ODBC_DEBUG_PRINTF_ARG2(str, arg1, arg2) ; +#define ODBC_DEBUG_PRINTF_1(str) ; +#define ODBC_DEBUG_PRINTF_2(str, arg) ; +#define ODBC_DEBUG_PRINTF_3(str, arg1, arg2) ; +#define ODBC_DEBUG_PRINTF_4(str, arg1, arg2, arg3) ; +#define ODBC_DEBUG_PRINTF_5(str, arg1, arg2, arg3, arg4) ; #endif /* offsets for scheme records */ @@ -101,6 +105,50 @@ static s48_value odbc_parameter_record_type = S48_FALSE; #define SR_ODBC_PARAMETER_DIGITS 2 #define SR_ODBC_PARAMETER_NULLABLE 3 +/* stuff needed for SQLBindCol() */ + +/* correspons to bindcol-buffer */ +static s48_value bindcol_buffer_record_type = S48_FALSE; + +#define SR_BINDCOL_BUFFER_POINTER 0 +#define SR_BINDCOL_BUFFER_LENGTH 1 +#define SR_BINDCOL_BUFFER_TARGET_TYPE 2 + +static s48_value signal_unbound_column = S48_FALSE; +static s48_value signal_buffer_exceeded = S48_FALSE; + +typedef struct bindcol_col_rec *ColumnRecPtr; + +typedef struct bindcol_col_rec { + SQLUSMALLINT col_no; + void *col_buffer; + SQLSMALLINT target_type; + SQLLEN buffer_len; + SQLLEN buffer_needed; + ColumnRecPtr next; +} ColumnRec; + +typedef struct bindcol_stmt_rec *StmtRecPtr; + +typedef struct bindcol_stmt_rec { + SQLHSTMT stmt_handle; + ColumnRecPtr col_recs; + StmtRecPtr next; +} StmtRec; + +/* global variables */ +StmtRecPtr global_bindcol_list = NULL; + +/* helper functions needed for SQLBindCol() */ +ColumnRecPtr bindcol_lookup_binding(SQLHSTMT stmt_handle, SQLUSMALLINT column_no); +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 odbc_sql_bindcol(s48_value stmt_handle, s48_value column_no, + s48_value target_type, s48_value buffer_len); + /* * * PART 1 @@ -433,6 +481,7 @@ void sql_timestamp_record_to_struct(s48_value sql_timestamp, SQL_TIMESTAMP_STRUCT *ts); void odbc_sql_alloc(void **buffer, size_t buffer_len, size_t type_len); +size_t sizeof_sql_c_type_identifier(SQLSMALLINT ctypeid); void s48_init_odbc(void);