Skip to content

Commit

Permalink
SAVE, different improvements
Browse files Browse the repository at this point in the history
Reset IPD and APD on prepare.
Change query setting parameter names.
Support functions.
Add check to test.

TODO: better resource free, use cleanup/goto
TODO: rename function to add parameters names
TODO: put functions at the end of odbc.c
  • Loading branch information
freddy77 committed Feb 18, 2025
1 parent 9bf8548 commit 607948a
Showing 1 changed file with 78 additions and 7 deletions.
85 changes: 78 additions & 7 deletions src/odbc/odbc.c
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,53 @@ get_int_col(TDSSOCKET *tds, TDSCOLUMN *col, TDS_INT default_value)
return res.i;
}

static char *
tds5_fix_dot_query(const char *query, size_t *query_len, bool is_func)
{
#define PRM_FMT "@P%d"
int i = 0;
size_t len, pos;
const char *e, *s;
size_t size = *query_len + 30;
char *out;

if (is_func)
size += 10;

out = tds_new(char, size);
if (!out)
goto memory_error;
pos = 0;
if (is_func)
pos += sprintf(out + pos, "exec " PRM_FMT "=", ++i);

s = query;
for (;; ++i) {
e = tds_next_placeholder(s);
len = e ? e - s : strlen(s);
if (pos + len + 12 >= size) {
size = pos + len + 30;
if (!TDS_RESIZE(out, size))
goto memory_error;
}
memcpy(out + pos, s, len);
pos += len;
if (!e)
break;
pos += sprintf(out + pos, PRM_FMT, i + 1);

s = e + 1;
}
out[pos] = 0;
*query_len = pos;
return out;

memory_error:
free(out);
return NULL;
#undef PRM_FMT
}

static bool
read_params(TDS_STMT *stmt)
{
Expand All @@ -754,12 +801,16 @@ read_params(TDS_STMT *stmt)
"SUGGESTED_TDS_LENGTH",
};
unsigned column_idx[NUM_COLUMNS];
unsigned num_params = tds_count_placeholders("INSERT INTO describe(i, vc, num) VALUES(?, ?, ?)"); // TODO
const char *query = "INSERT INTO describe(i, vc, num) VALUES(@P1, @P2, @P3)";
const char *query = tds_dstr_cstr(&stmt->query);
size_t query_len = tds_dstr_len(&stmt->query);
unsigned num_params = tds_count_placeholders(query);
char *new_query = NULL;

/* allocate tds */
if (!odbc_lock_statement(stmt))
if (!odbc_lock_statement(stmt)) {
odbc_errs_reset(&stmt->errs);
return false;
}

tds = stmt->tds;
stmt->params_queried = 1;
Expand All @@ -770,17 +821,30 @@ read_params(TDS_STMT *stmt)
return false;
}

/* replace parameters with names */
if (stmt->prepared_query_is_func)
++num_params;
if (num_params) {
new_query = tds5_fix_dot_query(query, &query_len, stmt->prepared_query_is_func);
if (!new_query) {
odbc_unlock_statement(stmt);
odbc_errs_add(&stmt->errs, "HY001", NULL);
return false;
}
query = new_query;
}

/* send query */
// TODO replace parameters with names, see tds5_fix_dot_query
params = odbc_add_char_param(tds, NULL, "", query, strlen(query));
// params = odbc_add_char_param(tds, NULL, "", tds_dstr_cstr(&stmt->query), tds_dstr_len(&stmt->query));
params = odbc_add_char_param(tds, NULL, "", query, query_len);
if (!params) {
free(new_query);
odbc_unlock_statement(stmt);
odbc_errs_add(&stmt->errs, "HY001", NULL);
return false;
}

if (TDS_FAILED(tds_submit_rpc(tds, "sp_describe_undeclared_parameters", params, NULL))) {
free(new_query);
tds_free_param_results(params);
odbc_unlock_statement(stmt);
return false;
Expand Down Expand Up @@ -846,7 +910,7 @@ printf("%d: XXXX Try to read params %d %u\n", __LINE__, in_row, num_params);
break;
// extract int values
res_info = tds->current_results;
printf("Mao\n");

TDSCOLUMN col[1];
memset(col, 0, sizeof(col));
int idx = 0;
Expand Down Expand Up @@ -881,6 +945,7 @@ printf("Col %d %d %d %d\n", tds_type, len, precision, scale);
break;
}
odbc_unlock_statement(stmt);
free(new_query);

/* clear IPD on error */
if (!ret)
Expand Down Expand Up @@ -4974,6 +5039,12 @@ ODBC_FUNC(SQLPrepare, (P(SQLHSTMT,hstmt), PCHARIN(SqlStr,SQLINTEGER) WIDE))
/* count parameters */
stmt->param_count = tds_count_placeholders(tds_dstr_cstr(&stmt->query));

/* reset IPD and APD */
if (!stmt->params_set) {
desc_alloc_records(stmt->ipd, 0);
desc_alloc_records(stmt->apd, 0);
}

/* trasform to native (one time, not for every SQLExecute) */
if (SQL_SUCCESS != prepare_call(stmt))
ODBC_EXIT(stmt, SQL_ERROR);
Expand Down

0 comments on commit 607948a

Please sign in to comment.