Example #1
0
swq_field_type SWQGeneralChecker( swq_expr_node *poNode,
                                  int bAllowMismatchTypeOnFieldComparison  )

{
    swq_field_type eRetType = SWQ_ERROR;
    swq_field_type eArgType = SWQ_OTHER;
    // int nArgCount = -1;

    switch( (swq_op) poNode->nOperation )
    {
      case SWQ_AND:
      case SWQ_OR:
      case SWQ_NOT:
        if( !SWQCheckSubExprAreNotGeometries(poNode) )
            return SWQ_ERROR;
        eRetType = SWQ_BOOLEAN;
        break;

      case SWQ_EQ:
      case SWQ_NE:
      case SWQ_GT:
      case SWQ_LT:
      case SWQ_GE:
      case SWQ_LE:
      case SWQ_IN:
      case SWQ_BETWEEN:
        if( !SWQCheckSubExprAreNotGeometries(poNode) )
            return SWQ_ERROR;
        eRetType = SWQ_BOOLEAN;
        SWQAutoConvertStringToNumeric( poNode );
        SWQAutoPromoteIntegerToInteger64OrFloat( poNode );
        SWQAutoPromoteStringToDateTime( poNode );
        eArgType = poNode->papoSubExpr[0]->field_type;
        break;

      case SWQ_ISNULL:
        eRetType = SWQ_BOOLEAN;
        break;

      case SWQ_LIKE:
        if( !SWQCheckSubExprAreNotGeometries(poNode) )
            return SWQ_ERROR;
        eRetType = SWQ_BOOLEAN;
        eArgType = SWQ_STRING;
        break;

      case SWQ_MODULUS:
        if( !SWQCheckSubExprAreNotGeometries(poNode) )
            return SWQ_ERROR;
        eRetType = SWQ_INTEGER;
        eArgType = SWQ_INTEGER;
        break;

      case SWQ_ADD:
        if( !SWQCheckSubExprAreNotGeometries(poNode) )
            return SWQ_ERROR;
        SWQAutoPromoteIntegerToInteger64OrFloat( poNode );
        if( poNode->papoSubExpr[0]->field_type == SWQ_STRING )
            eRetType = eArgType = SWQ_STRING;
        else if( poNode->papoSubExpr[0]->field_type == SWQ_FLOAT )
            eRetType = eArgType = SWQ_FLOAT;
        else if( poNode->papoSubExpr[0]->field_type == SWQ_INTEGER64 )
            eRetType = eArgType = SWQ_INTEGER64;
        else
            eRetType = eArgType = SWQ_INTEGER;
        break;

      case SWQ_SUBTRACT:
      case SWQ_MULTIPLY:
      case SWQ_DIVIDE:
        if( !SWQCheckSubExprAreNotGeometries(poNode) )
            return SWQ_ERROR;
        SWQAutoPromoteIntegerToInteger64OrFloat( poNode );
        if( poNode->papoSubExpr[0]->field_type == SWQ_FLOAT )
            eRetType = eArgType = SWQ_FLOAT;
        else if( poNode->papoSubExpr[0]->field_type == SWQ_INTEGER64 )
            eRetType = eArgType = SWQ_INTEGER64;
        else
            eRetType = eArgType = SWQ_INTEGER;
        break;

      case SWQ_CONCAT:
        if( !SWQCheckSubExprAreNotGeometries(poNode) )
            return SWQ_ERROR;
        eRetType = SWQ_STRING;
        eArgType = SWQ_STRING;
        break;

      case SWQ_SUBSTR:
        if( !SWQCheckSubExprAreNotGeometries(poNode) )
            return SWQ_ERROR;
        eRetType = SWQ_STRING;
        if( poNode->nSubExprCount > 3 || poNode->nSubExprCount < 2 )
        {
            CPLError( CE_Failure, CPLE_AppDefined,
                      "Expected 2 or 3 arguments to SUBSTR(), but got %d.",
                      poNode->nSubExprCount );
            return SWQ_ERROR;
        }
        if( poNode->papoSubExpr[0]->field_type != SWQ_STRING
            || poNode->papoSubExpr[1]->field_type != SWQ_INTEGER
            || (poNode->nSubExprCount > 2
                && poNode->papoSubExpr[2]->field_type != SWQ_INTEGER) )
        {
            CPLError( CE_Failure, CPLE_AppDefined,
                      "Wrong argument type for SUBSTR(), expected SUBSTR(string,int,int) or SUBSTR(string,int)." );
            return SWQ_ERROR;
        }
        break;

      case SWQ_HSTORE_GET_VALUE:
        if( !SWQCheckSubExprAreNotGeometries(poNode) )
            return SWQ_ERROR;
        eRetType = SWQ_STRING;
        if( poNode->nSubExprCount != 2 )
        {
            CPLError( CE_Failure, CPLE_AppDefined,
                      "Expected 2 arguments to hstore_get_value(), but got %d.",
                      poNode->nSubExprCount );
            return SWQ_ERROR;
        }
        if( poNode->papoSubExpr[0]->field_type != SWQ_STRING
            || poNode->papoSubExpr[1]->field_type != SWQ_STRING )
        {
            CPLError( CE_Failure, CPLE_AppDefined,
                      "Wrong argument type for hstore_get_value(), expected hstore_get_value(string,string)." );
            return SWQ_ERROR;
        }
        break;

      default:
      {
          const swq_operation *poOp =
              swq_op_registrar::GetOperator((swq_op)poNode->nOperation);

          CPLError( CE_Failure, CPLE_AppDefined,
                    "SWQGeneralChecker() called on unsupported operation %s.",
                    poOp->pszName);
          return SWQ_ERROR;
      }
    }
/* -------------------------------------------------------------------- */
/*      Check argument types.                                           */
/* -------------------------------------------------------------------- */
    if( eArgType != SWQ_OTHER )
    {
        if( SWQ_IS_INTEGER(eArgType) || eArgType == SWQ_BOOLEAN )
            eArgType = SWQ_FLOAT;

        for( int i = 0; i < poNode->nSubExprCount; i++ )
        {
            swq_field_type eThisArgType = poNode->papoSubExpr[i]->field_type;
            if( SWQ_IS_INTEGER(eThisArgType) ||  eThisArgType == SWQ_BOOLEAN )
                eThisArgType = SWQ_FLOAT;

            if( eArgType != eThisArgType )
            {
                // Convenience for join. We allow comparing numeric columns
                // and string columns, by casting string columns to numeric
                if( bAllowMismatchTypeOnFieldComparison &&
                    poNode->nSubExprCount == 2 &&
                    poNode->nOperation == SWQ_EQ &&
                    poNode->papoSubExpr[0]->eNodeType == SNT_COLUMN &&
                    poNode->papoSubExpr[i]->eNodeType == SNT_COLUMN &&
                    eArgType == SWQ_FLOAT && eThisArgType == SWQ_STRING )
                {
                    swq_expr_node* poNewNode = new swq_expr_node(SWQ_CAST);
                    poNewNode->PushSubExpression(poNode->papoSubExpr[i]);
                    poNewNode->PushSubExpression(new swq_expr_node("FLOAT"));
                    SWQCastChecker(poNewNode, FALSE);
                    poNode->papoSubExpr[i] = poNewNode;
                    break;
                }
                if( bAllowMismatchTypeOnFieldComparison &&
                    poNode->nSubExprCount == 2 &&
                    poNode->nOperation == SWQ_EQ &&
                    poNode->papoSubExpr[0]->eNodeType == SNT_COLUMN &&
                    poNode->papoSubExpr[i]->eNodeType == SNT_COLUMN &&
                    eThisArgType == SWQ_FLOAT && eArgType == SWQ_STRING )
                {
                    swq_expr_node* poNewNode = new swq_expr_node(SWQ_CAST);
                    poNewNode->PushSubExpression(poNode->papoSubExpr[0]);
                    poNewNode->PushSubExpression(new swq_expr_node("FLOAT"));
                    SWQCastChecker(poNewNode, FALSE);
                    poNode->papoSubExpr[0] = poNewNode;
                    break;
                }

                const swq_operation *poOp =
                    swq_op_registrar::GetOperator((swq_op)poNode->nOperation);

                CPLError( CE_Failure, CPLE_AppDefined,
                          "Type mismatch or improper type of arguments to %s operator.",
                          poOp->pszName );
                return SWQ_ERROR;
            }
        }
    }

/* -------------------------------------------------------------------- */
/*      Validate the arg count if requested.                            */
/* -------------------------------------------------------------------- */
#if 0
    // nArgCount was always -1, so this block was never executed.
    if( nArgCount != -1
        && nArgCount != poNode->nSubExprCount )
    {
        const swq_operation *poOp =
            swq_op_registrar::GetOperator((swq_op)poNode->nOperation);

        CPLError( CE_Failure, CPLE_AppDefined,
                  "Expected %d arguments to %s, but got %d arguments.",
                  nArgCount,
                  poOp->pszName,
                  poNode->nSubExprCount );
        return SWQ_ERROR;
    }
#endif

    return eRetType;
}
Example #2
0
swq_field_type SWQGeneralChecker( swq_expr_node *poNode )

