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 902 : swq_select::swq_select()
37 :
38 : {
39 902 : query_mode = 0;
40 902 : raw_select = NULL;
41 :
42 902 : result_columns = 0;
43 902 : column_defs = NULL;
44 902 : column_summary = NULL;
45 :
46 902 : table_count = 0;
47 902 : table_defs = NULL;
48 :
49 902 : join_count = 0;
50 902 : join_defs = NULL;
51 :
52 902 : where_expr = NULL;
53 :
54 902 : order_specs = 0;
55 902 : order_defs = NULL;
56 902 : }
57 :
58 : /************************************************************************/
59 : /* ~swq_select() */
60 : /************************************************************************/
61 :
62 902 : swq_select::~swq_select()
63 :
64 : {
65 : int i;
66 :
67 902 : delete where_expr;
68 902 : CPLFree( raw_select );
69 :
70 1718 : for( i = 0; i < table_count; i++ )
71 : {
72 816 : swq_table_def *table_def = table_defs + i;
73 :
74 816 : CPLFree( table_def->data_source );
75 816 : CPLFree( table_def->table_name );
76 816 : CPLFree( table_def->table_alias );
77 : }
78 902 : if( table_defs != NULL )
79 766 : CPLFree( table_defs );
80 :
81 4608 : for( i = 0; i < result_columns; i++ )
82 : {
83 3706 : CPLFree( column_defs[i].field_name );
84 3706 : CPLFree( column_defs[i].field_alias );
85 :
86 3706 : delete column_defs[i].expr;
87 :
88 3764 : if( column_summary != NULL
89 58 : && column_summary[i].distinct_list != NULL )
90 : {
91 : int j;
92 :
93 174 : for( j = 0; j < column_summary[i].count; j++ )
94 136 : CPLFree( column_summary[i].distinct_list[j] );
95 :
96 38 : CPLFree( column_summary[i].distinct_list );
97 : }
98 : }
99 :
100 902 : CPLFree( column_defs );
101 :
102 902 : CPLFree( column_summary );
103 :
104 952 : for( i = 0; i < order_specs; i++ )
105 : {
106 50 : CPLFree( order_defs[i].field_name );
107 : }
108 :
109 902 : CPLFree( order_defs );
110 :
111 948 : for( i = 0; i < join_count; i++ )
112 : {
113 46 : CPLFree( join_defs[i].primary_field_name );
114 46 : CPLFree( join_defs[i].secondary_field_name );
115 : }
116 902 : CPLFree( join_defs );
117 902 : }
118 :
119 :
120 : /************************************************************************/
121 : /* preparse() */
122 : /* */
123 : /* Parse the expression but without knowing the available */
124 : /* tables and fields. */
125 : /************************************************************************/
126 :
127 902 : 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 902 : column_defs = (swq_col_def *) CPLMalloc(sizeof(swq_col_def) * MAX_COLUMNS);
137 902 : memset( column_defs, 0, sizeof(swq_col_def) * MAX_COLUMNS );
138 :
139 : /* -------------------------------------------------------------------- */
140 : /* Prepare a parser context. */
141 : /* -------------------------------------------------------------------- */
142 902 : swq_parse_context context;
143 :
144 902 : context.pszInput = select_statement;
145 902 : context.pszNext = select_statement;
146 902 : context.nStartToken = SWQT_SELECT_START;
147 902 : context.poSelect = this;
148 :
149 : /* -------------------------------------------------------------------- */
150 : /* Do the parse. */
151 : /* -------------------------------------------------------------------- */
152 902 : if( swqparse( &context ) != 0 )
153 : {
154 188 : delete context.poRoot;
155 188 : return CE_Failure;
156 : }
157 :
158 : /* -------------------------------------------------------------------- */
159 : /* resize the columns list properly. */
160 : /* -------------------------------------------------------------------- */
161 : column_defs = (swq_col_def *)
162 714 : CPLRealloc( column_defs, sizeof(swq_col_def) * result_columns );
163 :
164 : /* -------------------------------------------------------------------- */
165 : /* Reorder the joins in the order they appear in the SQL string. */
166 : /* -------------------------------------------------------------------- */
167 : int i;
168 718 : for(i = 0; i < join_count / 2; i++)
169 : {
170 : swq_join_def sTmp;
171 4 : memcpy(&sTmp, &join_defs[i], sizeof(swq_join_def));
172 4 : memcpy(&join_defs[i], &join_defs[join_count - 1 - i], sizeof(swq_join_def));
173 4 : memcpy(&join_defs[join_count - 1 - i], &sTmp, sizeof(swq_join_def));
174 : }
175 :
176 : /* We make that strong assumption in ogr_gensql */
177 760 : for(i = 0; i < join_count; i++)
178 : {
179 46 : CPLAssert(join_defs[i].secondary_table == i + 1);
180 : }
181 :
182 714 : return CE_None;
183 : }
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 2962 : int swq_select::PushField( swq_expr_node *poExpr, const char *pszAlias,
325 : int distinct_flag )
326 :
327 : {
328 : /* -------------------------------------------------------------------- */
329 : /* Grow the array. */
330 : /* -------------------------------------------------------------------- */
331 2962 : result_columns++;
332 :
333 : column_defs = (swq_col_def *)
334 2962 : CPLRealloc( column_defs, sizeof(swq_col_def) * result_columns );
335 :
336 2962 : swq_col_def *col_def = column_defs + result_columns - 1;
337 :
338 2962 : memset( col_def, 0, sizeof(swq_col_def) );
339 :
340 : /* -------------------------------------------------------------------- */
341 : /* Try to capture a field name. */
342 : /* -------------------------------------------------------------------- */
343 2962 : if( poExpr->eNodeType == SNT_COLUMN )
344 : col_def->field_name =
345 2588 : CPLStrdup(poExpr->string_value);
346 1012 : else if( poExpr->eNodeType == SNT_OPERATION
347 : && poExpr->nSubExprCount >= 1
348 350 : && poExpr->papoSubExpr[0]->eNodeType == SNT_COLUMN )
349 : col_def->field_name =
350 288 : CPLStrdup(poExpr->papoSubExpr[0]->string_value);
351 : else
352 86 : col_def->field_name = CPLStrdup("");
353 :
354 : /* -------------------------------------------------------------------- */
355 : /* Initialize fields. */
356 : /* -------------------------------------------------------------------- */
357 2962 : if( pszAlias != NULL )
358 18 : col_def->field_alias = CPLStrdup( pszAlias );
359 :
360 2962 : col_def->table_index = -1;
361 2962 : col_def->field_index = -1;
362 2962 : col_def->field_type = SWQ_OTHER;
363 2962 : col_def->field_precision = -1;
364 2962 : col_def->target_type = SWQ_OTHER;
365 2962 : col_def->col_func = SWQCF_NONE;
366 2962 : col_def->distinct_flag = distinct_flag;
367 :
368 : /* -------------------------------------------------------------------- */
369 : /* Do we have a CAST operator in play? */
370 : /* -------------------------------------------------------------------- */
371 2962 : if( poExpr->eNodeType == SNT_OPERATION
372 : && poExpr->nOperation == SWQ_CAST )
373 : {
374 24 : const char *pszTypeName = poExpr->papoSubExpr[1]->string_value;
375 24 : int parse_precision = 0;
376 :
377 24 : if( EQUAL(pszTypeName,"character") )
378 : {
379 14 : col_def->target_type = SWQ_STRING;
380 14 : col_def->field_length = 1;
381 : }
382 10 : else if( strcasecmp(pszTypeName,"integer") == 0 )
383 : {
384 2 : col_def->target_type = SWQ_INTEGER;
385 : }
386 8 : else if( strcasecmp(pszTypeName,"float") == 0 )
387 : {
388 0 : col_def->target_type = SWQ_FLOAT;
389 : }
390 8 : else if( strcasecmp(pszTypeName,"numeric") == 0 )
391 : {
392 2 : col_def->target_type = SWQ_FLOAT;
393 2 : parse_precision = 1;
394 : }
395 6 : else if( strcasecmp(pszTypeName,"timestamp") == 0 )
396 : {
397 0 : col_def->target_type = SWQ_TIMESTAMP;
398 : }
399 6 : else if( strcasecmp(pszTypeName,"date") == 0 )
400 : {
401 0 : col_def->target_type = SWQ_DATE;
402 : }
403 6 : 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 6 : pszTypeName );
412 6 : CPLFree(col_def->field_name);
413 6 : col_def->field_name = NULL;
414 6 : CPLFree(col_def->field_alias);
415 6 : col_def->field_alias = NULL;
416 6 : result_columns--;
417 6 : return FALSE;
418 : }
419 :
420 : // field width.
421 18 : if( poExpr->nSubExprCount > 2 )
422 : {
423 10 : col_def->field_length = poExpr->papoSubExpr[2]->int_value;
424 : }
425 :
426 : // field width.
427 18 : if( poExpr->nSubExprCount > 3 && parse_precision )
428 : {
429 2 : 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 2956 : if( poExpr->eNodeType == SNT_OPERATION
437 : && poExpr->nOperation >= SWQ_AVG
438 : && poExpr->nOperation <= SWQ_SUM )
439 : {
440 256 : if( poExpr->nSubExprCount != 1 )
441 : {
442 : CPLError( CE_Failure, CPLE_AppDefined,
443 : "Column Summary Function '%s' has wrong number of arguments.",
444 4 : poExpr->string_value ? poExpr->string_value : "(null)");
445 4 : CPLFree(col_def->field_name);
446 4 : col_def->field_name = NULL;
447 4 : CPLFree(col_def->field_alias);
448 4 : col_def->field_alias = NULL;
449 4 : result_columns--;
450 4 : return FALSE;
451 : }
452 : else
453 : {
454 : col_def->col_func =
455 252 : (swq_col_func) poExpr->nOperation;
456 :
457 252 : swq_expr_node *poSubExpr = poExpr->papoSubExpr[0];
458 :
459 252 : poExpr->papoSubExpr[0] = NULL;
460 252 : poExpr->nSubExprCount = 0;
461 252 : delete poExpr;
462 :
463 252 : poExpr = poSubExpr;
464 : }
465 : }
466 :
467 2952 : col_def->expr = poExpr;
468 :
469 2952 : return TRUE;
470 : }
471 :
472 : /************************************************************************/
473 : /* PushTableDef() */
474 : /************************************************************************/
475 :
476 816 : int swq_select::PushTableDef( const char *pszDataSource,
477 : const char *pszName,
478 : const char *pszAlias )
479 :
480 : {
481 816 : table_count++;
482 :
483 : table_defs = (swq_table_def *)
484 816 : CPLRealloc( table_defs, sizeof(swq_table_def) * table_count );
485 :
486 816 : if( pszDataSource != NULL )
487 10 : table_defs[table_count-1].data_source = CPLStrdup(pszDataSource);
488 : else
489 806 : table_defs[table_count-1].data_source = NULL;
490 :
491 816 : table_defs[table_count-1].table_name = CPLStrdup(pszName);
492 :
493 816 : if( pszAlias != NULL )
494 32 : table_defs[table_count-1].table_alias = CPLStrdup(pszAlias);
495 : else
496 784 : table_defs[table_count-1].table_alias = CPLStrdup(pszName);
497 :
498 816 : return table_count-1;
499 : }
500 :
501 : /************************************************************************/
502 : /* PushOrderBy() */
503 : /************************************************************************/
504 :
505 50 : void swq_select::PushOrderBy( const char *pszFieldName, int bAscending )
506 :
507 : {
508 50 : order_specs++;
509 : order_defs = (swq_order_def *)
510 50 : CPLRealloc( order_defs, sizeof(swq_order_def) * order_specs );
511 :
512 50 : order_defs[order_specs-1].field_name = CPLStrdup(pszFieldName);
513 50 : order_defs[order_specs-1].table_index = -1;
514 50 : order_defs[order_specs-1].field_index = -1;
515 50 : order_defs[order_specs-1].ascending_flag = bAscending;
516 50 : }
517 :
518 : /************************************************************************/
519 : /* PushJoin() */
520 : /************************************************************************/
521 :
522 46 : void swq_select::PushJoin( int iSecondaryTable,
523 : const char *pszPrimaryField,
524 : const char *pszSecondaryField )
525 :
526 : {
527 46 : join_count++;
528 : join_defs = (swq_join_def *)
529 46 : CPLRealloc( join_defs, sizeof(swq_join_def) * join_count );
530 :
531 46 : join_defs[join_count-1].secondary_table = iSecondaryTable;
532 46 : join_defs[join_count-1].primary_field_name = CPLStrdup(pszPrimaryField);
533 46 : join_defs[join_count-1].primary_field = -1;
534 46 : join_defs[join_count-1].op = SWQ_EQ;
535 46 : join_defs[join_count-1].secondary_field_name = CPLStrdup(pszSecondaryField);
536 46 : join_defs[join_count-1].secondary_field = -1;
537 46 : }
538 :
539 :
540 : /************************************************************************/
541 : /* expand_wildcard() */
542 : /* */
543 : /* This function replaces the '*' in a "SELECT *" with the list */
544 : /* provided list of fields. Itis used by swq_select_parse(), */
545 : /* but may be called in advance by applications wanting the */
546 : /* "default" field list to be different than the full list of */
547 : /* fields. */
548 : /************************************************************************/
549 :
550 1398 : CPLErr swq_select::expand_wildcard( swq_field_list *field_list )
551 :
552 : {
553 : int isrc;
554 :
555 : /* ==================================================================== */
556 : /* Check each pre-expansion field. */
557 : /* ==================================================================== */
558 8938 : for( isrc = 0; isrc < result_columns; isrc++ )
559 : {
560 7540 : const char *src_fieldname = column_defs[isrc].field_name;
561 : int itable, new_fields, i, iout;
562 :
563 14924 : if( *src_fieldname == '\0'
564 7384 : || src_fieldname[strlen(src_fieldname)-1] != '*' )
565 6820 : continue;
566 :
567 : /* We don't want to expand COUNT(*) */
568 720 : if( column_defs[isrc].col_func == SWQCF_COUNT )
569 374 : continue;
570 :
571 : /* -------------------------------------------------------------------- */
572 : /* Parse out the table name, verify it, and establish the */
573 : /* number of fields to insert from it. */
574 : /* -------------------------------------------------------------------- */
575 346 : if( strcmp(src_fieldname,"*") == 0 )
576 : {
577 326 : itable = -1;
578 326 : new_fields = field_list->count;
579 : }
580 40 : else if( strlen(src_fieldname) < 3
581 20 : || src_fieldname[strlen(src_fieldname)-2] != '.' )
582 : {
583 : CPLError( CE_Failure, CPLE_AppDefined,
584 : "Ill formatted field definition '%s'.",
585 0 : src_fieldname );
586 0 : return CE_Failure;
587 : }
588 : else
589 : {
590 20 : char *table_name = CPLStrdup( src_fieldname );
591 20 : table_name[strlen(src_fieldname)-2] = '\0';
592 :
593 24 : for( itable = 0; itable < field_list->table_count; itable++ )
594 : {
595 24 : if( strcasecmp(table_name,
596 24 : field_list->table_defs[itable].table_alias ) == 0 )
597 20 : break;
598 : }
599 :
600 20 : if( itable == field_list->table_count )
601 : {
602 : CPLError( CE_Failure, CPLE_AppDefined,
603 : "Table %s not recognised from %s definition.",
604 0 : table_name, src_fieldname );
605 0 : CPLFree( table_name );
606 0 : return CE_Failure;
607 : }
608 20 : CPLFree( table_name );
609 :
610 : /* count the number of fields in this table. */
611 20 : new_fields = 0;
612 132 : for( i = 0; i < field_list->count; i++ )
613 : {
614 112 : if( field_list->table_ids[i] == itable )
615 60 : new_fields++;
616 : }
617 : }
618 :
619 346 : if (new_fields > 0)
620 : {
621 : /* -------------------------------------------------------------------- */
622 : /* Reallocate the column list larger. */
623 : /* -------------------------------------------------------------------- */
624 342 : CPLFree( column_defs[isrc].field_name );
625 342 : delete column_defs[isrc].expr;
626 :
627 : column_defs = (swq_col_def *)
628 : CPLRealloc( column_defs,
629 : sizeof(swq_col_def) *
630 342 : (result_columns + new_fields - 1 ) );
631 :
632 : /* -------------------------------------------------------------------- */
633 : /* Push the old definitions that came after the one to be */
634 : /* replaced further up in the array. */
635 : /* -------------------------------------------------------------------- */
636 342 : if (new_fields != 1)
637 : {
638 354 : for( i = result_columns-1; i > isrc; i-- )
639 : {
640 : memcpy( column_defs + i + new_fields - 1,
641 : column_defs + i,
642 22 : sizeof( swq_col_def ) );
643 : }
644 : }
645 :
646 342 : result_columns += (new_fields - 1 );
647 :
648 : /* -------------------------------------------------------------------- */
649 : /* Zero out all the stuff in the target column definitions. */
650 : /* -------------------------------------------------------------------- */
651 : memset( column_defs + isrc, 0,
652 342 : new_fields * sizeof(swq_col_def) );
653 : }
654 : else
655 : {
656 : /* -------------------------------------------------------------------- */
657 : /* The wildcard expands to nothing */
658 : /* -------------------------------------------------------------------- */
659 4 : CPLFree( column_defs[isrc].field_name );
660 4 : delete column_defs[isrc].expr;
661 :
662 : memmove( column_defs + isrc,
663 : column_defs + isrc + 1,
664 4 : sizeof( swq_col_def ) * (result_columns-1-isrc) );
665 :
666 4 : result_columns --;
667 : }
668 :
669 : /* -------------------------------------------------------------------- */
670 : /* Assign the selected fields. */
671 : /* -------------------------------------------------------------------- */
672 346 : iout = isrc;
673 :
674 1498 : for( i = 0; i < field_list->count; i++ )
675 : {
676 : swq_col_def *def;
677 1152 : int compose = itable != -1;
678 :
679 : /* skip this field if it isn't in the target table. */
680 1264 : if( itable != -1 && field_list->table_ids != NULL
681 112 : && itable != field_list->table_ids[i] )
682 52 : continue;
683 :
684 : /* set up some default values. */
685 1100 : def = column_defs + iout;
686 1100 : def->field_precision = -1;
687 1100 : def->target_type = SWQ_OTHER;
688 :
689 : /* does this field duplicate an earlier one? */
690 2200 : if( field_list->table_ids != NULL
691 1100 : && field_list->table_ids[i] != 0
692 : && !compose )
693 : {
694 : int other;
695 :
696 318 : for( other = 0; other < i; other++ )
697 : {
698 540 : if( strcasecmp(field_list->names[i],
699 270 : field_list->names[other]) == 0 )
700 : {
701 18 : compose = 1;
702 18 : break;
703 : }
704 : }
705 : }
706 :
707 1100 : if( !compose )
708 1022 : def->field_name = CPLStrdup( field_list->names[i] );
709 : else
710 : {
711 78 : int itable = field_list->table_ids[i];
712 : char *composed_name;
713 78 : const char *field_name = field_list->names[i];
714 : const char *table_alias =
715 78 : field_list->table_defs[itable].table_alias;
716 :
717 : composed_name = (char *)
718 78 : CPLMalloc(strlen(field_name)+strlen(table_alias)+2);
719 :
720 78 : sprintf( composed_name, "%s.%s", table_alias, field_name );
721 :
722 78 : def->field_name = composed_name;
723 : }
724 :
725 1100 : iout++;
726 :
727 : /* All the other table info will be provided by the later
728 : parse operation. */
729 : }
730 :
731 : /* If there are several occurrences of '*', go on, but stay on the */
732 : /* same index in case '*' is expanded to nothing */
733 : /* (the -- is to compensate the fact that isrc will be incremented in */
734 : /* the after statement of the for loop) */
735 346 : isrc --;
736 : }
737 :
738 1398 : return CE_None;
739 : }
740 :
741 : /************************************************************************/
742 : /* parse() */
743 : /* */
744 : /* This method really does post-parse processing. */
745 : /************************************************************************/
746 :
747 700 : CPLErr swq_select::parse( swq_field_list *field_list,
748 : int parse_flags )
749 :
750 : {
751 : int i;
752 : CPLErr eError;
753 :
754 700 : eError = expand_wildcard( field_list );
755 700 : if( eError != CE_None )
756 0 : return eError;
757 :
758 :
759 : /* -------------------------------------------------------------------- */
760 : /* Identify field information. */
761 : /* -------------------------------------------------------------------- */
762 4276 : for( i = 0; i < result_columns; i++ )
763 : {
764 3602 : swq_col_def *def = column_defs + i;
765 :
766 3690 : if( def->expr != NULL && def->expr->eNodeType != SNT_COLUMN )
767 : {
768 92 : def->field_index = -1;
769 92 : def->table_index = -1;
770 :
771 92 : if( def->expr->Check( field_list ) == SWQ_ERROR )
772 4 : return CE_Failure;
773 :
774 88 : def->field_type = def->expr->field_type;
775 :
776 : // If the field was changed from string constant to
777 : // column field then adopt the name.
778 88 : if( def->expr->eNodeType == SNT_COLUMN )
779 : {
780 4 : def->field_index = def->expr->field_index;
781 4 : def->table_index = def->expr->table_index;
782 :
783 4 : CPLFree( def->field_name );
784 4 : def->field_name = CPLStrdup(def->expr->string_value);
785 : }
786 : }
787 : else
788 : {
789 : swq_field_type this_type;
790 :
791 : /* identify field */
792 : def->field_index = swq_identify_field( def->field_name, field_list,
793 : &this_type,
794 3510 : &(def->table_index) );
795 :
796 : /* record field type */
797 3510 : def->field_type = this_type;
798 :
799 3510 : if( def->field_index == -1 && def->col_func != SWQCF_COUNT )
800 : {
801 : CPLError( CE_Failure, CPLE_AppDefined,
802 : "Unrecognised field name %s.",
803 14 : def->field_name );
804 14 : return CE_Failure;
805 : }
806 : }
807 :
808 : /* identify column function if present */
809 3584 : if( (def->col_func == SWQCF_MIN
810 : || def->col_func == SWQCF_MAX
811 : || def->col_func == SWQCF_AVG
812 : || def->col_func == SWQCF_SUM)
813 : && def->field_type == SWQ_STRING )
814 : {
815 : // possibly this is already enforced by the checker?
816 : const swq_operation *op = swq_op_registrar::GetOperator(
817 8 : (swq_op) def->col_func );
818 :
819 : CPLError( CE_Failure, CPLE_AppDefined,
820 : "Use of field function %s() on string field %s illegal.",
821 8 : op->osName.c_str(), def->field_name );
822 8 : return CE_Failure;
823 : }
824 : }
825 :
826 : /* -------------------------------------------------------------------- */
827 : /* Check if we are producing a one row summary result or a set */
828 : /* of records. Generate an error if we get conflicting */
829 : /* indications. */
830 : /* -------------------------------------------------------------------- */
831 674 : query_mode = -1;
832 4238 : for( i = 0; i < result_columns; i++ )
833 : {
834 3566 : swq_col_def *def = column_defs + i;
835 3566 : int this_indicator = -1;
836 :
837 3794 : if( def->col_func == SWQCF_MIN
838 : || def->col_func == SWQCF_MAX
839 : || def->col_func == SWQCF_AVG
840 : || def->col_func == SWQCF_SUM
841 : || def->col_func == SWQCF_COUNT )
842 228 : this_indicator = SWQM_SUMMARY_RECORD;
843 3338 : else if( def->col_func == SWQCF_NONE )
844 : {
845 3338 : if( def->distinct_flag )
846 34 : this_indicator = SWQM_DISTINCT_LIST;
847 : else
848 3304 : this_indicator = SWQM_RECORDSET;
849 : }
850 :
851 3566 : if( this_indicator != query_mode
852 : && this_indicator != -1
853 : && query_mode != -1 )
854 : {
855 : CPLError( CE_Failure, CPLE_AppDefined,
856 2 : "Field list implies mixture of regular recordset mode, summary mode or distinct field list mode." );
857 2 : return CE_Failure;
858 : }
859 :
860 3564 : if( this_indicator != -1 )
861 3564 : query_mode = this_indicator;
862 : }
863 :
864 672 : if( result_columns > 1
865 : && query_mode == SWQM_DISTINCT_LIST )
866 : {
867 : CPLError( CE_Failure, CPLE_AppDefined,
868 0 : "SELECTing more than one DISTINCT field is a query not supported." );
869 0 : return CE_Failure;
870 : }
871 672 : else if (result_columns == 0)
872 : {
873 2 : query_mode = SWQM_RECORDSET;
874 : }
875 :
876 : /* -------------------------------------------------------------------- */
877 : /* Process column names in JOIN specs. */
878 : /* -------------------------------------------------------------------- */
879 710 : for( i = 0; i < join_count; i++ )
880 : {
881 42 : swq_join_def *def = join_defs + i;
882 : int table_id;
883 :
884 : /* identify primary field */
885 : def->primary_field = swq_identify_field( def->primary_field_name,
886 42 : field_list, NULL, &table_id );
887 42 : if( def->primary_field == -1 )
888 : {
889 : CPLError( CE_Failure, CPLE_AppDefined,
890 : "Unrecognised primary field %s in JOIN clause..",
891 0 : def->primary_field_name );
892 0 : return CE_Failure;
893 : }
894 :
895 42 : if( table_id != 0 )
896 : {
897 : CPLError( CE_Failure, CPLE_AppDefined,
898 : "Currently the primary key must come from the primary table in\n"
899 : "JOIN, %s is not from the primary table.",
900 0 : def->primary_field_name );
901 0 : return CE_Failure;
902 : }
903 :
904 : /* identify secondary field */
905 : def->secondary_field = swq_identify_field( def->secondary_field_name,
906 42 : field_list, NULL,&table_id);
907 42 : if( def->secondary_field == -1 )
908 : {
909 : CPLError( CE_Failure, CPLE_AppDefined,
910 : "Unrecognised secondary field %s in JOIN clause..",
911 4 : def->secondary_field_name );
912 4 : return CE_Failure;
913 : }
914 :
915 38 : if( table_id != def->secondary_table )
916 : {
917 : CPLError( CE_Failure, CPLE_AppDefined,
918 : "Currently the secondary key must come from the secondary table\n"
919 : "listed in the JOIN. %s is not from table %s..",
920 : def->secondary_field_name,
921 0 : table_defs[def->secondary_table].table_name);
922 0 : return CE_Failure;
923 : }
924 : }
925 :
926 : /* -------------------------------------------------------------------- */
927 : /* Process column names in order specs. */
928 : /* -------------------------------------------------------------------- */
929 712 : for( i = 0; i < order_specs; i++ )
930 : {
931 46 : swq_order_def *def = order_defs + i;
932 :
933 : /* identify field */
934 : def->field_index = swq_identify_field( def->field_name, field_list,
935 46 : NULL, &(def->table_index) );
936 46 : if( def->field_index == -1 )
937 : {
938 : CPLError( CE_Failure, CPLE_AppDefined,
939 : "Unrecognised field name %s in ORDER BY.",
940 2 : def->field_name );
941 2 : return CE_Failure;
942 : }
943 : }
944 :
945 : /* -------------------------------------------------------------------- */
946 : /* Post process the where clause, subbing in field indexes and */
947 : /* doing final validation. */
948 : /* -------------------------------------------------------------------- */
949 666 : if( where_expr != NULL
950 : && where_expr->Check( field_list ) == SWQ_ERROR )
951 : {
952 14 : return CE_Failure;
953 : }
954 :
955 652 : return CE_None;
956 : }
|