17
17
#include "info.h"
18
18
#include "queries.h"
19
19
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 \
23
32
" LIKE " ESODBC_STRING_DELIM WPFWP_LDESC ESODBC_STRING_DELIM
33
+ #define SQL_TABLES_TYP \
34
+ " TYPE " WPFWP_LDESC
24
35
25
36
// TODO add schema, when supported
26
37
#define SQL_COLUMNS (...) "SYS COLUMNS" __VA_ARGS__ \
27
38
" TABLE LIKE " ESODBC_STRING_DELIM WPFWP_LDESC ESODBC_STRING_DELIM \
28
39
" LIKE " ESODBC_STRING_DELIM WPFWP_LDESC ESODBC_STRING_DELIM
29
- #define SQL_COL_CAT \
40
+ #define SQL_COL_CAT \
30
41
" CATALOG " ESODBC_STRING_DELIM WPFWP_LDESC ESODBC_STRING_DELIM \
31
42
32
43
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
+
33
167
SQLRETURN EsSQLTablesW (
34
168
SQLHSTMT StatementHandle ,
35
169
_In_reads_opt_ (NameLength1 ) SQLWCHAR * CatalogName ,
@@ -43,29 +177,47 @@ SQLRETURN EsSQLTablesW(
43
177
{
44
178
esodbc_stmt_st * stmt = STMH (StatementHandle );
45
179
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 ];
49
192
50
193
if (stmt -> metadata_id == SQL_TRUE )
51
194
FIXME ; // FIXME
52
195
196
+ pos = sizeof (SQL_TABLES ) - 1 ;
197
+ wmemcpy (wbuf , MK_WPTR (SQL_TABLES ), pos );
198
+
53
199
if (CatalogName ) {
54
200
catalog = CatalogName ;
55
201
if (NameLength1 == SQL_NTS ) {
56
202
cnt_cat = wcslen (catalog );
57
203
if (ESODBC_MAX_IDENTIFIER_LEN < cnt_cat ) {
58
204
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 ,
60
206
ESODBC_MAX_IDENTIFIER_LEN );
61
207
RET_HDIAG (stmt , SQL_STATE_HY090 , "catalog name too long" , 0 );
62
208
}
63
209
} else {
64
210
cnt_cat = NameLength1 ;
65
211
}
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
+ }
69
221
}
70
222
71
223
if (SchemaName ) {
@@ -74,23 +226,20 @@ SQLRETURN EsSQLTablesW(
74
226
cnt_sch = wcslen (schema );
75
227
if (ESODBC_MAX_IDENTIFIER_LEN < cnt_sch ) {
76
228
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 ,
78
230
ESODBC_MAX_IDENTIFIER_LEN );
79
231
RET_HDIAG (stmt , SQL_STATE_HY090 , "schema name too long" , 0 );
80
232
}
81
233
} else {
82
234
cnt_sch = NameLength2 ;
83
235
}
84
- } else {
85
- schema = MK_WPTR (SQL_ALL_SCHEMAS );
86
- cnt_sch = sizeof (SQL_ALL_SCHEMAS ) - /*0-term*/ 1 ;
87
- }
88
236
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
+ }
94
243
}
95
244
96
245
// FIXME: string needs escaping of % \\ _
@@ -100,32 +249,57 @@ SQLRETURN EsSQLTablesW(
100
249
cnt_tab = wcslen (table );
101
250
if (ESODBC_MAX_IDENTIFIER_LEN < cnt_tab ) {
102
251
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 ,
104
253
ESODBC_MAX_IDENTIFIER_LEN );
105
254
RET_HDIAG (stmt , SQL_STATE_HY090 , "table name too long" , 0 );
106
255
}
107
256
} else {
108
257
cnt_tab = NameLength3 ;
109
258
}
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
+ }
118
268
}
119
- #endif // 1
120
269
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
+ }
127
299
}
128
300
301
+ DBGH (stmt , "tables catalog SQL [%d]:`" LWPDL "`." , pos , pos , wbuf );
302
+
129
303
ret = EsSQLFreeStmt (stmt , ESODBC_SQL_CLOSE );
130
304
assert (SQL_SUCCEEDED (ret )); /* can't return error */
131
305
ret = attach_sql (stmt , wbuf , pos );
0 commit comments