{									
    swq_field_type eRetType = SWQ_ERROR;
    swq_field_type eArgType = SWQ_OTHER;
    int nArgCount = -1;

    switch( (swq_op) poNode->nOperation )
    {
      case SWQ_AND:
      case SWQ_OR:
      case SWQ_NOT:
        if( !SWQCheckSubExprAreNotGeometries(poNode) )
            return SWQ_ERROR;
        eRetType = SWQ_BOOLEAN;
        break;

      case SWQ_EQ:
      case SWQ_NE:
      case SWQ_GT:
      case SWQ_LT:
      case SWQ_GE:
      case SWQ_LE:
      case SWQ_IN:
      case SWQ_BETWEEN:
        if( !SWQCheckSubExprAreNotGeometries(poNode) )
            return SWQ_ERROR;
        eRetType = SWQ_BOOLEAN;
        SWQAutoConvertStringToNumeric( poNode );
        SWQAutoPromoteIntegerToFloat( poNode );
        SWQAutoPromoteStringToDateTime( poNode );
        eArgType = poNode->papoSubExpr[0]->field_type;
        break;

      case SWQ_ISNULL:
        eRetType = SWQ_BOOLEAN;
        break;

      case SWQ_LIKE:
        if( !SWQCheckSubExprAreNotGeometries(poNode) )
            return SWQ_ERROR;
        eRetType = SWQ_BOOLEAN;
        eArgType = SWQ_STRING;
        break;

      case SWQ_MODULUS:
        if( !SWQCheckSubExprAreNotGeometries(poNode) )
            return SWQ_ERROR;
        eRetType = SWQ_INTEGER;
        eArgType = SWQ_INTEGER;
        break;

      case SWQ_ADD:
        if( !SWQCheckSubExprAreNotGeometries(poNode) )
            return SWQ_ERROR;
        SWQAutoPromoteIntegerToFloat( poNode );
        if( poNode->papoSubExpr[0]->field_type == SWQ_STRING )
            eRetType = eArgType = SWQ_STRING;
        else if( poNode->papoSubExpr[0]->field_type == SWQ_FLOAT )
            eRetType = eArgType = SWQ_FLOAT;
        else
            eRetType = eArgType = SWQ_INTEGER;
        break;

      case SWQ_SUBTRACT:
      case SWQ_MULTIPLY:
      case SWQ_DIVIDE:
        if( !SWQCheckSubExprAreNotGeometries(poNode) )
            return SWQ_ERROR;
        SWQAutoPromoteIntegerToFloat( poNode );
        if( poNode->papoSubExpr[0]->field_type == SWQ_FLOAT )
            eRetType = eArgType = SWQ_FLOAT;
        else
            eRetType = eArgType = SWQ_INTEGER;
        break;

      case SWQ_CONCAT:
        if( !SWQCheckSubExprAreNotGeometries(poNode) )
            return SWQ_ERROR;
        eRetType = SWQ_STRING;
        eArgType = SWQ_STRING;
        break;

      case SWQ_SUBSTR:
        if( !SWQCheckSubExprAreNotGeometries(poNode) )
            return SWQ_ERROR;
        eRetType = SWQ_STRING;
        if( poNode->nSubExprCount > 3 || poNode->nSubExprCount < 2 )
        {
            CPLError( CE_Failure, CPLE_AppDefined, 
                      "Expected 2 or 3 arguments to SUBSTR(), but got %d.",
                      poNode->nSubExprCount );
            return SWQ_ERROR;
        }
        if( poNode->papoSubExpr[0]->field_type != SWQ_STRING 
            || poNode->papoSubExpr[1]->field_type != SWQ_INTEGER
            || (poNode->nSubExprCount > 2 
                && poNode->papoSubExpr[2]->field_type != SWQ_INTEGER) )
        {
            CPLError( CE_Failure, CPLE_AppDefined, 
                      "Wrong argument type for SUBSTR(), expected SUBSTR(string,int,int) or SUBSTR(string,int)." );
            return SWQ_ERROR;
        }
        break;

      case SWQ_HSTORE_GET_VALUE:
        if( !SWQCheckSubExprAreNotGeometries(poNode) )
            return SWQ_ERROR;
        eRetType = SWQ_STRING;
        if( poNode->nSubExprCount != 2 )
        {
            CPLError( CE_Failure, CPLE_AppDefined, 
                      "Expected 2 arguments to hstore_get_value(), but got %d.",
                      poNode->nSubExprCount );
            return SWQ_ERROR;
        }
        if( poNode->papoSubExpr[0]->field_type != SWQ_STRING 
            || poNode->papoSubExpr[1]->field_type != SWQ_STRING )
        {
            CPLError( CE_Failure, CPLE_AppDefined, 
                      "Wrong argument type for hstore_get_value(), expected hstore_get_value(string,string)." );
            return SWQ_ERROR;
        }
        break;
        
      default:
      {
          const swq_operation *poOp = 
              swq_op_registrar::GetOperator((swq_op)poNode->nOperation);
          
          CPLError( CE_Failure, CPLE_AppDefined,
                    "SWQGeneralChecker() called on unsupported operation %s.",
                    poOp->pszName);
          return SWQ_ERROR;
      }
    }
/* -------------------------------------------------------------------- */
/*      Check argument types.                                           */
/* -------------------------------------------------------------------- */
    if( eArgType != SWQ_OTHER )
    {
        int i;

        if( eArgType == SWQ_INTEGER )
            eArgType = SWQ_FLOAT;

        for( i = 0; i < poNode->nSubExprCount; i++ )
        {
            swq_field_type eThisArgType = poNode->papoSubExpr[i]->field_type;
            if( eThisArgType == SWQ_INTEGER )
                eThisArgType = SWQ_FLOAT;

            if( eArgType != eThisArgType )
            {
                const swq_operation *poOp = 
                    swq_op_registrar::GetOperator((swq_op)poNode->nOperation);
                
                CPLError( CE_Failure, CPLE_AppDefined, 
                          "Type mismatch or improper type of arguments to %s operator.",
                          poOp->pszName );
                return SWQ_ERROR;
            }
        }
    }

/* -------------------------------------------------------------------- */
/*      Validate the arg count if requested.                            */
/* -------------------------------------------------------------------- */
    if( nArgCount != -1 
        && nArgCount != poNode->nSubExprCount )
    {
        const swq_operation *poOp = 
            swq_op_registrar::GetOperator((swq_op)poNode->nOperation);
                
        CPLError( CE_Failure, CPLE_AppDefined, 
                  "Expected %d arguments to %s, but got %d arguments.",
                  nArgCount,
                  poOp->pszName,
                  poNode->nSubExprCount );
        return SWQ_ERROR;
    }

    return eRetType;
}