swq_field_type SWQCastChecker( swq_expr_node *poNode, CPL_UNUSED int bAllowMismatchTypeOnFieldComparison ) { swq_field_type eType = SWQ_ERROR; const char *pszTypeName = poNode->papoSubExpr[1]->string_value; if( poNode->papoSubExpr[0]->field_type == SWQ_GEOMETRY && !(EQUAL(pszTypeName,"character") || EQUAL(pszTypeName,"geometry")) ) { CPLError( CE_Failure, CPLE_AppDefined, "Cannot cast geometry to %s", pszTypeName ); } else if( EQUAL(pszTypeName,"boolean") ) eType = SWQ_BOOLEAN; else if( EQUAL(pszTypeName,"character") ) eType = SWQ_STRING; else if( EQUAL(pszTypeName,"integer") ) eType = SWQ_INTEGER; else if( EQUAL(pszTypeName,"bigint") ) eType = SWQ_INTEGER64; else if( EQUAL(pszTypeName,"smallint") ) eType = SWQ_INTEGER; else if( EQUAL(pszTypeName,"float") ) eType = SWQ_FLOAT; else if( EQUAL(pszTypeName,"numeric") ) eType = SWQ_FLOAT; else if( EQUAL(pszTypeName,"timestamp") ) eType = SWQ_TIMESTAMP; else if( EQUAL(pszTypeName,"date") ) eType = SWQ_DATE; else if( EQUAL(pszTypeName,"time") ) eType = SWQ_TIME; else if( EQUAL(pszTypeName,"geometry") ) { if( !(poNode->papoSubExpr[0]->field_type == SWQ_GEOMETRY || poNode->papoSubExpr[0]->field_type == SWQ_STRING) ) { CPLError( CE_Failure, CPLE_AppDefined, "Cannot cast %s to geometry", SWQFieldTypeToString(poNode->papoSubExpr[0]->field_type) ); } else eType = SWQ_GEOMETRY; } else { CPLError( CE_Failure, CPLE_AppDefined, "Unrecognized typename %s in CAST operator.", pszTypeName ); } poNode->field_type = eType; return eType; }
CPLErr swq_select::parse( swq_field_list *field_list, swq_select_parse_options* poParseOptions ) { int i; CPLErr eError; int bAlwaysPrefixWithTableName = poParseOptions && poParseOptions->bAlwaysPrefixWithTableName; eError = expand_wildcard( field_list, bAlwaysPrefixWithTableName ); if( eError != CE_None ) return eError; swq_custom_func_registrar* poCustomFuncRegistrar = NULL; if( poParseOptions != NULL ) poCustomFuncRegistrar = poParseOptions->poCustomFuncRegistrar; /* -------------------------------------------------------------------- */ /* Identify field information. */ /* -------------------------------------------------------------------- */ for( i = 0; i < result_columns; i++ ) { swq_col_def *def = column_defs + i; if( def->expr != NULL && def->expr->eNodeType != SNT_COLUMN ) { def->field_index = -1; def->table_index = -1; if( def->expr->Check( field_list, TRUE, FALSE, poCustomFuncRegistrar ) == SWQ_ERROR ) return CE_Failure; def->field_type = def->expr->field_type; } else { swq_field_type this_type; /* identify field */ def->field_index = swq_identify_field( def->table_name, def->field_name, field_list, &this_type, &(def->table_index) ); /* record field type */ def->field_type = this_type; if( def->field_index == -1 && def->col_func != SWQCF_COUNT ) { CPLError( CE_Failure, CPLE_AppDefined, "Unrecognised field name %s.", def->table_name[0] ? CPLSPrintf("%s.%s", def->table_name, def->field_name) : def->field_name ); return CE_Failure; } } /* identify column function if present */ if( (def->col_func == SWQCF_MIN || def->col_func == SWQCF_MAX || def->col_func == SWQCF_AVG || def->col_func == SWQCF_SUM) && (def->field_type == SWQ_STRING || def->field_type == SWQ_GEOMETRY) ) { // possibly this is already enforced by the checker? const swq_operation *op = swq_op_registrar::GetOperator( (swq_op) def->col_func ); CPLError( CE_Failure, CPLE_AppDefined, "Use of field function %s() on %s field %s illegal.", op->pszName, SWQFieldTypeToString(def->field_type), def->field_name ); return CE_Failure; } } /* -------------------------------------------------------------------- */ /* Check if we are producing a one row summary result or a set */ /* of records. Generate an error if we get conflicting */ /* indications. */ /* -------------------------------------------------------------------- */ int bAllowDistinctOnMultipleFields = ( poParseOptions && poParseOptions->bAllowDistinctOnMultipleFields ); if( query_mode == SWQM_DISTINCT_LIST && result_columns > 1 && !bAllowDistinctOnMultipleFields ) { CPLError( CE_Failure, CPLE_NotSupported, "SELECT DISTINCT not supported on multiple columns." ); return CE_Failure; } for( i = 0; i < result_columns; i++ ) { swq_col_def *def = column_defs + i; int this_indicator = -1; if( query_mode == SWQM_DISTINCT_LIST && def->field_type == SWQ_GEOMETRY ) { int bAllowDistinctOnGeometryField = ( poParseOptions && poParseOptions->bAllowDistinctOnGeometryField ); if( !bAllowDistinctOnGeometryField ) { CPLError( CE_Failure, CPLE_NotSupported, "SELECT DISTINCT on a geometry not supported." ); return CE_Failure; } } if( def->col_func == SWQCF_MIN || def->col_func == SWQCF_MAX || def->col_func == SWQCF_AVG || def->col_func == SWQCF_SUM || def->col_func == SWQCF_COUNT ) { this_indicator = SWQM_SUMMARY_RECORD; if( def->col_func == SWQCF_COUNT && def->distinct_flag && def->field_type == SWQ_GEOMETRY ) { CPLError( CE_Failure, CPLE_AppDefined, "SELECT COUNT DISTINCT on a geometry not supported." ); return CE_Failure; } } else if( def->col_func == SWQCF_NONE ) { if( query_mode == SWQM_DISTINCT_LIST ) { def->distinct_flag = TRUE; this_indicator = SWQM_DISTINCT_LIST; } else this_indicator = SWQM_RECORDSET; } if( this_indicator != query_mode && this_indicator != -1 && query_mode != 0 ) { CPLError( CE_Failure, CPLE_AppDefined, "Field list implies mixture of regular recordset mode, summary mode or distinct field list mode." ); return CE_Failure; } if( this_indicator != -1 ) query_mode = this_indicator; } if (result_columns == 0) { query_mode = SWQM_RECORDSET; } /* -------------------------------------------------------------------- */ /* Process column names in JOIN specs. */ /* -------------------------------------------------------------------- */ for( i = 0; i < join_count; i++ ) { swq_join_def *def = join_defs + i; if( def->poExpr->Check( field_list, TRUE, TRUE, poCustomFuncRegistrar ) == SWQ_ERROR ) return CE_Failure; if( !CheckCompatibleJoinExpr( def->poExpr, def->secondary_table, field_list ) ) return CE_Failure; } /* -------------------------------------------------------------------- */ /* Process column names in order specs. */ /* -------------------------------------------------------------------- */ for( i = 0; i < order_specs; i++ ) { swq_order_def *def = order_defs + i; /* identify field */ swq_field_type field_type; def->field_index = swq_identify_field( def->table_name, def->field_name, field_list, &field_type, &(def->table_index) ); if( def->field_index == -1 ) { CPLError( CE_Failure, CPLE_AppDefined, "Unrecognised field name %s in ORDER BY.", def->table_name[0] ? CPLSPrintf("%s.%s", def->table_name, def->field_name) : def->field_name ); return CE_Failure; } if( def->table_index != 0 ) { CPLError( CE_Failure, CPLE_AppDefined, "Cannot use field '%s' of a secondary table in a ORDER BY clause", def->field_name ); return CE_Failure; } if( field_type == SWQ_GEOMETRY ) { CPLError( CE_Failure, CPLE_AppDefined, "Cannot use geometry field '%s' in a ORDER BY clause", def->field_name ); return CE_Failure; } } /* -------------------------------------------------------------------- */ /* Post process the where clause, subbing in field indexes and */ /* doing final validation. */ /* -------------------------------------------------------------------- */ int bAllowFieldsInSecondaryTablesInWhere = FALSE; if( poParseOptions != NULL ) bAllowFieldsInSecondaryTablesInWhere = poParseOptions->bAllowFieldsInSecondaryTablesInWhere; if( where_expr != NULL && where_expr->Check( field_list, bAllowFieldsInSecondaryTablesInWhere, FALSE, poCustomFuncRegistrar ) == SWQ_ERROR ) { return CE_Failure; } return CE_None; }
CPLErr swq_select::parse( swq_field_list *field_list, CPL_UNUSED int parse_flags ) { int i; CPLErr eError; eError = expand_wildcard( field_list ); if( eError != CE_None ) return eError; /* -------------------------------------------------------------------- */ /* Identify field information. */ /* -------------------------------------------------------------------- */ for( i = 0; i < result_columns; i++ ) { swq_col_def *def = column_defs + i; if( def->expr != NULL && def->expr->eNodeType != SNT_COLUMN ) { def->field_index = -1; def->table_index = -1; if( def->expr->Check( field_list, TRUE ) == SWQ_ERROR ) return CE_Failure; def->field_type = def->expr->field_type; // If the field was changed from string constant to // column field then adopt the name. if( def->expr->eNodeType == SNT_COLUMN ) { def->field_index = def->expr->field_index; def->table_index = def->expr->table_index; CPLFree( def->field_name ); def->field_name = CPLStrdup(def->expr->string_value); } } else { swq_field_type this_type; /* identify field */ def->field_index = swq_identify_field( def->field_name, field_list, &this_type, &(def->table_index) ); /* record field type */ def->field_type = this_type; if( def->field_index == -1 && def->col_func != SWQCF_COUNT ) { CPLError( CE_Failure, CPLE_AppDefined, "Unrecognised field name %s.", def->field_name ); return CE_Failure; } } /* identify column function if present */ if( (def->col_func == SWQCF_MIN || def->col_func == SWQCF_MAX || def->col_func == SWQCF_AVG || def->col_func == SWQCF_SUM) && (def->field_type == SWQ_STRING || def->field_type == SWQ_GEOMETRY) ) { // possibly this is already enforced by the checker? const swq_operation *op = swq_op_registrar::GetOperator( (swq_op) def->col_func ); CPLError( CE_Failure, CPLE_AppDefined, "Use of field function %s() on %s field %s illegal.", op->pszName, SWQFieldTypeToString(def->field_type), def->field_name ); return CE_Failure; } } /* -------------------------------------------------------------------- */ /* Check if we are producing a one row summary result or a set */ /* of records. Generate an error if we get conflicting */ /* indications. */ /* -------------------------------------------------------------------- */ query_mode = -1; for( i = 0; i < result_columns; i++ ) { swq_col_def *def = column_defs + i; int this_indicator = -1; if( def->col_func == SWQCF_MIN || def->col_func == SWQCF_MAX || def->col_func == SWQCF_AVG || def->col_func == SWQCF_SUM || def->col_func == SWQCF_COUNT ) { this_indicator = SWQM_SUMMARY_RECORD; if( def->col_func == SWQCF_COUNT && def->distinct_flag && def->field_type == SWQ_GEOMETRY ) { CPLError( CE_Failure, CPLE_AppDefined, "SELECT COUNT DISTINCT on a geometry not supported." ); return CE_Failure; } } else if( def->col_func == SWQCF_NONE ) { if( def->distinct_flag ) { this_indicator = SWQM_DISTINCT_LIST; if( def->field_type == SWQ_GEOMETRY ) { CPLError( CE_Failure, CPLE_AppDefined, "SELECT DISTINCT on a geometry not supported." ); return CE_Failure; } } else this_indicator = SWQM_RECORDSET; } if( this_indicator != query_mode && this_indicator != -1 && query_mode != -1 ) { CPLError( CE_Failure, CPLE_AppDefined, "Field list implies mixture of regular recordset mode, summary mode or distinct field list mode." ); return CE_Failure; } if( this_indicator != -1 ) query_mode = this_indicator; } if( result_columns > 1 && query_mode == SWQM_DISTINCT_LIST ) { CPLError( CE_Failure, CPLE_AppDefined, "SELECTing more than one DISTINCT field is a query not supported." ); return CE_Failure; } else if (result_columns == 0) { query_mode = SWQM_RECORDSET; } /* -------------------------------------------------------------------- */ /* Process column names in JOIN specs. */ /* -------------------------------------------------------------------- */ for( i = 0; i < join_count; i++ ) { swq_join_def *def = join_defs + i; int table_id; /* identify primary field */ def->primary_field = swq_identify_field( def->primary_field_name, field_list, NULL, &table_id ); if( def->primary_field == -1 ) { CPLError( CE_Failure, CPLE_AppDefined, "Unrecognised primary field %s in JOIN clause..", def->primary_field_name ); return CE_Failure; } if( table_id != 0 ) { CPLError( CE_Failure, CPLE_AppDefined, "Currently the primary key must come from the primary table in\n" "JOIN, %s is not from the primary table.", def->primary_field_name ); return CE_Failure; } /* identify secondary field */ def->secondary_field = swq_identify_field( def->secondary_field_name, field_list, NULL,&table_id); if( def->secondary_field == -1 ) { CPLError( CE_Failure, CPLE_AppDefined, "Unrecognised secondary field %s in JOIN clause..", def->secondary_field_name ); return CE_Failure; } if( table_id != def->secondary_table ) { CPLError( CE_Failure, CPLE_AppDefined, "Currently the secondary key must come from the secondary table\n" "listed in the JOIN. %s is not from table %s..", def->secondary_field_name, table_defs[def->secondary_table].table_name); return CE_Failure; } } /* -------------------------------------------------------------------- */ /* Process column names in order specs. */ /* -------------------------------------------------------------------- */ for( i = 0; i < order_specs; i++ ) { swq_order_def *def = order_defs + i; /* identify field */ swq_field_type field_type; def->field_index = swq_identify_field( def->field_name, field_list, &field_type, &(def->table_index) ); if( def->field_index == -1 ) { CPLError( CE_Failure, CPLE_AppDefined, "Unrecognised field name %s in ORDER BY.", def->field_name ); return CE_Failure; } if( def->table_index != 0 ) { CPLError( CE_Failure, CPLE_AppDefined, "Cannot use field '%s' of a secondary table in a ORDER BY clause", def->field_name ); return CE_Failure; } if( field_type == SWQ_GEOMETRY ) { CPLError( CE_Failure, CPLE_AppDefined, "Cannot use geometry field '%s' in a ORDER BY clause", def->field_name ); return CE_Failure; } } /* -------------------------------------------------------------------- */ /* Post process the where clause, subbing in field indexes and */ /* doing final validation. */ /* -------------------------------------------------------------------- */ if( where_expr != NULL && where_expr->Check( field_list, FALSE ) == SWQ_ERROR ) { return CE_Failure; } return CE_None; }