Esempio n. 1
0
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;
}
Esempio n. 2
0
CPLErr swq_select::parse( swq_field_list *field_list,
                          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 ) == 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 )
        {
            // 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 string field %s illegal.", 
                          op->osName.c_str(), 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;
        else if( def->col_func == SWQCF_NONE )
        {
            if( def->distinct_flag )
                this_indicator = SWQM_DISTINCT_LIST;
            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 */
        def->field_index = swq_identify_field( def->field_name, field_list,
                                               NULL, &(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;
        }
    }

/* -------------------------------------------------------------------- */
/*      Post process the where clause, subbing in field indexes and     */
/*      doing final validation.                                         */
/* -------------------------------------------------------------------- */
    if( where_expr != NULL 
        && where_expr->Check( field_list ) == SWQ_ERROR )
    {
        return CE_Failure;
    }
    
    return CE_None;
}
Esempio n. 3
0
swq_field_type
swq_expr_node::Check( swq_field_list *poFieldList,
                      int bAllowFieldsInSecondaryTables,
                      int bAllowMismatchTypeOnFieldComparison,
                      swq_custom_func_registrar* poCustomFuncRegistrar,
                      int nDepth )

{
    if( nDepth == 32 )
    {
        CPLError(CE_Failure, CPLE_AppDefined,
                 "Too many recursion levels in expression");
        return SWQ_ERROR;
    }

/* -------------------------------------------------------------------- */
/*      Otherwise we take constants literally.                          */
/* -------------------------------------------------------------------- */
    if( eNodeType == SNT_CONSTANT )
        return field_type;

/* -------------------------------------------------------------------- */
/*      If this is intended to be a field definition, but has not       */
/*      yet been looked up, we do so now.                               */
/* -------------------------------------------------------------------- */
    if( eNodeType == SNT_COLUMN && field_index == -1 )
    {
        field_index =
            swq_identify_field( table_name, string_value, poFieldList,
                                &field_type, &table_index );

        if( field_index < 0 )
        {
            if( table_name )
                CPLError( CE_Failure, CPLE_AppDefined,
                      R"("%s"."%s" not recognised as an available field.)",
                      table_name, string_value );
            else
                CPLError( CE_Failure, CPLE_AppDefined,
                      "\"%s\" not recognised as an available field.",
                      string_value );

            return SWQ_ERROR;
        }

        if( !bAllowFieldsInSecondaryTables && table_index != 0 )
        {
            CPLError(
                CE_Failure, CPLE_AppDefined,
                "Cannot use field '%s' of a secondary table in this context",
                string_value );
            return SWQ_ERROR;
        }
    }

    if( eNodeType == SNT_COLUMN )
        return field_type;

/* -------------------------------------------------------------------- */
/*      We are dealing with an operation - fetch the definition.        */
/* -------------------------------------------------------------------- */
    const swq_operation *poOp =
        (nOperation == SWQ_CUSTOM_FUNC && poCustomFuncRegistrar != nullptr ) ?
            poCustomFuncRegistrar->GetOperator(string_value) :
            swq_op_registrar::GetOperator(static_cast<swq_op>(nOperation));

    if( poOp == nullptr )
    {
        if( nOperation == SWQ_CUSTOM_FUNC )
            CPLError( CE_Failure, CPLE_AppDefined,
                      "Check(): Unable to find definition for operator %s.",
                      string_value );
        else
            CPLError( CE_Failure, CPLE_AppDefined,
                      "Check(): Unable to find definition for operator %d.",
                      nOperation );
        return SWQ_ERROR;
    }

/* -------------------------------------------------------------------- */
/*      Check subexpressions first.                                     */
/* -------------------------------------------------------------------- */
    for( int i = 0; i < nSubExprCount; i++ )
    {
        if( papoSubExpr[i]->Check(poFieldList, bAllowFieldsInSecondaryTables,
                                  bAllowMismatchTypeOnFieldComparison,
                                  poCustomFuncRegistrar,
                                  nDepth + 1) == SWQ_ERROR )
            return SWQ_ERROR;
    }

/* -------------------------------------------------------------------- */
/*      Check this node.                                                */
/* -------------------------------------------------------------------- */
    field_type = poOp->pfnChecker( this, bAllowMismatchTypeOnFieldComparison );

    return field_type;
}
swq_field_type swq_expr_node::Check(swq_field_list *poFieldList)

{
/* -------------------------------------------------------------------- */
/*      If something is a string constant, we must check if it is       */
/*      actually a reference to a field in which case we will           */
/*      convert it into a column type.                                  */
/* -------------------------------------------------------------------- */
    if (eNodeType == SNT_CONSTANT && field_type == SWQ_STRING)
    {
        int            wrk_field_index, wrk_table_index;
        swq_field_type wrk_field_type;

        wrk_field_index =
            swq_identify_field(string_value, poFieldList,
                               &wrk_field_type, &wrk_table_index);

        if (wrk_field_index >= 0)
        {
            eNodeType   = SNT_COLUMN;
            field_index = -1;
            table_index = -1;
        }
    }

/* -------------------------------------------------------------------- */
/*      Otherwise we take constants literally.                          */
/* -------------------------------------------------------------------- */
    if (eNodeType == SNT_CONSTANT)
        return field_type;

/* -------------------------------------------------------------------- */
/*      If this is intended to be a field definition, but has not       */
/*      yet been looked up, we do so now.                               */
/* -------------------------------------------------------------------- */
    if (eNodeType == SNT_COLUMN && field_index == -1)
    {
        field_index =
            swq_identify_field(string_value, poFieldList,
                               &field_type, &table_index);

        if (field_index < 0)
        {
            CPLError(CE_Failure, CPLE_AppDefined,
                     "'%s' not recognised as an available field.",
                     string_value);

            return SWQ_ERROR;
        }
    }

    if (eNodeType == SNT_COLUMN)
        return field_type;

/* -------------------------------------------------------------------- */
/*      We are dealing with an operation - fetch the definition.        */
/* -------------------------------------------------------------------- */
    const swq_operation *poOp =
        swq_op_registrar::GetOperator((swq_op)nOperation);

    if (poOp == NULL)
    {
        CPLError(CE_Failure, CPLE_AppDefined,
                 "Check(): Unable to find definition for operator %d.",
                 nOperation);
        return SWQ_ERROR;
    }

/* -------------------------------------------------------------------- */
/*      Check subexpressions first.                                     */
/* -------------------------------------------------------------------- */
    int i;

    for (i = 0; i < nSubExprCount; i++)
    {
        if (papoSubExpr[i]->Check(poFieldList) == SWQ_ERROR)
            return SWQ_ERROR;
    }

/* -------------------------------------------------------------------- */
/*      Check this node.                                                */
/* -------------------------------------------------------------------- */
    field_type = poOp->pfnChecker(this);

    return field_type;
}