- support for SQLNativeSql()
- dynamic memory allocation for return values in these functions: - odbc_sql_get_info_string() - odbc_sql_get_connect_attr_string() - odbc_sql_get_stmt_attr_string() - odbc_sql_get_desc_field_string() - odbc_sql_get_cursor_name() - odbc_sql_native_sql() - odbc_sql_get_data() - odbc_sql_describe_col() - odbc_sql_get_diag_recs() - odbc_sql_data_sources() is still broken: sometimes the result string is truncated. I'm not sure if this not a unixODBC-bug...
This commit is contained in:
parent
cd9907c68f
commit
87846eef58
317
scsh/odbc/odbc.c
317
scsh/odbc/odbc.c
|
@ -162,18 +162,12 @@ s48_value odbc_sql_connect(s48_value connection_handle,
|
|||
SQLHDBC ch;
|
||||
SQLCHAR *dsn, *user, *auth;
|
||||
SQLRETURN retval;
|
||||
int dsn_len, user_len, auth_len;
|
||||
|
||||
ODBC_DEBUG_PRINTF("odbc_sql_connect\n");
|
||||
|
||||
dsn = (SQLCHAR *) s48_extract_string(ds_name);
|
||||
user = (SQLCHAR *) s48_extract_string(user_name);
|
||||
auth = (SQLCHAR *) s48_extract_string(authentication);
|
||||
|
||||
dsn_len = S48_STRING_LENGTH(ds_name);
|
||||
user_len = S48_STRING_LENGTH(user_name);
|
||||
auth_len = S48_STRING_LENGTH(authentication);
|
||||
|
||||
ch = (SQLHDBC) s48_extract_integer(connection_handle);
|
||||
|
||||
retval = SQLConnect(ch,
|
||||
|
@ -218,10 +212,9 @@ s48_value odbc_sql_data_sources(s48_value env_handle)
|
|||
SQLHENV eh;
|
||||
SQLUSMALLINT dir;
|
||||
SQLRETURN retval;
|
||||
SQLCHAR server_name[SQL_MAX_DSN_LENGTH+1];
|
||||
SQLSMALLINT server_name_len;
|
||||
SQLCHAR driver_descr[ODBC_MAX_DRIVER_NAME_LEN];
|
||||
SQLSMALLINT driver_descr_len;
|
||||
SQLCHAR *server_name, *driver_descr;
|
||||
SQLSMALLINT server_name_len, driver_descr_len;
|
||||
SQLSMALLINT server_name_needed, driver_descr_needed;
|
||||
s48_value result = S48_UNSPECIFIC;
|
||||
int first, more_items;
|
||||
|
||||
|
@ -231,20 +224,59 @@ 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");
|
||||
|
||||
server_name_len = driver_descr_len = ODBC_RETVAL_BUFFER_INITIAL_SIZE;
|
||||
server_name = (SQLCHAR *) calloc(server_name_len, sizeof(SQLCHAR));
|
||||
driver_descr = (SQLCHAR *) calloc(driver_descr_len, sizeof(SQLCHAR));
|
||||
|
||||
if ((server_name == NULL) || (driver_descr == NULL))
|
||||
{
|
||||
ODBC_RAISE_EXCEPTION("Could not allocate memory for return values");
|
||||
return S48_UNSPECIFIC;
|
||||
}
|
||||
|
||||
redo_loop:
|
||||
ODBC_DEBUG_PRINTF("redo_loop\n");
|
||||
result = S48_NULL;
|
||||
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, SQL_MAX_DSN_LENGTH+1, &server_name_len,
|
||||
driver_descr, ODBC_MAX_DRIVER_NAME_LEN, &driver_descr_len);
|
||||
/* FIXME */
|
||||
if (driver_descr_len > ODBC_MAX_DRIVER_NAME_LEN - 1)
|
||||
server_name, sizeof(SQLCHAR)*server_name_len, &server_name_needed,
|
||||
driver_descr, sizeof(SQLCHAR)*driver_descr_len, &driver_descr_needed);
|
||||
|
||||
if (ODBC_SUCCESS(retval))
|
||||
{
|
||||
ODBC_RAISE_EXCEPTION("SQLDataSources(): string driver_descr to long");
|
||||
return S48_UNSPECIFIC;
|
||||
int redo_call = 0;
|
||||
|
||||
if (server_name_needed > server_name_len)
|
||||
{
|
||||
ODBC_DEBUG_PRINTF("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);
|
||||
redo_call = 1;
|
||||
}
|
||||
if (driver_descr_needed > driver_descr_len)
|
||||
{
|
||||
ODBC_DEBUG_PRINTF("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);
|
||||
redo_call = 1;
|
||||
}
|
||||
|
||||
if ((server_name == NULL) || (driver_descr == NULL))
|
||||
{
|
||||
ODBC_RAISE_EXCEPTION("Could not allocate memory for return values");
|
||||
return S48_UNSPECIFIC;
|
||||
}
|
||||
|
||||
if (redo_call) goto redo_loop;
|
||||
}
|
||||
|
||||
first = 0;
|
||||
|
@ -253,6 +285,7 @@ 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);
|
||||
|
@ -281,6 +314,9 @@ s48_value odbc_sql_data_sources(s48_value env_handle)
|
|||
}
|
||||
}
|
||||
|
||||
free(server_name);
|
||||
free(driver_descr);
|
||||
|
||||
S48_GC_UNPROTECT();
|
||||
return result;
|
||||
}
|
||||
|
@ -401,21 +437,35 @@ s48_value odbc_sql_get_info_string(s48_value conn_handle, s48_value info_key)
|
|||
SQLHDBC ch;
|
||||
SQLUSMALLINT ik;
|
||||
SQLRETURN retval;
|
||||
SQLCHAR info[ODBC_GET_INFO_MAX_LEN];
|
||||
SQLSMALLINT buffer_size;
|
||||
SQLCHAR *buffer = NULL;
|
||||
SQLSMALLINT buffer_needed, buffer_len;
|
||||
|
||||
ODBC_DEBUG_PRINTF("odbc_sql_get_info_string\n");
|
||||
|
||||
ch = (SQLHDBC) s48_extract_integer(conn_handle);
|
||||
ik = (SQLUSMALLINT) s48_extract_integer(info_key);
|
||||
buffer_len = ODBC_RETVAL_BUFFER_INITIAL_SIZE;
|
||||
|
||||
retval = SQLGetInfo(ch, ik, &info, ODBC_GET_INFO_MAX_LEN, &buffer_size);
|
||||
for (;;)
|
||||
{
|
||||
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))
|
||||
buffer_len = buffer_needed+1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
switch (retval)
|
||||
{
|
||||
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
||||
{
|
||||
return s48_enter_string(info);
|
||||
s48_value res = s48_enter_string(buffer);
|
||||
free(buffer);
|
||||
return res;
|
||||
}
|
||||
case SQL_ERROR:
|
||||
{
|
||||
|
@ -612,21 +662,32 @@ s48_value odbc_sql_get_connect_attr_string(s48_value conn_handle,
|
|||
|
||||
SQLHDBC ch;
|
||||
SQLINTEGER attr;
|
||||
SQLCHAR buffer[ODBC_GET_CONNECT_ATTR_MAX_LEN];
|
||||
SQLINTEGER buffer_size;
|
||||
SQLCHAR *buffer = NULL;
|
||||
SQLINTEGER buffer_needed, buffer_len;
|
||||
SQLRETURN retval;
|
||||
|
||||
ODBC_DEBUG_PRINTF("odbc_sql_get_connect_attr_string\n");
|
||||
|
||||
buffer_len = ODBC_RETVAL_BUFFER_INITIAL_SIZE;
|
||||
|
||||
retval = SQLGetConnectAttr(ch, attr,
|
||||
buffer, ODBC_GET_CONNECT_ATTR_MAX_LEN-1,
|
||||
&buffer_size);
|
||||
for (;;) {
|
||||
odbc_sql_alloc((void **) &buffer, buffer_len, sizeof(SQLCHAR));
|
||||
|
||||
retval = SQLGetConnectAttr(ch, attr, buffer, buffer_len, &buffer_needed);
|
||||
|
||||
if (ODBC_SUCCESS(retval) && (buffer_needed > buffer_len))
|
||||
buffer_needed = buffer_len;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
switch (retval)
|
||||
{
|
||||
case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO:
|
||||
{
|
||||
return s48_enter_string(buffer);
|
||||
s48_value res = s48_enter_string(buffer);
|
||||
free(buffer);
|
||||
return res;
|
||||
}
|
||||
case SQL_ERROR:
|
||||
{
|
||||
|
@ -816,7 +877,6 @@ s48_value odbc_sql_set_stmt_attr_string(s48_value stmt_handle,
|
|||
s48_value attribute,
|
||||
s48_value value)
|
||||
{
|
||||
|
||||
SQLHSTMT sh;
|
||||
SQLINTEGER attr;
|
||||
SQLCHAR *val;
|
||||
|
@ -828,8 +888,7 @@ s48_value odbc_sql_set_stmt_attr_string(s48_value stmt_handle,
|
|||
attr = (SQLINTEGER) s48_extract_integer(attribute);
|
||||
val = (SQLCHAR *) s48_extract_string(value);
|
||||
|
||||
retval = SQLSetStmtAttr(sh, attr,
|
||||
val, S48_STRING_LENGTH(value));
|
||||
retval = SQLSetStmtAttr(sh, attr, val, S48_STRING_LENGTH(value));
|
||||
|
||||
switch (retval)
|
||||
{
|
||||
|
@ -855,10 +914,8 @@ s48_value odbc_sql_set_stmt_attr_string(s48_value stmt_handle,
|
|||
}
|
||||
}
|
||||
|
||||
s48_value odbc_sql_get_stmt_attr_int(s48_value stmt_handle,
|
||||
s48_value attribute)
|
||||
s48_value odbc_sql_get_stmt_attr_int(s48_value stmt_handle, s48_value attribute)
|
||||
{
|
||||
|
||||
SQLHSTMT sh;
|
||||
SQLINTEGER attr, val, buf_size;
|
||||
SQLRETURN retval;
|
||||
|
@ -899,20 +956,32 @@ s48_value odbc_sql_get_stmt_attr_string(s48_value stmt_handle,
|
|||
{
|
||||
|
||||
SQLHSTMT sh;
|
||||
SQLINTEGER attr, buf_size;
|
||||
SQLCHAR buf[ODBC_GET_STMT_ATTR_MAX_LEN];
|
||||
SQLINTEGER attr, buffer_len, buffer_needed;
|
||||
SQLCHAR *buffer = NULL;
|
||||
SQLRETURN retval;
|
||||
|
||||
ODBC_DEBUG_PRINTF("odbc_sql_get_stmt_attr_string\n");
|
||||
|
||||
retval = SQLGetStmtAttr(sh, attr, &buf,
|
||||
ODBC_GET_STMT_ATTR_MAX_LEN-1, &buf_size);
|
||||
|
||||
buffer_len = ODBC_RETVAL_BUFFER_INITIAL_SIZE;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
odbc_sql_alloc((void **) &buffer, buffer_len, sizeof(SQLCHAR));
|
||||
retval = SQLGetStmtAttr(sh, attr, &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:
|
||||
{
|
||||
return s48_enter_string(buf);
|
||||
s48_value res = s48_enter_string(buffer);
|
||||
free(buffer);
|
||||
return res;
|
||||
}
|
||||
case SQL_ERROR:
|
||||
{
|
||||
|
@ -1007,8 +1076,8 @@ s48_value odbc_sql_get_desc_field_string(s48_value desc_handle, s48_value rec_nu
|
|||
{
|
||||
SQLHDESC dh;
|
||||
SQLSMALLINT rn, fi;
|
||||
SQLCHAR value[ODBC_MAX_GET_DESC_FIELD_STR_LEN];
|
||||
SQLINTEGER buffer_len;
|
||||
SQLCHAR *buffer = NULL;
|
||||
SQLINTEGER buffer_len, buffer_needed;
|
||||
SQLRETURN retval;
|
||||
|
||||
ODBC_DEBUG_PRINTF("odbc_sql_get_desc_field_string\n");
|
||||
|
@ -1017,15 +1086,26 @@ s48_value odbc_sql_get_desc_field_string(s48_value desc_handle, s48_value rec_nu
|
|||
rn = (SQLSMALLINT) s48_extract_integer(rec_number);
|
||||
fi = (SQLSMALLINT) s48_extract_integer(field_id);
|
||||
|
||||
retval = SQLGetDescField(dh, rn, fi, (SQLPOINTER) value,
|
||||
(ODBC_MAX_GET_DESC_FIELD_STR_LEN - 1),
|
||||
&buffer_len);
|
||||
buffer_len = ODBC_RETVAL_BUFFER_INITIAL_SIZE;
|
||||
for (;;)
|
||||
{
|
||||
odbc_sql_alloc((void **) &buffer, buffer_len, sizeof(SQLCHAR));
|
||||
retval = SQLGetDescField(dh, rn, fi, (SQLPOINTER) 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:
|
||||
{
|
||||
return s48_enter_string(value);
|
||||
s48_value res = s48_enter_string(buffer);
|
||||
free(buffer);
|
||||
return res;
|
||||
}
|
||||
case SQL_NO_DATA:
|
||||
{
|
||||
|
@ -1344,20 +1424,32 @@ s48_value odbc_sql_get_cursor_name(s48_value stmt_handle)
|
|||
{
|
||||
SQLHSTMT sh;
|
||||
SQLRETURN retval;
|
||||
SQLCHAR cursorname[ODBC_MAX_CURSOR_NAME_STR_LEN];
|
||||
SQLSMALLINT buffer_len;
|
||||
SQLCHAR *buffer = NULL;
|
||||
SQLSMALLINT buffer_len, buffer_needed;
|
||||
|
||||
ODBC_DEBUG_PRINTF("odbc_sql_get_cursor_name\n");
|
||||
|
||||
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
|
||||
|
||||
retval = SQLGetCursorName(sh, cursorname, ODBC_MAX_CURSOR_NAME_STR_LEN - 1, &buffer_len);
|
||||
buffer_len = ODBC_RETVAL_BUFFER_INITIAL_SIZE;
|
||||
for (;;)
|
||||
{
|
||||
odbc_sql_alloc((void **) &buffer, buffer_len, sizeof(SQLCHAR));
|
||||
retval = SQLGetCursorName(sh, 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:
|
||||
{
|
||||
return s48_enter_string(cursorname);
|
||||
s48_value res = s48_enter_string(buffer);
|
||||
free(buffer);
|
||||
return s48_enter_string(buffer);
|
||||
}
|
||||
case SQL_ERROR:
|
||||
{
|
||||
|
@ -1514,24 +1606,35 @@ s48_value odbc_sql_execute_direct(s48_value stmt_handle,
|
|||
s48_value odbc_sql_native_sql(s48_value conn_handle, s48_value stmt_txt)
|
||||
{
|
||||
SQLHDBC ch;
|
||||
SQLCHAR *stmt_in, stmt_out[ODBC_MAX_NATIVE_SQL_STR_LEN];
|
||||
SQLINTEGER buffer_len;
|
||||
SQLCHAR *stmt_in, *stmt_out = NULL;
|
||||
SQLINTEGER buffer_len, buffer_needed;
|
||||
SQLRETURN retval;
|
||||
|
||||
ch = (SQLHDBC) s48_extract_integer(conn_handle);
|
||||
stmt_in = (SQLCHAR *) s48_extract_string(stmt_txt);
|
||||
|
||||
ODBC_DEBUG_PRINTF("odbc_sql_native_sql\n");
|
||||
|
||||
buffer_len = ODBC_RETVAL_BUFFER_INITIAL_SIZE;
|
||||
for (;;)
|
||||
{
|
||||
odbc_sql_alloc((void **) &stmt_out, buffer_len, sizeof(SQLCHAR));
|
||||
retval = SQLNativeSql(ch, stmt_in, S48_STRING_LENGTH(stmt_txt),
|
||||
stmt_out, buffer_len, &buffer_needed);
|
||||
|
||||
retval = SQLNativeSql(ch, stmt_in, S48_STRING_LENGTH(stmt_txt),
|
||||
stmt_out, ODBC_MAX_NATIVE_SQL_STR_LEN - 1,
|
||||
&buffer_len);
|
||||
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:
|
||||
{
|
||||
return s48_enter_string(stmt_out);
|
||||
s48_value res = s48_enter_string(stmt_out);
|
||||
free(stmt_out);
|
||||
return res;
|
||||
}
|
||||
case SQL_ERROR:
|
||||
{
|
||||
|
@ -1672,14 +1775,25 @@ s48_value odbc_sql_get_data(s48_value stmt_handle,
|
|||
case SQL_C_CHAR:
|
||||
case SQL_C_BINARY:
|
||||
{
|
||||
SQLCHAR str[ODBC_GET_DATA_MAX_STR_LEN];
|
||||
SQLINTEGER str_len;
|
||||
|
||||
retval = SQLGetData(sh, cn, tt,
|
||||
str, ODBC_GET_DATA_MAX_STR_LEN-1,
|
||||
&str_len);
|
||||
SQLCHAR *buffer = NULL;
|
||||
SQLINTEGER buffer_len, buffer_needed;
|
||||
s48_value res = S48_UNSPECIFIC;
|
||||
|
||||
buffer_len = ODBC_RETVAL_BUFFER_INITIAL_SIZE;
|
||||
for (;;)
|
||||
{
|
||||
odbc_sql_alloc((void **) &buffer, buffer_len, sizeof(SQLCHAR));
|
||||
retval = SQLGetData(sh, cn, tt,
|
||||
buffer, buffer_len, &buffer_needed);
|
||||
if (ODBC_SUCCESS(retval) && (buffer_needed > buffer_len))
|
||||
buffer_len = buffer_needed+1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
check_sql_get_data_result(retval, sh);
|
||||
return s48_enter_string((char *) str);
|
||||
res = s48_enter_string(buffer);
|
||||
free(buffer);
|
||||
return res;
|
||||
}
|
||||
case SQL_C_SSHORT:
|
||||
case SQL_C_USHORT:
|
||||
|
@ -1966,8 +2080,8 @@ s48_value odbc_sql_describe_col(s48_value stmt_handle, s48_value column_number)
|
|||
|
||||
SQLHSTMT sh;
|
||||
SQLSMALLINT cn;
|
||||
SQLCHAR column_name[ODBC_DESCRIBE_COL_MAX_STR_LEN];
|
||||
SQLSMALLINT buf_len, data_type, digits, nullable;
|
||||
SQLCHAR *buffer = NULL;
|
||||
SQLSMALLINT buffer_len, buffer_needed, data_type, digits, nullable;
|
||||
SQLUINTEGER col_size;
|
||||
SQLRETURN retval;
|
||||
s48_value col_rec = S48_UNSPECIFIC;
|
||||
|
@ -1980,14 +2094,20 @@ s48_value odbc_sql_describe_col(s48_value stmt_handle, s48_value column_number)
|
|||
sh = (SQLHSTMT) s48_extract_integer(stmt_handle);
|
||||
cn = (SQLSMALLINT) s48_extract_integer(column_number);
|
||||
|
||||
retval = SQLDescribeCol(sh, cn,
|
||||
column_name,
|
||||
ODBC_DESCRIBE_COL_MAX_STR_LEN - 1,
|
||||
&buf_len,
|
||||
&data_type,
|
||||
&col_size,
|
||||
&digits,
|
||||
&nullable);
|
||||
buffer_len = ODBC_RETVAL_BUFFER_INITIAL_SIZE;
|
||||
for (;;)
|
||||
{
|
||||
odbc_sql_alloc((void **) &buffer, buffer_len, sizeof(SQLCHAR));
|
||||
retval = SQLDescribeCol(sh, cn,
|
||||
buffer, buffer_len, &buffer_needed,
|
||||
&data_type, &col_size, &digits,
|
||||
&nullable);
|
||||
|
||||
if (ODBC_SUCCESS(retval) && (buffer_needed > buffer_len))
|
||||
buffer_len = buffer_needed+1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
switch (retval)
|
||||
{
|
||||
|
@ -1995,7 +2115,7 @@ s48_value odbc_sql_describe_col(s48_value stmt_handle, s48_value column_number)
|
|||
{
|
||||
col_rec = s48_make_record(odbc_column_record_type);
|
||||
S48_RECORD_SET(col_rec, SR_ODBC_COLUMN_NAME,
|
||||
s48_enter_string(column_name));
|
||||
s48_enter_string(buffer));
|
||||
S48_RECORD_SET(col_rec, SR_ODBC_COLUMN_TYPE,
|
||||
s48_enter_integer(data_type));
|
||||
S48_RECORD_SET(col_rec, SR_ODBC_COLUMN_SIZE,
|
||||
|
@ -2006,6 +2126,7 @@ s48_value odbc_sql_describe_col(s48_value stmt_handle, s48_value column_number)
|
|||
s48_enter_integer(nullable));
|
||||
|
||||
S48_GC_UNPROTECT();
|
||||
free(buffer);
|
||||
return col_rec;
|
||||
}
|
||||
case SQL_STILL_EXECUTING:
|
||||
|
@ -2817,8 +2938,8 @@ s48_value odbc_sql_get_diag_recs(s48_value handle_type, s48_value handle)
|
|||
SQLHANDLE h;
|
||||
SQLCHAR sql_state[6];
|
||||
SQLINTEGER native_error;
|
||||
SQLCHAR message[ERROR_MSG_BUFFER_LEN];
|
||||
SQLSMALLINT i, message_len, more_recs;
|
||||
SQLCHAR *buffer = NULL;
|
||||
SQLSMALLINT i, more_recs, buffer_len, buffer_needed;
|
||||
SQLRETURN retval;
|
||||
s48_value res = S48_UNSPECIFIC;
|
||||
s48_value diag_rec = S48_UNSPECIFIC;
|
||||
|
@ -2833,12 +2954,23 @@ s48_value odbc_sql_get_diag_recs(s48_value handle_type, s48_value handle)
|
|||
ODBC_DEBUG_PRINTF("odbc_sql_get_diag_recs\n");
|
||||
|
||||
i = more_recs = 1;
|
||||
buffer_len = ODBC_RETVAL_BUFFER_INITIAL_SIZE;
|
||||
while (more_recs) {
|
||||
|
||||
diag_rec = s48_make_record(odbc_diag_record_type);
|
||||
retval = SQLGetDiagRec(ht, h, i,
|
||||
sql_state, &native_error,
|
||||
message, sizeof(message), &message_len);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
odbc_sql_alloc((void **) &buffer, buffer_len, sizeof(SQLCHAR));
|
||||
retval = SQLGetDiagRec(ht, h, i,
|
||||
sql_state, &native_error,
|
||||
buffer, buffer_len, &buffer_needed);
|
||||
|
||||
if (ODBC_SUCCESS(retval) && (buffer_needed > buffer_len))
|
||||
buffer_len = buffer_needed+1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
switch (retval)
|
||||
{
|
||||
|
@ -2846,7 +2978,7 @@ s48_value odbc_sql_get_diag_recs(s48_value handle_type, s48_value handle)
|
|||
{
|
||||
S48_RECORD_SET(diag_rec, SR_ODBC_DIAG_SQL_STATE, s48_enter_string(sql_state));
|
||||
S48_RECORD_SET(diag_rec, SR_ODBC_DIAG_NATIVE_ERROR, s48_enter_integer(native_error));
|
||||
S48_RECORD_SET(diag_rec, SR_ODBC_DIAG_MESSAGE, s48_enter_string(message));
|
||||
S48_RECORD_SET(diag_rec, SR_ODBC_DIAG_MESSAGE, s48_enter_string(buffer));
|
||||
res = s48_cons(diag_rec, res);
|
||||
break;
|
||||
}
|
||||
|
@ -2875,6 +3007,7 @@ s48_value odbc_sql_get_diag_recs(s48_value handle_type, s48_value handle)
|
|||
}
|
||||
|
||||
S48_GC_UNPROTECT(); /* res */
|
||||
free(buffer);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -3050,6 +3183,30 @@ s48_value struct_to_sql_timestamp_record(SQL_TIMESTAMP_STRUCT *ts)
|
|||
return sql_timestamp;
|
||||
}
|
||||
|
||||
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
|
||||
*buffer = (void *) calloc(buffer_len+1, type_len);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef ODBC_DEBUG_MSGS
|
||||
printf("realloc %d\n", buffer_len*type_len);
|
||||
#endif
|
||||
*buffer = (void *) realloc(*buffer, buffer_len*type_len);
|
||||
}
|
||||
|
||||
if (*buffer == NULL)
|
||||
{
|
||||
ODBC_RAISE_EXCEPTION("Could not allocate return value buffer");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void s48_init_odbc(void)
|
||||
{
|
||||
/* bindings for record types */
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#define ODBC_MAX_NATIVE_SQL_STR_LEN ODBC_MAX_STR_LEN
|
||||
#define ODBC_MAX_GET_DESC_FIELD_STR_LEN ODBC_MAX_STR_LEN
|
||||
|
||||
#define ODBC_RETVAL_BUFFER_INITIAL_SIZE 3
|
||||
|
||||
#define ODBC_DEBUG_MSGS 1
|
||||
|
||||
#define ODBC_RAISE_EXCEPTION(MSG) s48_raise_string_os_error(MSG)
|
||||
|
@ -41,6 +43,9 @@
|
|||
|
||||
/* offsets for scheme records */
|
||||
|
||||
/* some useful macros */
|
||||
#define ODBC_SUCCESS(retval) ((retval == SQL_SUCCESS) || (retval == SQL_SUCCESS_WITH_INFO))
|
||||
|
||||
/* corresponds to sql-date */
|
||||
static s48_value sql_date_record_type = S48_FALSE;
|
||||
|
||||
|
@ -419,5 +424,7 @@ s48_value struct_to_sql_time_record(SQL_TIME_STRUCT *ts);
|
|||
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);
|
||||
|
||||
void s48_init_odbc(void);
|
||||
|
||||
|
|
|
@ -203,7 +203,7 @@
|
|||
(define sql-api-sqlsetscrolloptions 69)
|
||||
(define sql-api-sqltableprivileges 70)
|
||||
|
||||
;;; info keys for odbc-sql-get-info-argint/string
|
||||
;;; info keys for odbc-sql-get-info-arg-int/string
|
||||
; ODBC 1.0, returns integer
|
||||
(define sql-get-info-arg-maxdriverconnections 0)
|
||||
; ODBC 1.0, returns integer
|
||||
|
@ -472,7 +472,7 @@
|
|||
|
||||
(define (odbc-sql-data-sources env-handle)
|
||||
(check-arg environment-handle? env-handle odbc-sql-data-sources)
|
||||
(odbc-sql-data-sources-internal (environment-handle-handle env-handle)))
|
||||
(reverse (odbc-sql-data-sources-internal (environment-handle-handle env-handle))))
|
||||
|
||||
(import-lambda-definition odbc-sql-data-sources-internal
|
||||
(env-handle)
|
||||
|
@ -685,6 +685,14 @@
|
|||
(stmt-handle stmt-txt)
|
||||
"odbc_sql_execute_direct")
|
||||
|
||||
(define (odbc-sql-native-sql conn-handle stmt-txt)
|
||||
(check-arg connection-handle? conn-handle odbc-sql-native-sql)
|
||||
(odbc-sql-native-sql-internal (connection-handle-handle conn-handle)
|
||||
stmt-txt))
|
||||
|
||||
(import-lambda-definition odbc-sql-native-sql-internal
|
||||
(conn-handle stmt-txt)
|
||||
"odbc_sql_native_sql")
|
||||
|
||||
;;; PART 7
|
||||
|
||||
|
|
Loading…
Reference in New Issue