Skip to content

Commit cdb8601

Browse files
authored
Merge pull request #6 from bpintea/feature/catalog_fixes
Catalog function fixes
2 parents d6a3fc7 + 6cc82cf commit cdb8601

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
@@ -17,19 +17,153 @@
1717
#include "info.h"
1818
#include "queries.h"
1919

20-
// TODO: add type (and schema, when supported)
21-
#define SQL_TABLES "SYS TABLES" \
22-
" CATALOG LIKE " ESODBC_STRING_DELIM WPFWP_LDESC ESODBC_STRING_DELIM \
20+
21+
#define SYS_CATALOGS \
22+
"SYS CATALOGS"
23+
24+
/* SYS TABLES syntax tokens; these need to stay broken down, since this
25+
* query makes a difference between a predicate being '%' or left out */
26+
// TODO: schema, when supported
27+
#define SQL_TABLES \
28+
"SYS TABLES"
29+
#define SQL_TABLES_CAT \
30+
" CATALOG LIKE " ESODBC_STRING_DELIM WPFWP_LDESC ESODBC_STRING_DELIM
31+
#define SQL_TABLES_TAB \
2332
" LIKE " ESODBC_STRING_DELIM WPFWP_LDESC ESODBC_STRING_DELIM
33+
#define SQL_TABLES_TYP \
34+
" TYPE " WPFWP_LDESC
2435

2536
// TODO add schema, when supported
2637
#define SQL_COLUMNS(...) "SYS COLUMNS" __VA_ARGS__ \
2738
" TABLE LIKE " ESODBC_STRING_DELIM WPFWP_LDESC ESODBC_STRING_DELIM \
2839
" LIKE " ESODBC_STRING_DELIM WPFWP_LDESC ESODBC_STRING_DELIM
29-
#define SQL_COL_CAT \
40+
#define SQL_COL_CAT \
3041
" CATALOG " ESODBC_STRING_DELIM WPFWP_LDESC ESODBC_STRING_DELIM \
3142

3243

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

50193
if (stmt->metadata_id == SQL_TRUE)
51194
FIXME; // FIXME
52195

196+
pos = sizeof(SQL_TABLES) - 1;
197+
wmemcpy(wbuf, MK_WPTR(SQL_TABLES), pos);
198+
53199
if (CatalogName) {
54200
catalog = CatalogName;
55201
if (NameLength1 == SQL_NTS) {
56202
cnt_cat = wcslen(catalog);
57203
if (ESODBC_MAX_IDENTIFIER_LEN < cnt_cat) {
58204
ERRH(stmt, "catalog identifier name '" LTPDL "' too long "
59-
"(%d. max=%d).", cnt_cat, catalog, cnt_cat,
205+
"(%zd. max=%d).", (int)cnt_cat, catalog, cnt_cat,
60206
ESODBC_MAX_IDENTIFIER_LEN);
61207
RET_HDIAG(stmt, SQL_STATE_HY090, "catalog name too long", 0);
62208
}
63209
} else {
64210
cnt_cat = NameLength1;
65211
}
66-
} else {
67-
catalog = MK_WPTR(SQL_ALL_CATALOGS);
68-
cnt_cat = sizeof(SQL_ALL_CATALOGS) - /*0-term*/1;
212+
213+
cnt_cat = swprintf(wbuf + pos, wbuf_len - pos, SQL_TABLES_CAT,
214+
(int)cnt_cat, catalog);
215+
if (cnt_cat <= 0) {
216+
ERRH(stmt, "failed to print 'catalog' for tables catalog SQL.");
217+
RET_HDIAGS(stmt, SQL_STATE_HY000);
218+
} else {
219+
pos += cnt_cat;
220+
}
69221
}
70222

