1 : /******************************************************************************
2 : *
3 : * Component: OGR SQL Engine
4 : * Purpose: swq_select class implementation.
5 : * Author: Frank Warmerdam <warmerdam@pobox.com>
6 : *
7 : ******************************************************************************
8 : * Copyright (C) 2010 Frank Warmerdam <warmerdam@pobox.com>
9 : *
10 : * Permission is hereby granted, free of charge, to any person obtaining a
11 : * copy of this software and associated documentation files (the "Software"),
12 : * to deal in the Software without restriction, including without limitation
13 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 : * and/or sell copies of the Software, and to permit persons to whom the
15 : * Software is furnished to do so, subject to the following conditions:
16 : *
17 : * The above copyright notice and this permission notice shall be included
18 : * in all copies or substantial portions of the Software.
19 : *
20 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 : * DEALINGS IN THE SOFTWARE.
27 : ****************************************************************************/
28 :
29 : #include "swq.h"
30 : #include "swq_parser.hpp"
31 :
32 : /************************************************************************/
33 : /* swq_select() */
34 : /************************************************************************/
35 :
36 303 : swq_select::swq_select()
37 :
38 : {
39 303 : query_mode = 0;
40 303 : raw_select = NULL;
41 :
42 303 : result_columns = 0;
43 303 : column_defs = NULL;
44 303 : column_summary = NULL;
45 :
46 303 : table_count = 0;
47 303 : table_defs = NULL;
48 :
49 303 : join_count = 0;
50 303 : join_defs = NULL;
51 :
52 303 : where_expr = NULL;
53 :
54 303 : order_specs = 0;
55 303 : order_defs = NULL;
56 303 : }
57 :
58 : /************************************************************************/
59 : /* ~swq_select() */
60 : /************************************************************************/
61 :
62 303 : swq_select::~swq_select()
63 :
64 : {
65 : int i;
66 :
67 303 : delete where_expr;
68 303 : CPLFree( raw_select );
69 :
70 565 : for( i = 0; i < table_count; i++ )
71 : {
72 262 : swq_table_def *table_def = table_defs + i;
73 :
74 262 : CPLFree( table_def->data_source );
75 262 : CPLFree( table_def->table_name );
76 262 : CPLFree( table_def->table_alias );
77 : }
78 303 : if( table_defs != NULL )
79 239 : CPLFree( table_defs );
80 :
81 1795 : for( i = 0; i < result_columns; i++ )
82 : {
83 1492 : CPLFree( column_defs[i].field_name );
84 1492 : CPLFree( column_defs[i].field_alias );
85 :
86 1492 : delete column_defs[i].expr;
87 :
88 1519 : if( column_summary != NULL
89 27 : && column_summary[i].distinct_list != NULL )
90 : {
91 : int j;
92 :
93 84 : for( j = 0; j < column_summary[i].count; j++ )
94 66 : CPLFree( column_summary[i].distinct_list[j] );
95 :
96 18 : CPLFree( column_summary[i].distinct_list );
97 : }
98 : }
99 :
100 303 : CPLFree( column_defs );
101 :
102 303 : CPLFree( column_summary );
103 :
104 326 : for( i = 0; i < order_specs; i++ )
105 : {
106 23 : CPLFree( order_defs[i].field_name );
107 : }
108 :
109 303 : CPLFree( order_defs );
110 :
111 324 : for( i = 0; i < join_count; i++ )
112 : {
113 21 : CPLFree( join_defs[i].primary_field_name );
114 21 : CPLFree( join_defs[i].secondary_field_name );
115 : }
116 303 : CPLFree( join_defs );
117 303 : }
118 :
119 :
120 : /************************************************************************/
121 : /* preparse() */
122 : /* */
123 : /* Parse the expression but without knowing the available */
124 : /* tables and fields. */
125 : /************************************************************************/
126 :
127 303 : CPLErr swq_select::preparse( const char *select_statement )
128 :
129 : {
130 : /* -------------------------------------------------------------------- */
131 : /* Allocate a big field list. It would be nice to make this */
132 : /* dynamic! */
133 : /* -------------------------------------------------------------------- */
134 : #define MAX_COLUMNS 250
135 :
136 303 : column_defs = (swq_col_def *) CPLMalloc(sizeof(swq_col_def) * MAX_COLUMNS);
137 303 : memset( column_defs, 0, sizeof(swq_col_def) * MAX_COLUMNS );
138 :
139 : /* -------------------------------------------------------------------- */
140 : /* Prepare a parser context. */
141 : /* -------------------------------------------------------------------- */
142 303 : swq_parse_context context;
143 :
144 303 : context.pszInput = select_statement;
145 303 : context.pszNext = select_statement;
146 303 : context.nStartToken = SWQT_SELECT_START;
147 303 : context.poSelect = this;
148 :
149 : /* -------------------------------------------------------------------- */
150 : /* Do the parse. */
151 : /* -------------------------------------------------------------------- */
152 303 : if( swqparse( &context ) != 0 )
153 : {
154 90 : delete context.poRoot;
155 90 : return CE_Failure;
156 : }
157 :
158 : /* -------------------------------------------------------------------- */
159 : /* resize the columns list properly. */
160 : /* -------------------------------------------------------------------- */
161 : column_defs = (swq_col_def *)
162 213 : CPLRealloc( column_defs, sizeof(swq_col_def) * result_columns );
163 :
164 213 : return CE_None;
165 : }
166 :
167 : /************************************************************************/
168 : /* Dump() */
169 : /************************************************************************/
170 :
171 0 : void swq_select::Dump( FILE *fp )
172 :
173 : {
174 : int i;
175 :
176 0 : fprintf( fp, "SELECT Statement:\n" );
177 :
178 : /* -------------------------------------------------------------------- */
179 : /* query mode. */
180 : /* -------------------------------------------------------------------- */
181 0 : if( query_mode == SWQM_SUMMARY_RECORD )
182 0 : fprintf( fp, " QUERY MODE: SUMMARY RECORD\n" );
183 0 : else if( query_mode == SWQM_RECORDSET )
184 0 : fprintf( fp, " QUERY MODE: RECORDSET\n" );
185 0 : else if( query_mode == SWQM_DISTINCT_LIST )
186 0 : fprintf( fp, " QUERY MODE: DISTINCT LIST\n" );
187 : else
188 0 : fprintf( fp, " QUERY MODE: %d/unknown\n", query_mode );
189 :
190 : /* -------------------------------------------------------------------- */
191 : /* column_defs */
192 : /* -------------------------------------------------------------------- */
193 0 : fprintf( fp, " Result Columns:\n" );
194 0 : for( i = 0; i < result_columns; i++ )
195 : {
196 0 : swq_col_def *def = column_defs + i;
197 :
198 :
199 0 : fprintf( fp, " Name: %s\n", def->field_name );
200 :
201 0 : if( def->field_alias )
202 0 : fprintf( fp, " Alias: %s\n", def->field_alias );
203 :
204 0 : if( def->col_func == SWQCF_NONE )
205 : /* nothing */;
206 0 : else if( def->col_func == SWQCF_AVG )
207 0 : fprintf( fp, " Function: AVG\n" );
208 0 : else if( def->col_func == SWQCF_MIN )
209 0 : fprintf( fp, " Function: MIN\n" );
210 0 : else if( def->col_func == SWQCF_MAX )
211 0 : fprintf( fp, " Function: MAX\n" );
212 0 : else if( def->col_func == SWQCF_COUNT )
213 0 : fprintf( fp, " Function: COUNT\n" );
214 0 : else if( def->col_func == SWQCF_SUM )
215 0 : fprintf( fp, " Function: SUM\n" );
216 0 : else if( def->col_func == SWQCF_CUSTOM )
217 0 : fprintf( fp, " Function: CUSTOM\n" );
218 : else
219 0 : fprintf( fp, " Function: UNKNOWN!\n" );
220 :
221 0 : if( def->distinct_flag )
222 0 : fprintf( fp, " DISTINCT flag set\n" );
223 :
224 : fprintf( fp, " Field Index: %d, Table Index: %d\n",
225 0 : def->field_index, def->table_index );
226 :
227 0 : fprintf( fp, " Field Type: %d\n", def->field_type );
228 0 : fprintf( fp, " Target Type: %d\n", def->target_type );
229 : fprintf( fp, " Length: %d, Precision: %d\n",
230 0 : def->field_length, def->field_precision );
231 :
232 0 : if( def->expr != NULL )
233 : {
234 0 : fprintf( fp, " Expression:\n" );
235 0 : def->expr->Dump( fp, 3 );
236 : }
237 : }
238 :
239 : /* -------------------------------------------------------------------- */
240 : /* table_defs */
241 : /* -------------------------------------------------------------------- */
242 0 : fprintf( fp, " Table Defs: %d\n", table_count );
243 0 : for( i = 0; i < table_count; i++ )
244 : {
245 : fprintf( fp, " datasource=%s, table_name=%s, table_alias=%s\n",
246 0 : table_defs[i].data_source,
247 0 : table_defs[i].table_name,
248 0 : table_defs[i].table_alias );
249 : }
250 :
251 : /* -------------------------------------------------------------------- */
252 : /* join_defs */
253 : /* -------------------------------------------------------------------- */
254 0 : if( join_count > 0 )
255 0 : fprintf( fp, " joins:\n" );
256 :
257 0 : for( i = 0; i < join_count; i++ )
258 : {
259 0 : fprintf( fp, " %d:\n", i );
260 : fprintf( fp, " Primary Field: %s/%d\n",
261 0 : join_defs[i].primary_field_name,
262 0 : join_defs[i].primary_field );
263 :
264 : fprintf( fp, " Operation: %d\n",
265 0 : join_defs[i].op );
266 :
267 : fprintf( fp, " Secondary Field: %s/%d\n",
268 0 : join_defs[i].secondary_field_name,
269 0 : join_defs[i].secondary_field );
270 : fprintf( fp, " Secondary Table: %d\n",
271 0 : join_defs[i].secondary_table );
272 : }
273 :
274 : /* -------------------------------------------------------------------- */
275 : /* Where clause. */
276 : /* -------------------------------------------------------------------- */
277 0 : if( where_expr != NULL )
278 : {
279 0 : fprintf( fp, " WHERE:\n" );
280 0 : where_expr->Dump( fp, 2 );
281 : }
282 :
283 : /* -------------------------------------------------------------------- */
284 : /* Order by */
285 : /* -------------------------------------------------------------------- */
286 :
287 0 : for( i = 0; i < order_specs; i++ )
288 : {
289 : fprintf( fp, " ORDER BY: %s (%d/%d)",
290 0 : order_defs[i].field_name,
291 0 : order_defs[i].table_index,
292 0 : order_defs[i].field_index );
293 0 : if( order_defs[i].ascending_flag )
294 0 : fprintf( fp, " ASC\n" );
295 : else
296 0 : fprintf( fp, " DESC\n" );
297 : }
298 0 : }
299 :
300 : /************************************************************************/
301 : /* PushField() */
302 : /* */
303 : /* Create a new field definition by name and possibly alias. */
304 : /************************************************************************/
305 :
306 1336 : int swq_select::PushField( swq_expr_node *poExpr, const char *pszAlias,
307 : int distinct_flag )
308 :
309 : {
310 : /* -------------------------------------------------------------------- */
311 : /* Grow the array. */
312 : /* -------------------------------------------------------------------- */
313 1336 : result_columns++;
314 :
315 : column_defs = (swq_col_def *)
316 1336 : CPLRealloc( column_defs, sizeof(swq_col_def) * result_columns );
317 :
318 1336 : swq_col_def *col_def = column_defs + result_columns - 1;
319 :
320 1336 : memset( col_def, 0, sizeof(swq_col_def) );
321 :
322 : /* -------------------------------------------------------------------- */
323 : /* Try to capture a field name. */
324 : /* -------------------------------------------------------------------- */
325 1336 : if( poExpr->eNodeType == SNT_COLUMN )
326 : col_def->field_name =
327 1190 : CPLStrdup(poExpr->string_value);
328 403 : else if( poExpr->eNodeType == SNT_OPERATION
329 : && poExpr->nSubExprCount >= 1
330 134 : && poExpr->papoSubExpr[0]->eNodeType == SNT_COLUMN )
331 : col_def->field_name =
332 123 : CPLStrdup(poExpr->papoSubExpr[0]->string_value);
333 : else
334 23 : col_def->field_name = CPLStrdup("");
335 :
336 : /* -------------------------------------------------------------------- */
337 : /* Initialize fields. */
338 : /* -------------------------------------------------------------------- */
339 1336 : if( pszAlias != NULL )
340 9 : col_def->field_alias = CPLStrdup( pszAlias );
341 :
342 1336 : col_def->table_index = -1;
343 1336 : col_def->field_index = -1;
344 1336 : col_def->field_type = SWQ_OTHER;
345 1336 : col_def->field_precision = -1;
346 1336 : col_def->target_type = SWQ_OTHER;
347 1336 : col_def->col_func = SWQCF_NONE;
348 1336 : col_def->distinct_flag = distinct_flag;
349 :
350 : /* -------------------------------------------------------------------- */
351 : /* Do we have a CAST operator in play? */
352 : /* -------------------------------------------------------------------- */
353 1336 : if( poExpr->eNodeType == SNT_OPERATION
354 : && poExpr->nOperation == SWQ_CAST )
355 : {
356 12 : const char *pszTypeName = poExpr->papoSubExpr[1]->string_value;
357 12 : int parse_precision = 0;
358 :
359 12 : if( EQUAL(pszTypeName,"character") )
360 : {
361 7 : col_def->target_type = SWQ_STRING;
362 7 : col_def->field_length = 1;
363 : }
364 5 : else if( strcasecmp(pszTypeName,"integer") == 0 )
365 : {
366 1 : col_def->target_type = SWQ_INTEGER;
367 : }
368 4 : else if( strcasecmp(pszTypeName,"float") == 0 )
369 : {
370 0 : col_def->target_type = SWQ_FLOAT;
371 : }
372 4 : else if( strcasecmp(pszTypeName,"numeric") == 0 )
373 : {
374 1 : col_def->target_type = SWQ_FLOAT;
375 1 : parse_precision = 1;
376 : }
377 3 : else if( strcasecmp(pszTypeName,"timestamp") == 0 )
378 : {
379 0 : col_def->target_type = SWQ_TIMESTAMP;
380 : }
381 3 : else if( strcasecmp(pszTypeName,"date") == 0 )
382 : {
383 0 : col_def->target_type = SWQ_DATE;
384 : }
385 3 : else if( strcasecmp(pszTypeName,"time") == 0 )
386 : {
387 0 : col_def->target_type = SWQ_TIME;
388 : }
389 : else
390 : {
391 : CPLError( CE_Failure, CPLE_AppDefined,
392 : "Unrecognized typename %s in CAST operator.",
393 3 : pszTypeName );
394 3 : CPLFree(col_def->field_name);
395 3 : col_def->field_name = NULL;
396 3 : CPLFree(col_def->field_alias);
397 3 : col_def->field_alias = NULL;
398 3 : result_columns--;
399 3 : return FALSE;
400 : }
401 :
402 : // field width.
403 9 : if( poExpr->nSubExprCount > 2 )
404 : {
405 5 : col_def->field_length = poExpr->papoSubExpr[2]->int_value;
406 : }
407 :
408 : // field width.
409 9 : if( poExpr->nSubExprCount > 3 && parse_precision )
410 : {
411 1 : col_def->field_precision = poExpr->papoSubExpr[3]->int_value;
412 : }
413 : }
414 :
415 : /* -------------------------------------------------------------------- */
416 : /* Do we have a special column function in play? */
417 : /* -------------------------------------------------------------------- */
418 1333 : if( poExpr->eNodeType == SNT_OPERATION
419 : && poExpr->nOperation >= SWQ_AVG
420 : && poExpr->nOperation <= SWQ_SUM )
421 : {
422 108 : if( poExpr->nSubExprCount != 1 )
423 : {
424 : CPLError( CE_Failure, CPLE_AppDefined,
425 : "Column Summary Function '%s' has wrong number of arguments.",
426 2 : poExpr->string_value ? poExpr->string_value : "(null)");
427 2 : CPLFree(col_def->field_name);
428 2 : col_def->field_name = NULL;
429 2 : CPLFree(col_def->field_alias);
430 2 : col_def->field_alias = NULL;
431 2 : result_columns--;
432 2 : return FALSE;
433 : }
434 : else
435 : {
436 : col_def->col_func =
437 106 : (swq_col_func) poExpr->nOperation;
438 :
439 106 : swq_expr_node *poSubExpr = poExpr->papoSubExpr[0];
440 :
441 106 : poExpr->papoSubExpr[0] = NULL;
442 106 : poExpr->nSubExprCount = 0;
443 106 : delete poExpr;
444 :
445 106 : poExpr = poSubExpr;
446 : }
447 : }
448 :
449 1331 : col_def->expr = poExpr;
450 :
451 1331 : return TRUE;
452 : }
453 :
454 : /************************************************************************/
455 : /* PushTableDef() */
456 : /************************************************************************/
457 :
458 262 : int swq_select::PushTableDef( const char *pszDataSource,
459 : const char *pszName,
460 : const char *pszAlias )
461 :
462 : {
463 262 : table_count++;
464 :
465 : table_defs = (swq_table_def *)
466 262 : CPLRealloc( table_defs, sizeof(swq_table_def) * table_count );
467 :
468 262 : if( pszDataSource != NULL )
469 5 : table_defs[table_count-1].data_source = CPLStrdup(pszDataSource);
470 : else
471 257 : table_defs[table_count-1].data_source = NULL;
472 :
473 262 : table_defs[table_count-1].table_name = CPLStrdup(pszName);
474 :
475 262 : if( pszAlias != NULL )
476 16 : table_defs[table_count-1].table_alias = CPLStrdup(pszAlias);
477 : else
478 246 : table_defs[table_count-1].table_alias = CPLStrdup(pszName);
479 :
480 262 : return table_count-1;
481 : }
482 :
483 : /************************************************************************/
484 : /* PushOrderBy() */
485 : /************************************************************************/
486 :
487 23 : void swq_select::PushOrderBy( const char *pszFieldName, int bAscending )
488 :
489 : {
490 23 : order_specs++;
491 : order_defs = (swq_order_def *)
492 23 : CPLRealloc( order_defs, sizeof(swq_order_def) * order_specs );
493 :
494 23 : order_defs[order_specs-1].field_name = CPLStrdup(pszFieldName);
495 23 : order_defs[order_specs-1].table_index = -1;
496 23 : order_defs[order_specs-1].field_index = -1;
497 23 : order_defs[order_specs-1].ascending_flag = bAscending;
498 23 : }
499 :
500 : /************************************************************************/
501 : /* PushJoin() */
502 : /************************************************************************/
503 :
504 21 : void swq_select::PushJoin( int iSecondaryTable,
505 : const char *pszPrimaryField,
506 : const char *pszSecondaryField )
507 :
508 : {
509 21 : join_count++;
510 : join_defs = (swq_join_def *)
511 21 : CPLRealloc( join_defs, sizeof(swq_join_def) * join_count );
512 :
513 21 : join_defs[join_count-1].secondary_table = iSecondaryTable;
514 21 : join_defs[join_count-1].primary_field_name = CPLStrdup(pszPrimaryField);
515 21 : join_defs[join_count-1].primary_field = -1;
516 21 : join_defs[join_count-1].op = SWQ_EQ;
517 21 : join_defs[join_count-1].secondary_field_name = CPLStrdup(pszSecondaryField);
518 21 : join_defs[join_count-1].secondary_field = -1;
519 21 : }
520 :
521 :
522 : /************************************************************************/
523 : /* expand_wildcard() */
524 : /* */
525 : /* This function replaces the '*' in a "SELECT *" with the list */
526 : /* provided list of fields. Itis used by swq_select_parse(), */
527 : /* but may be called in advance by applications wanting the */
528 : /* "default" field list to be different than the full list of */
529 : /* fields. */
530 : /************************************************************************/
531 :
532 415 : CPLErr swq_select::expand_wildcard( swq_field_list *field_list )
533 :
534 : {
535 : int isrc;
536 :
537 : /* ==================================================================== */
538 : /* Check each pre-expansion field. */
539 : /* ==================================================================== */
540 3366 : for( isrc = 0; isrc < result_columns; isrc++ )
541 : {
542 2951 : const char *src_fieldname = column_defs[isrc].field_name;
543 : int itable, new_fields, i, iout;
544 :
545 5864 : if( *src_fieldname == '\0'
546 2913 : || src_fieldname[strlen(src_fieldname)-1] != '*' )
547 2728 : continue;
548 :
549 : /* We don't want to expand COUNT(*) */
550 223 : if( column_defs[isrc].col_func == SWQCF_COUNT )
551 151 : continue;
552 :
553 : /* -------------------------------------------------------------------- */
554 : /* Parse out the table name, verify it, and establish the */
555 : /* number of fields to insert from it. */
556 : /* -------------------------------------------------------------------- */
557 72 : if( strcmp(src_fieldname,"*") == 0 )
558 : {
559 62 : itable = -1;
560 62 : new_fields = field_list->count;
561 : }
562 20 : else if( strlen(src_fieldname) < 3
563 10 : || src_fieldname[strlen(src_fieldname)-2] != '.' )
564 : {
565 : CPLError( CE_Failure, CPLE_AppDefined,
566 : "Ill formatted field definition '%s'.",
567 0 : src_fieldname );
568 0 : return CE_Failure;
569 : }
570 : else
571 : {
572 10 : char *table_name = CPLStrdup( src_fieldname );
573 10 : table_name[strlen(src_fieldname)-2] = '\0';
574 :
575 12 : for( itable = 0; itable < field_list->table_count; itable++ )
576 : {
577 12 : if( strcasecmp(table_name,
578 12 : field_list->table_defs[itable].table_alias ) == 0 )
579 10 : break;
580 : }
581 :
582 10 : if( itable == field_list->table_count )
583 : {
584 : CPLError( CE_Failure, CPLE_AppDefined,
585 : "Table %s not recognised from %s definition.",
586 0 : table_name, src_fieldname );
587 0 : CPLFree( table_name );
588 0 : return CE_Failure;
589 : }
590 10 : CPLFree( table_name );
591 :
592 : /* count the number of fields in this table. */
593 10 : new_fields = 0;
594 66 : for( i = 0; i < field_list->count; i++ )
595 : {
596 56 : if( field_list->table_ids[i] == itable )
597 30 : new_fields++;
598 : }
599 : }
600 :
601 72 : if (new_fields > 0)
602 : {
603 : /* -------------------------------------------------------------------- */
604 : /* Reallocate the column list larger. */
605 : /* -------------------------------------------------------------------- */
606 70 : CPLFree( column_defs[isrc].field_name );
607 70 : delete column_defs[isrc].expr;
608 :
609 : column_defs = (swq_col_def *)
610 : CPLRealloc( column_defs,
611 : sizeof(swq_col_def) *
612 70 : (result_columns + new_fields - 1 ) );
613 :
614 : /* -------------------------------------------------------------------- */
615 : /* Push the old definitions that came after the one to be */
616 : /* replaced further up in the array. */
617 : /* -------------------------------------------------------------------- */
618 70 : if (new_fields != 1)
619 : {
620 76 : for( i = result_columns-1; i > isrc; i-- )
621 : {
622 : memcpy( column_defs + i + new_fields - 1,
623 : column_defs + i,
624 11 : sizeof( swq_col_def ) );
625 : }
626 : }
627 :
628 70 : result_columns += (new_fields - 1 );
629 :
630 : /* -------------------------------------------------------------------- */
631 : /* Zero out all the stuff in the target column definitions. */
632 : /* -------------------------------------------------------------------- */
633 : memset( column_defs + isrc, 0,
634 70 : new_fields * sizeof(swq_col_def) );
635 : }
636 : else
637 : {
638 : /* -------------------------------------------------------------------- */
639 : /* The wildcard expands to nothing */
640 : /* -------------------------------------------------------------------- */
641 2 : CPLFree( column_defs[isrc].field_name );
642 2 : delete column_defs[isrc].expr;
643 :
644 : memmove( column_defs + isrc,
645 : column_defs + isrc + 1,
646 2 : sizeof( swq_col_def ) * (result_columns-1-isrc) );
647 :
648 2 : result_columns --;
649 : }
650 :
651 : /* -------------------------------------------------------------------- */
652 : /* Assign the selected fields. */
653 : /* -------------------------------------------------------------------- */
654 72 : iout = isrc;
655 :
656 331 : for( i = 0; i < field_list->count; i++ )
657 : {
658 : swq_col_def *def;
659 259 : int compose = itable != -1;
660 :
661 : /* skip this field if it isn't in the target table. */
662 315 : if( itable != -1 && field_list->table_ids != NULL
663 56 : && itable != field_list->table_ids[i] )
664 26 : continue;
665 :
666 : /* set up some default values. */
667 233 : def = column_defs + iout;
668 233 : def->field_precision = -1;
669 233 : def->target_type = SWQ_OTHER;
670 :
671 : /* does this field duplicate an earlier one? */
672 466 : if( field_list->table_ids != NULL
673 233 : && field_list->table_ids[i] != 0
674 : && !compose )
675 : {
676 : int other;
677 :
678 159 : for( other = 0; other < i; other++ )
679 : {
680 270 : if( strcasecmp(field_list->names[i],
681 135 : field_list->names[other]) == 0 )
682 : {
683 9 : compose = 1;
684 9 : break;
685 : }
686 : }
687 : }
688 :
689 233 : if( !compose )
690 194 : def->field_name = CPLStrdup( field_list->names[i] );
691 : else
692 : {
693 39 : int itable = field_list->table_ids[i];
694 : char *composed_name;
695 39 : const char *field_name = field_list->names[i];
696 : const char *table_alias =
697 39 : field_list->table_defs[itable].table_alias;
698 :
699 : composed_name = (char *)
700 39 : CPLMalloc(strlen(field_name)+strlen(table_alias)+2);
701 :
702 39 : sprintf( composed_name, "%s.%s", table_alias, field_name );
703 :
704 39 : def->field_name = composed_name;
705 : }
706 :
707 233 : iout++;
708 :
709 : /* All the other table info will be provided by the later
710 : parse operation. */
711 : }
712 :
713 : /* If there are several occurrences of '*', go on, but stay on the */
714 : /* same index in case '*' is expanded to nothing */
715 : /* (the -- is to compensate the fact that isrc will be incremented in */
716 : /* the after statement of the for loop) */
717 72 : isrc --;
718 : }
719 :
720 415 : return CE_None;
721 : }
722 :
723 : /************************************************************************/
724 : /* parse() */
725 : /* */
726 : /* This method really does post-parse processing. */
727 : /************************************************************************/
728 :
729 208 : CPLErr swq_select::parse( swq_field_list *field_list,
730 : int parse_flags )
731 :
732 : {
733 : int i;
734 : CPLErr eError;
735 :
736 208 : eError = expand_wildcard( field_list );
737 208 : if( eError != CE_None )
738 0 : return eError;
739 :
740 :
741 : /* -------------------------------------------------------------------- */
742 : /* Identify field information. */
743 : /* -------------------------------------------------------------------- */
744 1637 : for( i = 0; i < result_columns; i++ )
745 : {
746 1442 : swq_col_def *def = column_defs + i;
747 :
748 1465 : if( def->expr != NULL && def->expr->eNodeType != SNT_COLUMN )
749 : {
750 25 : def->field_index = -1;
751 25 : def->table_index = -1;
752 :
753 25 : if( def->expr->Check( field_list ) == SWQ_ERROR )
754 2 : return CE_Failure;
755 :
756 23 : def->field_type = def->expr->field_type;
757 :
758 : // If the field was changed from string constant to
759 : // column field then adopt the name.
760 23 : if( def->expr->eNodeType == SNT_COLUMN )
761 : {
762 2 : def->field_index = def->expr->field_index;
763 2 : def->table_index = def->expr->table_index;
764 :
765 2 : CPLFree( def->field_name );
766 2 : def->field_name = CPLStrdup(def->expr->string_value);
767 : }
768 : }
769 : else
770 : {
771 : swq_field_type this_type;
772 :
773 : /* identify field */
774 : def->field_index = swq_identify_field( def->field_name, field_list,
775 : &this_type,
776 1417 : &(def->table_index) );
777 :
778 : /* record field type */
779 1417 : def->field_type = this_type;
780 :
781 1417 : if( def->field_index == -1 && def->col_func != SWQCF_COUNT )
782 : {
783 : CPLError( CE_Failure, CPLE_AppDefined,
784 : "Unrecognised field name %s.",
785 7 : def->field_name );
786 7 : return CE_Failure;
787 : }
788 : }
789 :
790 : /* identify column function if present */
791 1433 : if( (def->col_func == SWQCF_MIN
792 : || def->col_func == SWQCF_MAX
793 : || def->col_func == SWQCF_AVG
794 : || def->col_func == SWQCF_SUM)
795 : && def->field_type == SWQ_STRING )
796 : {
797 : // possibly this is already enforced by the checker?
798 : const swq_operation *op = swq_op_registrar::GetOperator(
799 4 : (swq_op) def->col_func );
800 :
801 : CPLError( CE_Failure, CPLE_AppDefined,
802 : "Use of field function %s() on string field %s illegal.",
803 4 : op->osName.c_str(), def->field_name );
804 4 : return CE_Failure;
805 : }
806 : }
807 :
808 : /* -------------------------------------------------------------------- */
809 : /* Check if we are producing a one row summary result or a set */
810 : /* of records. Generate an error if we get conflicting */
811 : /* indications. */
812 : /* -------------------------------------------------------------------- */
813 195 : query_mode = -1;
814 1618 : for( i = 0; i < result_columns; i++ )
815 : {
816 1424 : swq_col_def *def = column_defs + i;
817 1424 : int this_indicator = -1;
818 :
819 1519 : if( def->col_func == SWQCF_MIN
820 : || def->col_func == SWQCF_MAX
821 : || def->col_func == SWQCF_AVG
822 : || def->col_func == SWQCF_SUM
823 : || def->col_func == SWQCF_COUNT )
824 95 : this_indicator = SWQM_SUMMARY_RECORD;
825 1329 : else if( def->col_func == SWQCF_NONE )
826 : {
827 1329 : if( def->distinct_flag )
828 15 : this_indicator = SWQM_DISTINCT_LIST;
829 : else
830 1314 : this_indicator = SWQM_RECORDSET;
831 : }
832 :
833 1424 : if( this_indicator != query_mode
834 : && this_indicator != -1
835 : && query_mode != -1 )
836 : {
837 : CPLError( CE_Failure, CPLE_AppDefined,
838 1 : "Field list implies mixture of regular recordset mode, summary mode or distinct field list mode." );
839 1 : return CE_Failure;
840 : }
841 :
842 1423 : if( this_indicator != -1 )
843 1423 : query_mode = this_indicator;
844 : }
845 :
846 194 : if( result_columns > 1
847 : && query_mode == SWQM_DISTINCT_LIST )
848 : {
849 : CPLError( CE_Failure, CPLE_AppDefined,
850 0 : "SELECTing more than one DISTINCT field is a query not supported." );
851 0 : return CE_Failure;
852 : }
853 194 : else if (result_columns == 0)
854 : {
855 1 : query_mode = SWQM_RECORDSET;
856 : }
857 :
858 : /* -------------------------------------------------------------------- */
859 : /* Process column names in JOIN specs. */
860 : /* -------------------------------------------------------------------- */
861 211 : for( i = 0; i < join_count; i++ )
862 : {
863 19 : swq_join_def *def = join_defs + i;
864 : int table_id;
865 :
866 : /* identify primary field */
867 : def->primary_field = swq_identify_field( def->primary_field_name,
868 19 : field_list, NULL, &table_id );
869 19 : if( def->primary_field == -1 )
870 : {
871 : CPLError( CE_Failure, CPLE_AppDefined,
872 : "Unrecognised primary field %s in JOIN clause..",
873 0 : def->primary_field_name );
874 0 : return CE_Failure;
875 : }
876 :
877 19 : if( table_id != 0 )
878 : {
879 : CPLError( CE_Failure, CPLE_AppDefined,
880 : "Currently the primary key must come from the primary table in\n"
881 : "JOIN, %s is not from the primary table.",
882 0 : def->primary_field_name );
883 0 : return CE_Failure;
884 : }
885 :
886 : /* identify secondary field */
887 : def->secondary_field = swq_identify_field( def->secondary_field_name,
888 19 : field_list, NULL,&table_id);
889 19 : if( def->secondary_field == -1 )
890 : {
891 : CPLError( CE_Failure, CPLE_AppDefined,
892 : "Unrecognised secondary field %s in JOIN clause..",
893 2 : def->primary_field_name );
894 2 : return CE_Failure;
895 : }
896 :
897 17 : if( table_id != def->secondary_table )
898 : {
899 : CPLError( CE_Failure, CPLE_AppDefined,
900 : "Currently the secondary key must come from the secondary table\n"
901 : "listed in the JOIN. %s is not from table %s..",
902 : def->primary_field_name,
903 0 : table_defs[def->secondary_table].table_name);
904 0 : return CE_Failure;
905 : }
906 : }
907 :
908 : /* -------------------------------------------------------------------- */
909 : /* Process column names in order specs. */
910 : /* -------------------------------------------------------------------- */
911 213 : for( i = 0; i < order_specs; i++ )
912 : {
913 22 : swq_order_def *def = order_defs + i;
914 :
915 : /* identify field */
916 : def->field_index = swq_identify_field( def->field_name, field_list,
917 22 : NULL, &(def->table_index) );
918 22 : if( def->field_index == -1 )
919 : {
920 : CPLError( CE_Failure, CPLE_AppDefined,
921 : "Unrecognised field name %s in ORDER BY.",
922 1 : def->field_name );
923 1 : return CE_Failure;
924 : }
925 : }
926 :
927 : /* -------------------------------------------------------------------- */
928 : /* Post process the where clause, subbing in field indexes and */
929 : /* doing final validation. */
930 : /* -------------------------------------------------------------------- */
931 191 : if( where_expr != NULL
932 : && where_expr->Check( field_list ) == SWQ_ERROR )
933 : {
934 7 : return CE_Failure;
935 : }
936 :
937 184 : return CE_None;
938 : }
939 :
|