Skip to content

Commit 0ac9b79

Browse files
authored
Merge pull request #6 from bpintea/feature/catalog_fixes
Catalog function fixes
2 parents d4127f1 + 48714fe commit 0ac9b79

File tree

6 files changed

+243
-65
lines changed

6 files changed

+243
-65
lines changed

driver/catalogue.c

Lines changed: 211 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,153 @@
2828
#include "info.h"
2929
#include "queries.h"
3030

31-
// TODO: add type (and schema, when supported)
32-
#define SQL_TABLES "SYS TABLES" \
33-
" CATALOG LIKE " ESODBC_STRING_DELIM WPFWP_LDESC ESODBC_STRING_DELIM \
31+
32+
#define SYS_CATALOGS \
33+
"SYS CATALOGS"
34+
35+
/* SYS TABLES syntax tokens; these need to stay broken down, since this
36+
* query makes a difference between a predicate being '%' or left out */
37+
// TODO: schema, when supported
38+
#define SQL_TABLES \
39+
"SYS TABLES"
40+
#define SQL_TABLES_CAT \
41+
" CATALOG LIKE " ESODBC_STRING_DELIM WPFWP_LDESC ESODBC_STRING_DELIM
42+
#define SQL_TABLES_TAB \
3443
" LIKE " ESODBC_STRING_DELIM WPFWP_LDESC ESODBC_STRING_DELIM
44+
#define SQL_TABLES_TYP \
45+
" TYPE " WPFWP_LDESC
3546

3647
// TODO add schema, when supported
3748
#define SQL_COLUMNS(...) "SYS COLUMNS" __VA_ARGS__ \
3849
" TABLE LIKE " ESODBC_STRING_DELIM WPFWP_LDESC ESODBC_STRING_DELIM \
3950
" LIKE " ESODBC_STRING_DELIM WPFWP_LDESC ESODBC_STRING_DELIM
40-
#define SQL_COL_CAT \
51+
#define SQL_COL_CAT \
4152
" CATALOG " ESODBC_STRING_DELIM WPFWP_LDESC ESODBC_STRING_DELIM \
4253

4354

