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