71223
if (SchemaName) {
@@ -74,23 +226,20 @@ SQLRETURN EsSQLTablesW(
74226
cnt_sch = wcslen(schema);
75227
if (ESODBC_MAX_IDENTIFIER_LEN < cnt_sch) {
76228
ERRH(stmt, "schema identifier name '" LTPDL "' too long "
77-
"(%d. max=%d).", cnt_sch, schema, cnt_sch,
229+
"(%zd. max=%d).", (int)cnt_sch, schema, cnt_sch,
78230
ESODBC_MAX_IDENTIFIER_LEN);
79231
RET_HDIAG(stmt, SQL_STATE_HY090, "schema name too long", 0);
80232
}
81233
} else {
82234
cnt_sch = NameLength2;
83235
}
84-
} else {
85-
schema = MK_WPTR(SQL_ALL_SCHEMAS);
86-
cnt_sch = sizeof(SQL_ALL_SCHEMAS) - /*0-term*/1;
87-
}
88236

89-
/* TODO: server support needed for sch. name filtering */
90-
if (cnt_sch && wszmemcmp(schema, MK_WPTR(SQL_ALL_SCHEMAS),
91-
(long)cnt_sch)) {
92-
ERRH(stmt, "filtering by schemas is not supported.");
93-
RET_HDIAG(stmt, SQL_STATE_IM001, "schema filtering not supported", 0);
237+
/* TODO: server support needed for sch. name filtering */
238+
if (wszmemcmp(schema, MK_WPTR(SQL_ALL_SCHEMAS), (long)cnt_sch)) {
239+
ERRH(stmt, "filtering by schemas is not supported.");
240+
RET_HDIAG(stmt, SQL_STATE_IM001, "schema filtering not supported",
241+
0);
242+
}
94243
}
95244

96245
// FIXME: string needs escaping of % \\ _
@@ -100,32 +249,57 @@ SQLRETURN EsSQLTablesW(
100249
cnt_tab = wcslen(table);
101250
if (ESODBC_MAX_IDENTIFIER_LEN < cnt_tab) {
102251
ERRH(stmt, "table identifier name '" LTPDL "' too long "
103-
"(%d. max=%d).", cnt_tab, table, cnt_tab,
252+
"(%zd. max=%d).", (int)cnt_tab, table, cnt_tab,
104253
ESODBC_MAX_IDENTIFIER_LEN);
105254
RET_HDIAG(stmt, SQL_STATE_HY090, "table name too long", 0);
106255
}
107256
} else {
108257
cnt_tab = NameLength3;
109258
}
110-
} else {
111-
table = MK_WPTR(ESODBC_ALL_TABLES);
112-
cnt_tab = sizeof(ESODBC_ALL_TABLES) - /*0-term*/1;
113-
}
114-
#if 1 // TODO: GH#4334
115-
if (cnt_tab == 0) {
116-
table = MK_WPTR(ESODBC_ALL_TABLES);
117-
cnt_tab = sizeof(ESODBC_ALL_TABLES) - /*0-term*/1;
259+
260+
cnt_tab = swprintf(wbuf + pos, wbuf_len - pos, SQL_TABLES_TAB,
261+
(int)cnt_tab, table);
262+
if (cnt_tab <= 0) {
263+
ERRH(stmt, "failed to print 'table' for tables catalog SQL.");
264+
RET_HDIAGS(stmt, SQL_STATE_HY000);
265+
} else {
266+
pos += cnt_tab;
267+
}
118268
}
119-
#endif // 1
120269