55+
/* writes into 'dest', of size 'room', the current catalog of 'dbc'.
56+
* returns negative on error, or the char count written otherwise */
57+
SQLSMALLINT copy_current_catalog(esodbc_dbc_st *dbc, SQLWCHAR *dest,
58+
SQLSMALLINT room)
59+
{
60+
esodbc_stmt_st *stmt = NULL;
61+
SQLSMALLINT used = -1; /*failure*/
62+
SQLLEN row_cnt;
63+
SQLLEN ind_len = SQL_NULL_DATA;
64+
SQLWCHAR buff[ESODBC_MAX_IDENTIFIER_LEN];
65+
SQLWCHAR *catalog;
66+
67+
if (! SQL_SUCCEEDED(EsSQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt))) {
68+
ERRH(dbc, "failed to alloc a statement handle.");
69+
return -1;
70+
}
71+
assert(stmt);
72+
73+
if (! SQL_SUCCEEDED(attach_sql(stmt, MK_WPTR(SYS_CATALOGS),
74+
sizeof(SYS_CATALOGS) - 1))) {
75+
ERRH(dbc, "failed to attach query to statement.");
76+
goto end;
77+
}
78+
if (! SQL_SUCCEEDED(post_statement(stmt))) {
79+
ERRH(dbc, "failed to post query.");
80+
goto end;
81+
}
82+
83+
/* check that we have received proper number of rows (non-0, less than
84+
* max allowed here) */
85+
if (! SQL_SUCCEEDED(EsSQLRowCount(stmt, &row_cnt))) {
86+
ERRH(dbc, "failed to get result rows count.");
87+
goto end;
88+
} else if (row_cnt <= 0) {
89+
WARNH(stmt, "Elasticsearch returned no current catalog.");
90+
catalog = MK_WPTR(""); /* empty string, it's not quite an error */
91+
} else {
92+
DBGH(stmt, "Elasticsearch catalogs rows count: %ld.", row_cnt);
93+
if (1 < row_cnt) {
94+
WARNH(dbc, "Elasticsearch connected to %d clusters, returning "
95+
"the first's name as current catalog.", row_cnt);
96+
}
97+
98+
if (! SQL_SUCCEEDED(EsSQLBindCol(stmt, /*col#*/1, SQL_C_WCHAR, buff,
99+
sizeof(buff), &ind_len))) {
100+
ERRH(dbc, "failed to bind first column.");
101+
goto end;
102+
}
103+
if (! SQL_SUCCEEDED(EsSQLFetch(stmt))) {
104+
ERRH(stmt, "failed to fetch results.");
105+
goto end;
106+
}
107+
if (ind_len <= 0) {
108+
WARNH(dbc, "NULL catalog received."); /*tho maybe != NULL_DATA */
109+
catalog = MK_WPTR("");
110+
} else {
111+
catalog = buff;
112+
DBGH(dbc, "current catalog (first value returned): `" LWPD "`.",
113+
catalog);
114+
}
115+
}
116+
117+
if (! SQL_SUCCEEDED(write_wptr(&dbc->hdr.diag, dest, catalog, room,
118+
&used))) {
119+
ERRH(dbc, "failed to copy catalog: `" LWPD "`.", catalog);
120+
used = -1; /* write_wptr() can change pointer, and still fail */
121+
}
122+
123+
end:
124+
/* safe even if no binding occured */
125+
if (! SQL_SUCCEEDED(EsSQLFreeStmt(stmt, SQL_UNBIND))) {
126+
ERRH(stmt, "failed to unbind statement");
127+
used = -1;
128+
}
129+
if (! SQL_SUCCEEDED(EsSQLFreeHandle(SQL_HANDLE_STMT, stmt))) {
130+
ERRH(dbc, "failed to free statement handle!");
131+
}
132+
return used;
133+
}
134+
135+
/*
136+
* Quote the tokens in a string: "a, b,,c" -> "'a','b',,'c'".
137+
* No string sanity done (garbage in, garbage out).
138+
*/
139+
size_t quote_tokens(SQLWCHAR *src, size_t len, SQLWCHAR *dest)
140+
{
141+
size_t i;
142+
BOOL copying;
143+
SQLWCHAR *pos;
144+
145+
copying = FALSE;
146+
pos = dest;
147+
for (i = 0; i < len; i ++) {
148+
switch (src[i]) {
149+
/* ignore white space */
150+
case L' ':
151+
case L'\t':
152+
if (copying) {
153+
*pos ++ = L'\''; /* end current token */
154+
copying = FALSE;
155+
}
156+
continue; /* don't copy WS */
157+
158+
case L',':
159+
if (copying) {
160+
*pos ++ = L'\''; /* end current token */
161+
copying = FALSE;
162+
} /* else continue; -- to remove extra `,` */
163+
break;
164+
165+
default:
166+
if (! copying) {
167+
*pos ++ = L'\''; /* start a new token */
168+
}
169+
copying = TRUE;
170+
}
171+
*pos ++ = src[i];
172+
}
173+
/* should not overrun */
174+
assert(i < 2/*see typ_buf below*/ * ESODBC_MAX_IDENTIFIER_LEN);
175+
return pos - dest;
176+
}
177+
44178
SQLRETURN EsSQLTablesW(
45179
SQLHSTMT StatementHandle,
46180
_In_reads_opt_(NameLength1) SQLWCHAR *CatalogName,
@@ -54,29 +188,47 @@ SQLRETURN EsSQLTablesW(
54188
{
55189
esodbc_stmt_st *stmt = STMH(StatementHandle);
56190
SQLRETURN ret;
57-
SQLWCHAR wbuf[sizeof(SQL_TABLES) + 2 * ESODBC_MAX_IDENTIFIER_LEN];
58-
SQLWCHAR *table, *schema, *catalog;
59-
size_t cnt_tab, cnt_sch, cnt_cat, pos;
191+
/* b/c declaring an array with a const doesn't work with MSVC's compiler */
192+
enum wbuf_len { wbuf_len = sizeof(SQL_TABLES)
193+
+ sizeof(SQL_TABLES_CAT)
194+
+ sizeof(SQL_TABLES_TAB)
195+
+ sizeof(SQL_TABLES_TYP)
196+
+ 3 * ESODBC_MAX_IDENTIFIER_LEN /* it has 4x 0-term space */
197+
};
198+
SQLWCHAR wbuf[wbuf_len];
199+
SQLWCHAR *table, *schema, *catalog, *type;
200+
size_t cnt_tab, cnt_sch, cnt_cat, cnt_typ, pos;
201+
/* 2x: "a,b,c" -> "'a','b','c'" : each "x," => "'x'," */
202+
SQLWCHAR typ_buf[2 * ESODBC_MAX_IDENTIFIER_LEN];
60203

61204
if (stmt->metadata_id == SQL_TRUE)
62205
FIXME; // FIXME
63206

207+
pos = sizeof(SQL_TABLES) - 1;
208+
wmemcpy(wbuf, MK_WPTR(SQL_TABLES), pos);
209+
64210
if (CatalogName) {
65211
catalog = CatalogName;
66212
if (NameLength1 == SQL_NTS) {
67213
cnt_cat = wcslen(catalog);
68214
if (ESODBC_MAX_IDENTIFIER_LEN < cnt_cat) {
69215
ERRH(stmt, "catalog identifier name '" LTPDL "' too long "
70-
"(%d. max=%d).", cnt_cat, catalog, cnt_cat,
216+
"(%zd. max=%d).", (int)cnt_cat, catalog, cnt_cat,
71217
ESODBC_MAX_IDENTIFIER_LEN);
72218
RET_HDIAG(stmt, SQL_STATE_HY090, "catalog name too long", 0);
73219
}
74220
} else {
75221
cnt_cat = NameLength1;
76222
}
77-
} else {
78-
catalog = MK_WPTR(SQL_ALL_CATALOGS);
79-
cnt_cat = sizeof(SQL_ALL_CATALOGS) - /*0-term*/1;
223+
224+
cnt_cat = swprintf(wbuf + pos, wbuf_len - pos, SQL_TABLES_CAT,
225+
(int)cnt_cat, catalog);
226+
if (cnt_cat <= 0) {
227+
ERRH(stmt, "failed to print 'catalog' for tables catalog SQL.");
228+
RET_HDIAGS(stmt, SQL_STATE_HY000);
229+
} else {
230+
pos += cnt_cat;
231+
}
80232
}
81233

82234
if (SchemaName) {
@@ -85,23 +237,20 @@ SQLRETURN EsSQLTablesW(
85237
cnt_sch = wcslen(schema);
86238
if (ESODBC_MAX_IDENTIFIER_LEN < cnt_sch) {
87239
ERRH(stmt, "schema identifier name '" LTPDL "' too long "
88-
"(%d. max=%d).", cnt_sch, schema, cnt_sch,
240+
"(%zd. max=%d).", (int)cnt_sch, schema, cnt_sch,
89241
ESODBC_MAX_IDENTIFIER_LEN);
90242
RET_HDIAG(stmt, SQL_STATE_HY090, "schema name too long", 0);
91243
}
92244
} else {
93245
cnt_sch = NameLength2;
94246
}
95-
} else {
96-
schema = MK_WPTR(SQL_ALL_SCHEMAS);
97-
cnt_sch = sizeof(SQL_ALL_SCHEMAS) - /*0-term*/1;
98-
}
99247

100-
/* TODO: server support needed for sch. name filtering */
101-
if (cnt_sch && wszmemcmp(schema, MK_WPTR(SQL_ALL_SCHEMAS),
102-
(long)cnt_sch)) {
103-
ERRH(stmt, "filtering by schemas is not supported.");
104-
RET_HDIAG(stmt, SQL_STATE_IM001, "schema filtering not supported", 0);
248+
/* TODO: server support needed for sch. name filtering */
249+
if (wszmemcmp(schema, MK_WPTR(SQL_ALL_SCHEMAS), (long)cnt_sch)) {
250+
ERRH(stmt, "filtering by schemas is not supported.");
251+
RET_HDIAG(stmt, SQL_STATE_IM001, "schema filtering not supported",
252+
0);
253+
}
105254
}
106255

107256
// FIXME: string needs escaping of % \\ _
@@ -111,32 +260,57 @@ SQLRETURN EsSQLTablesW(
111260
cnt_tab = wcslen(table);
112261
if (ESODBC_MAX_IDENTIFIER_LEN < cnt_tab) {
113262
ERRH(stmt, "table identifier name '" LTPDL "' too long "
114-
"(%d. max=%d).", cnt_tab, table, cnt_tab,
263+
"(%zd. max=%d).", (int)cnt_tab, table, cnt_tab,
115264
ESODBC_MAX_IDENTIFIER_LEN);
116265
RET_HDIAG(stmt, SQL_STATE_HY090, "table name too long", 0);
117266
}
118267
} else {
119268
cnt_tab = NameLength3;
120269
}
121-
} else {
122-
table = MK_WPTR(ESODBC_ALL_TABLES);
123-
cnt_tab = sizeof(ESODBC_ALL_TABLES) - /*0-term*/1;
124-
}
125-
#if 1 // TODO: GH#4334
126-
if (cnt_tab == 0) {
127-
table = MK_WPTR(ESODBC_ALL_TABLES);
128-
cnt_tab = sizeof(ESODBC_ALL_TABLES) - /*0-term*/1;
270+
271+
cnt_tab = swprintf(wbuf + pos, wbuf_len - pos, SQL_TABLES_TAB,
272+
(int)cnt_tab, table);
273+
if (cnt_tab <= 0) {
274+
ERRH(stmt, "failed to print 'table' for tables catalog SQL.");
275+
RET_HDIAGS(stmt, SQL_STATE_HY000);
276+
} else {
277+
pos += cnt_tab;
278+
}
129279
}
130-
#endif // 1
131280

132-
/* print SQL to send to server */
133-
pos = swprintf(wbuf, sizeof(wbuf)/sizeof(wbuf[0]), SQL_TABLES,
134-
(int)cnt_cat, catalog, (int)cnt_tab, table);
135-
if (pos <= 0) {
136-
ERRH(stmt, "failed to print 'tables' catalog SQL.");
137-
RET_HDIAGS(stmt, SQL_STATE_HY000);
281+
if (TableType) {
282+
type = TableType;
283+
if (NameLength4 == SQL_NTS) {
284+
cnt_typ = wcslen(type);
285+
if (ESODBC_MAX_IDENTIFIER_LEN < cnt_typ) {
286+
ERRH(stmt, "type identifier name '" LTPDL "' too long "
287+
"(%zd. max=%d).", (int)cnt_typ, type, cnt_typ,
288+
ESODBC_MAX_IDENTIFIER_LEN);
289+
RET_HDIAG(stmt, SQL_STATE_HY090, "type name too long", 0);
290+
}
291+
} else {
292+
cnt_typ = NameLength4;
293+
}
294+
295+
/* In this argument, "each value can be enclosed in single quotation
296+
* marks (') or unquoted" => quote if not quoted (see GH#30398). */
297+
if (! wcsnstr(type, cnt_typ, L'\'')) {
298+
cnt_typ = quote_tokens(type, cnt_typ, typ_buf);
299+
type = typ_buf;
300+
}
301+
302+
cnt_typ = swprintf(wbuf + pos, wbuf_len - pos, SQL_TABLES_TYP,
303+
(int)cnt_typ, type);
304+
if (cnt_typ <= 0) {
305+
ERRH(stmt, "failed to print 'type' for tables catalog SQL.");
306+
RET_HDIAGS(stmt, SQL_STATE_HY000);
307+
} else {
308+
pos += cnt_typ;
309+
}
138310
}
139311

312+
DBGH(stmt, "tables catalog SQL [%d]:`" LWPDL "`.", pos, pos, wbuf);
313+
140314
ret = EsSQLFreeStmt(stmt, ESODBC_SQL_CLOSE);
141315
assert(SQL_SUCCEEDED(ret)); /* can't return error */
142316
ret = attach_sql(stmt, wbuf, pos);

driver/catalogue.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@
1919
#define __CATALOGUE_H__
2020

2121
#include "error.h"
22+
#include "handles.h"
23+
24+
25+
SQLSMALLINT copy_current_catalog(esodbc_dbc_st *dbc, SQLWCHAR *dest,
26+
SQLSMALLINT room);
27+
2228

2329
SQLRETURN EsSQLTablesW(
2430
SQLHSTMT StatementHandle,

driver/connect.c

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#include "connect.h"
2424
#include "queries.h"
25+
#include "catalogue.h"
2526
#include "log.h"
2627
#include "info.h"
2728
#include "util.h"
@@ -2095,26 +2096,6 @@ SQLRETURN EsSQLSetConnectAttrW(
20952096
return SQL_SUCCESS;
20962097
}
20972098

2098-
/* writes into 'dest', of size 'room', the current catalog of 'dbc'.
2099-
* returns negative on error, or the char count written otherwise */
2100-
static SQLSMALLINT get_current_catalog(esodbc_dbc_st *dbc, SQLWCHAR *dest,
2101-
SQLSMALLINT room)
2102-
{
2103-
SQLSMALLINT used;
2104-
SQLWCHAR *catalog = MK_WPTR("my_current_catalog"); // FIXME
2105-
2106-
//
2107-
// TODO: use the new SYS CATALOGS query
2108-
//
2109-
2110-
DBGH(dbc, "current catalog: `" LWPD "`.", catalog);
2111-
if (! SQL_SUCCEEDED(write_wptr(&dbc->hdr.diag, dest, catalog, room,
2112-
&used))) {
2113-
return -1;
2114-
}
2115-
return used;
2116-
}
2117-
21182099
SQLRETURN EsSQLGetConnectAttrW(
21192100
SQLHDBC ConnectionHandle,
21202101
SQLINTEGER Attribute,
@@ -2142,7 +2123,7 @@ SQLRETURN EsSQLGetConnectAttrW(
21422123
if (! dbc->es_types) {
21432124
ERRH(dbc, "no connection active.");
21442125
RET_HDIAGS(dbc, SQL_STATE_08003);
2145-
} else if ((used = get_current_catalog(dbc, (SQLWCHAR *)ValuePtr,
2126+
} else if ((used = copy_current_catalog(dbc, (SQLWCHAR *)ValuePtr,
21462127
(SQLSMALLINT)BufferLength)) < 0) {
21472128
ERRH(dbc, "failed to get current catalog.");
21482129
RET_STATE(dbc->hdr.diag.state);

driver/defs.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@
5959
#define ESODBC_MAX_CONCURRENT_ACTIVITIES 16
6060
/* maximum identifer length */
6161
/* TODO: review@alpha */
62-
#define ESODBC_MAX_IDENTIFIER_LEN 128
62+
/* match 'keyword' ES type lenght */
63+
#define ESODBC_MAX_IDENTIFIER_LEN 256
6364

6465

6566
/*

0 commit comments

Comments
 (0)