121-
/* print SQL to send to server */
122-
pos = swprintf(wbuf, sizeof(wbuf)/sizeof(wbuf[0]), SQL_TABLES,
123-
(int)cnt_cat, catalog, (int)cnt_tab, table);
124-
if (pos <= 0) {
125-
ERRH(stmt, "failed to print 'tables' catalog SQL.");
126-
RET_HDIAGS(stmt, SQL_STATE_HY000);
270+
if (TableType) {
271+
type = TableType;
272+
if (NameLength4 == SQL_NTS) {
273+
cnt_typ = wcslen(type);
274+
if (ESODBC_MAX_IDENTIFIER_LEN < cnt_typ) {
275+
ERRH(stmt, "type identifier name '" LTPDL "' too long "
276+
"(%zd. max=%d).", (int)cnt_typ, type, cnt_typ,
277+
ESODBC_MAX_IDENTIFIER_LEN);
278+
RET_HDIAG(stmt, SQL_STATE_HY090, "type name too long", 0);
279+
}
280+
} else {
281+
cnt_typ = NameLength4;
282+
}
283+
284+
/* In this argument, "each value can be enclosed in single quotation
285+
* marks (') or unquoted" => quote if not quoted (see GH#30398). */
286+
if (! wcsnstr(type, cnt_typ, L'\'')) {
287+
cnt_typ = quote_tokens(type, cnt_typ, typ_buf);
288+
type = typ_buf;
289+
}
290+
291+
cnt_typ = swprintf(wbuf + pos, wbuf_len - pos, SQL_TABLES_TYP,
292+
(int)cnt_typ, type);
293+
if (cnt_typ <= 0) {
294+
ERRH(stmt, "failed to print 'type' for tables catalog SQL.");
295+
RET_HDIAGS(stmt, SQL_STATE_HY000);
296+
} else {
297+
pos += cnt_typ;
298+
}
127299
}
128300

301+
DBGH(stmt, "tables catalog SQL [%d]:`" LWPDL "`.", pos, pos, wbuf);
302+
129303
ret = EsSQLFreeStmt(stmt, ESODBC_SQL_CLOSE);
130304
assert(SQL_SUCCEEDED(ret)); /* can't return error */
131305
ret = attach_sql(stmt, wbuf, pos);

driver/catalogue.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@
88
#define __CATALOGUE_H__
99

1010
#include "error.h"
11+
#include "handles.h"
12+
13+
14+
SQLSMALLINT copy_current_catalog(esodbc_dbc_st *dbc, SQLWCHAR *dest,
15+
SQLSMALLINT room);
16+
1117

1218
SQLRETURN EsSQLTablesW(
1319
SQLHSTMT StatementHandle,

driver/connect.c

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

1212
#include "connect.h"
1313
#include "queries.h"
14+
#include "catalogue.h"
1415
#include "log.h"
1516
#include "info.h"
1617
#include "util.h"
@@ -2084,26 +2085,6 @@ SQLRETURN EsSQLSetConnectAttrW(
20842085
return SQL_SUCCESS;
20852086
}
20862087

2087-
/* writes into 'dest', of size 'room', the current catalog of 'dbc'.
2088-
* returns negative on error, or the char count written otherwise */
2089-
static SQLSMALLINT get_current_catalog(esodbc_dbc_st *dbc, SQLWCHAR *dest,
2090-
SQLSMALLINT room)
2091-
{
2092-
SQLSMALLINT used;
2093-
SQLWCHAR *catalog = MK_WPTR("my_current_catalog"); // FIXME
2094-
2095-
//
2096-
// TODO: use the new SYS CATALOGS query
2097-
//
2098-
2099-
DBGH(dbc, "current catalog: `" LWPD "`.", catalog);
2100-
if (! SQL_SUCCEEDED(write_wptr(&dbc->hdr.diag, dest, catalog, room,
2101-
&used))) {
2102-
return -1;
2103-
}
2104-
return used;
2105-
}
2106-
21072088
SQLRETURN EsSQLGetConnectAttrW(
21082089
SQLHDBC ConnectionHandle,
21092090
SQLINTEGER Attribute,
@@ -2131,7 +2112,7 @@ SQLRETURN EsSQLGetConnectAttrW(
21312112
if (! dbc->es_types) {
21322113
ERRH(dbc, "no connection active.");
21332114
RET_HDIAGS(dbc, SQL_STATE_08003);
2134-
} else if ((used = get_current_catalog(dbc, (SQLWCHAR *)ValuePtr,
2115+
} else if ((used = copy_current_catalog(dbc, (SQLWCHAR *)ValuePtr,
21352116
(SQLSMALLINT)BufferLength)) < 0) {
21362117
ERRH(dbc, "failed to get current catalog.");
21372118
RET_STATE(dbc->hdr.diag.state);

driver/defs.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@
4848
#define ESODBC_MAX_CONCURRENT_ACTIVITIES 16
4949
/* maximum identifer length */
5050
/* TODO: review@alpha */
51-
#define ESODBC_MAX_IDENTIFIER_LEN 128
51+
/* match 'keyword' ES type lenght */
52+
#define ESODBC_MAX_IDENTIFIER_LEN 256
5253

5354

5455
/*

0 commit comments

Comments
 (0)