int swq_test_like( const char *input, const char *pattern ) { if( input == NULL || pattern == NULL ) return 0; while( *input != '\0' ) { if( *pattern == '\0' ) return 0; else if( *pattern == '_' ) { input++; pattern++; } else if( *pattern == '%' ) { int eat; if( pattern[1] == '\0' ) return 1; /* try eating varying amounts of the input till we get a positive*/ for( eat = 0; input[eat] != '\0'; eat++ ) { if( swq_test_like(input+eat,pattern+1) ) return 1; } return 0; } else { if( tolower(*pattern) != tolower(*input) ) return 0; else { input++; pattern++; } } } if( *pattern != '\0' && strcmp(pattern,"%") != 0 ) return 0; else return 1; }
swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node, swq_expr_node **sub_node_values ) { swq_expr_node *poRet = NULL; /* -------------------------------------------------------------------- */ /* Floating point operations. */ /* -------------------------------------------------------------------- */ if( sub_node_values[0]->field_type == SWQ_FLOAT || (node->nSubExprCount > 1 && sub_node_values[1]->field_type == SWQ_FLOAT) ) { poRet = new swq_expr_node(0); poRet->field_type = node->field_type; if( sub_node_values[0]->field_type == SWQ_INTEGER ) sub_node_values[0]->float_value = sub_node_values[0]->int_value; if( node->nSubExprCount > 1 && sub_node_values[1]->field_type == SWQ_INTEGER ) sub_node_values[1]->float_value = sub_node_values[1]->int_value; switch( (swq_op) node->nOperation ) { case SWQ_EQ: poRet->int_value = sub_node_values[0]->float_value == sub_node_values[1]->float_value; break; case SWQ_NE: poRet->int_value = sub_node_values[0]->float_value != sub_node_values[1]->float_value; break; case SWQ_GT: poRet->int_value = sub_node_values[0]->float_value > sub_node_values[1]->float_value; break; case SWQ_LT: poRet->int_value = sub_node_values[0]->float_value < sub_node_values[1]->float_value; break; case SWQ_GE: poRet->int_value = sub_node_values[0]->float_value >= sub_node_values[1]->float_value; break; case SWQ_LE: poRet->int_value = sub_node_values[0]->float_value <= sub_node_values[1]->float_value; break; case SWQ_IN: { int i; poRet->int_value = 0; for( i = 1; i < node->nSubExprCount; i++ ) { if( sub_node_values[0]->float_value == sub_node_values[i]->float_value ) { poRet->int_value = 1; break; } } } break; case SWQ_BETWEEN: poRet->int_value = sub_node_values[0]->float_value >= sub_node_values[1]->float_value && sub_node_values[0]->float_value <= sub_node_values[2]->float_value; break; case SWQ_ISNULL: poRet->int_value = sub_node_values[0]->is_null; break; case SWQ_ADD: poRet->float_value = sub_node_values[0]->float_value + sub_node_values[1]->float_value; break; case SWQ_SUBTRACT: poRet->float_value = sub_node_values[0]->float_value - sub_node_values[1]->float_value; break; case SWQ_MULTIPLY: poRet->float_value = sub_node_values[0]->float_value * sub_node_values[1]->float_value; break; case SWQ_DIVIDE: if( sub_node_values[1]->float_value == 0 ) poRet->float_value = INT_MAX; else poRet->float_value = sub_node_values[0]->float_value / sub_node_values[1]->float_value; break; case SWQ_MODULUS: { int nRight = (int) sub_node_values[1]->float_value; poRet->field_type = SWQ_INTEGER; if (nRight == 0) poRet->int_value = INT_MAX; else poRet->int_value = ((int) sub_node_values[0]->float_value) % nRight; break; } default: CPLAssert( FALSE ); delete poRet; poRet = NULL; break; } } /* -------------------------------------------------------------------- */ /* integer/boolean operations. */ /* -------------------------------------------------------------------- */ else if( sub_node_values[0]->field_type == SWQ_INTEGER || sub_node_values[0]->field_type == SWQ_BOOLEAN ) { poRet = new swq_expr_node(0); poRet->field_type = node->field_type; switch( (swq_op) node->nOperation ) { case SWQ_AND: poRet->int_value = sub_node_values[0]->int_value && sub_node_values[1]->int_value; break; case SWQ_OR: poRet->int_value = sub_node_values[0]->int_value || sub_node_values[1]->int_value; break; case SWQ_NOT: poRet->int_value = !sub_node_values[0]->int_value; break; case SWQ_EQ: poRet->int_value = sub_node_values[0]->int_value == sub_node_values[1]->int_value; break; case SWQ_NE: poRet->int_value = sub_node_values[0]->int_value != sub_node_values[1]->int_value; break; case SWQ_GT: poRet->int_value = sub_node_values[0]->int_value > sub_node_values[1]->int_value; break; case SWQ_LT: poRet->int_value = sub_node_values[0]->int_value < sub_node_values[1]->int_value; break; case SWQ_GE: poRet->int_value = sub_node_values[0]->int_value >= sub_node_values[1]->int_value; break; case SWQ_LE: poRet->int_value = sub_node_values[0]->int_value <= sub_node_values[1]->int_value; break; case SWQ_IN: { int i; poRet->int_value = 0; for( i = 1; i < node->nSubExprCount; i++ ) { if( sub_node_values[0]->int_value == sub_node_values[i]->int_value ) { poRet->int_value = 1; break; } } } break; case SWQ_BETWEEN: poRet->int_value = sub_node_values[0]->int_value >= sub_node_values[1]->int_value && sub_node_values[0]->int_value <= sub_node_values[2]->int_value; break; case SWQ_ISNULL: poRet->int_value = sub_node_values[0]->is_null; break; case SWQ_ADD: poRet->int_value = sub_node_values[0]->int_value + sub_node_values[1]->int_value; break; case SWQ_SUBTRACT: poRet->int_value = sub_node_values[0]->int_value - sub_node_values[1]->int_value; break; case SWQ_MULTIPLY: poRet->int_value = sub_node_values[0]->int_value * sub_node_values[1]->int_value; break; case SWQ_DIVIDE: if( sub_node_values[1]->int_value == 0 ) poRet->int_value = INT_MAX; else poRet->int_value = sub_node_values[0]->int_value / sub_node_values[1]->int_value; break; case SWQ_MODULUS: if( sub_node_values[1]->int_value == 0 ) poRet->int_value = INT_MAX; else poRet->int_value = sub_node_values[0]->int_value % sub_node_values[1]->int_value; break; default: CPLAssert( FALSE ); delete poRet; poRet = NULL; break; } } /* -------------------------------------------------------------------- */ /* String operations. */ /* -------------------------------------------------------------------- */ else { poRet = new swq_expr_node(0); poRet->field_type = node->field_type; switch( (swq_op) node->nOperation ) { case SWQ_EQ: poRet->int_value = strcasecmp(sub_node_values[0]->string_value, sub_node_values[1]->string_value) == 0; break; case SWQ_NE: poRet->int_value = strcasecmp(sub_node_values[0]->string_value, sub_node_values[1]->string_value) != 0; break; case SWQ_GT: poRet->int_value = strcasecmp(sub_node_values[0]->string_value, sub_node_values[1]->string_value) > 0; break; case SWQ_LT: poRet->int_value = strcasecmp(sub_node_values[0]->string_value, sub_node_values[1]->string_value) < 0; break; case SWQ_GE: poRet->int_value = strcasecmp(sub_node_values[0]->string_value, sub_node_values[1]->string_value) >= 0; break; case SWQ_LE: poRet->int_value = strcasecmp(sub_node_values[0]->string_value, sub_node_values[1]->string_value) <= 0; break; case SWQ_IN: { int i; poRet->int_value = 0; for( i = 1; i < node->nSubExprCount; i++ ) { if( strcasecmp(sub_node_values[0]->string_value, sub_node_values[i]->string_value) == 0 ) { poRet->int_value = 1; break; } } } break; case SWQ_BETWEEN: poRet->int_value = strcasecmp(sub_node_values[0]->string_value, sub_node_values[1]->string_value) >= 0 && strcasecmp(sub_node_values[0]->string_value, sub_node_values[2]->string_value) <= 0; break; case SWQ_LIKE: poRet->int_value = swq_test_like(sub_node_values[0]->string_value, sub_node_values[1]->string_value); break; case SWQ_ISNULL: poRet->int_value = sub_node_values[0]->is_null; break; case SWQ_CONCAT: case SWQ_ADD: { CPLString osResult = sub_node_values[0]->string_value; int i; for( i = 1; i < node->nSubExprCount; i++ ) osResult += sub_node_values[i]->string_value; poRet->string_value = CPLStrdup(osResult); break; } case SWQ_SUBSTR: { int nOffset, nSize; const char *pszSrcStr = sub_node_values[0]->string_value; if( sub_node_values[1]->field_type == SWQ_INTEGER ) nOffset = sub_node_values[1]->int_value; else if( sub_node_values[1]->field_type == SWQ_FLOAT ) nOffset = (int) sub_node_values[1]->float_value; else nOffset = 0; if( node->nSubExprCount < 3 ) nSize = 100000; else if( sub_node_values[2]->field_type == SWQ_INTEGER ) nSize = sub_node_values[2]->int_value; else if( sub_node_values[2]->field_type == SWQ_FLOAT ) nSize = (int) sub_node_values[2]->float_value; else nSize = 0; int nSrcStrLen = (int)strlen(pszSrcStr); if( nOffset < 0 || nSize < 0 || nOffset > nSrcStrLen ) { nOffset = 0; nSize = 0; } else if( nOffset + nSize > nSrcStrLen ) nSize = nSrcStrLen - nOffset; CPLString osResult = pszSrcStr + nOffset; if( (int)osResult.size() > nSize ) osResult.resize( nSize ); poRet->string_value = CPLStrdup(osResult); break; } default: CPLAssert( FALSE ); delete poRet; poRet = NULL; break; } } return poRet; }
swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node, swq_expr_node **sub_node_values ) { swq_expr_node *poRet = NULL; /* -------------------------------------------------------------------- */ /* Floating point operations. */ /* -------------------------------------------------------------------- */ if( sub_node_values[0]->field_type == SWQ_FLOAT || (node->nSubExprCount > 1 && sub_node_values[1]->field_type == SWQ_FLOAT) ) { poRet = new swq_expr_node(0); poRet->field_type = node->field_type; if( SWQ_IS_INTEGER(sub_node_values[0]->field_type) ) sub_node_values[0]->float_value = (double) sub_node_values[0]->int_value; if( node->nSubExprCount > 1 && SWQ_IS_INTEGER(sub_node_values[1]->field_type) ) sub_node_values[1]->float_value = (double)sub_node_values[1]->int_value; if( node->nOperation != SWQ_ISNULL ) { for( int i = 0; i < node->nSubExprCount; i++ ) { if( sub_node_values[i]->is_null ) { if( poRet->field_type == SWQ_BOOLEAN ) { poRet->int_value = FALSE; return poRet; } else if( poRet->field_type == SWQ_FLOAT ) { poRet->float_value = 0; poRet->is_null = 1; return poRet; } else if( SWQ_IS_INTEGER(poRet->field_type) || node->nOperation == SWQ_MODULUS ) { poRet->field_type = SWQ_INTEGER; poRet->int_value = 0; poRet->is_null = 1; return poRet; } } } } switch( (swq_op) node->nOperation ) { case SWQ_EQ: poRet->int_value = sub_node_values[0]->float_value == sub_node_values[1]->float_value; break; case SWQ_NE: poRet->int_value = sub_node_values[0]->float_value != sub_node_values[1]->float_value; break; case SWQ_GT: poRet->int_value = sub_node_values[0]->float_value > sub_node_values[1]->float_value; break; case SWQ_LT: poRet->int_value = sub_node_values[0]->float_value < sub_node_values[1]->float_value; break; case SWQ_GE: poRet->int_value = sub_node_values[0]->float_value >= sub_node_values[1]->float_value; break; case SWQ_LE: poRet->int_value = sub_node_values[0]->float_value <= sub_node_values[1]->float_value; break; case SWQ_IN: { poRet->int_value = 0; for( int i = 1; i < node->nSubExprCount; i++ ) { if( sub_node_values[0]->float_value == sub_node_values[i]->float_value ) { poRet->int_value = 1; break; } } } break; case SWQ_BETWEEN: poRet->int_value = sub_node_values[0]->float_value >= sub_node_values[1]->float_value && sub_node_values[0]->float_value <= sub_node_values[2]->float_value; break; case SWQ_ISNULL: poRet->int_value = sub_node_values[0]->is_null; break; case SWQ_ADD: poRet->float_value = sub_node_values[0]->float_value + sub_node_values[1]->float_value; break; case SWQ_SUBTRACT: poRet->float_value = sub_node_values[0]->float_value - sub_node_values[1]->float_value; break; case SWQ_MULTIPLY: poRet->float_value = sub_node_values[0]->float_value * sub_node_values[1]->float_value; break; case SWQ_DIVIDE: if( sub_node_values[1]->float_value == 0 ) poRet->float_value = INT_MAX; else poRet->float_value = sub_node_values[0]->float_value / sub_node_values[1]->float_value; break; case SWQ_MODULUS: { GIntBig nRight = (GIntBig) sub_node_values[1]->float_value; poRet->field_type = SWQ_INTEGER; if (nRight == 0) poRet->int_value = INT_MAX; else poRet->int_value = ((GIntBig) sub_node_values[0]->float_value) % nRight; break; } default: CPLAssert( false ); delete poRet; poRet = NULL; break; } } /* -------------------------------------------------------------------- */ /* integer/boolean operations. */ /* -------------------------------------------------------------------- */ else if( SWQ_IS_INTEGER(sub_node_values[0]->field_type) || sub_node_values[0]->field_type == SWQ_BOOLEAN ) { poRet = new swq_expr_node(0); poRet->field_type = node->field_type; if( node->nOperation != SWQ_ISNULL ) { for( int i = 0; i < node->nSubExprCount; i++ ) { if( sub_node_values[i]->is_null ) { if( poRet->field_type == SWQ_BOOLEAN ) { poRet->int_value = FALSE; return poRet; } else if( SWQ_IS_INTEGER(poRet->field_type) ) { poRet->int_value = 0; poRet->is_null = 1; return poRet; } } } } switch( (swq_op) node->nOperation ) { case SWQ_AND: poRet->int_value = sub_node_values[0]->int_value && sub_node_values[1]->int_value; break; case SWQ_OR: poRet->int_value = sub_node_values[0]->int_value || sub_node_values[1]->int_value; break; case SWQ_NOT: poRet->int_value = !sub_node_values[0]->int_value; break; case SWQ_EQ: poRet->int_value = sub_node_values[0]->int_value == sub_node_values[1]->int_value; break; case SWQ_NE: poRet->int_value = sub_node_values[0]->int_value != sub_node_values[1]->int_value; break; case SWQ_GT: poRet->int_value = sub_node_values[0]->int_value > sub_node_values[1]->int_value; break; case SWQ_LT: poRet->int_value = sub_node_values[0]->int_value < sub_node_values[1]->int_value; break; case SWQ_GE: poRet->int_value = sub_node_values[0]->int_value >= sub_node_values[1]->int_value; break; case SWQ_LE: poRet->int_value = sub_node_values[0]->int_value <= sub_node_values[1]->int_value; break; case SWQ_IN: { poRet->int_value = 0; for( int i = 1; i < node->nSubExprCount; i++ ) { if( sub_node_values[0]->int_value == sub_node_values[i]->int_value ) { poRet->int_value = 1; break; } } } break; case SWQ_BETWEEN: poRet->int_value = sub_node_values[0]->int_value >= sub_node_values[1]->int_value && sub_node_values[0]->int_value <= sub_node_values[2]->int_value; break; case SWQ_ISNULL: poRet->int_value = sub_node_values[0]->is_null; break; case SWQ_ADD: poRet->int_value = sub_node_values[0]->int_value + sub_node_values[1]->int_value; break; case SWQ_SUBTRACT: poRet->int_value = sub_node_values[0]->int_value - sub_node_values[1]->int_value; break; case SWQ_MULTIPLY: poRet->int_value = sub_node_values[0]->int_value * sub_node_values[1]->int_value; break; case SWQ_DIVIDE: if( sub_node_values[1]->int_value == 0 ) poRet->int_value = INT_MAX; else poRet->int_value = sub_node_values[0]->int_value / sub_node_values[1]->int_value; break; case SWQ_MODULUS: if( sub_node_values[1]->int_value == 0 ) poRet->int_value = INT_MAX; else poRet->int_value = sub_node_values[0]->int_value % sub_node_values[1]->int_value; break; default: CPLAssert( false ); delete poRet; poRet = NULL; break; } } /* -------------------------------------------------------------------- */ /* String operations. */ /* -------------------------------------------------------------------- */ else { poRet = new swq_expr_node(0); poRet->field_type = node->field_type; if( node->nOperation != SWQ_ISNULL ) { for( int i = 0; i < node->nSubExprCount; i++ ) { if( sub_node_values[i]->is_null ) { if( poRet->field_type == SWQ_BOOLEAN ) { poRet->int_value = FALSE; return poRet; } else if( poRet->field_type == SWQ_STRING ) { poRet->string_value = CPLStrdup(""); poRet->is_null = 1; return poRet; } } } } switch( (swq_op) node->nOperation ) { case SWQ_EQ: { /* When comparing timestamps, the +00 at the end might be discarded */ /* if the other member has no explicit timezone */ if( (sub_node_values[0]->field_type == SWQ_TIMESTAMP || sub_node_values[0]->field_type == SWQ_STRING) && (sub_node_values[1]->field_type == SWQ_TIMESTAMP || sub_node_values[1]->field_type == SWQ_STRING) && strlen(sub_node_values[0]->string_value) > 3 && strlen(sub_node_values[1]->string_value) > 3 && (strcmp(sub_node_values[0]->string_value + strlen(sub_node_values[0]->string_value)-3, "+00") == 0 && sub_node_values[1]->string_value[strlen(sub_node_values[1]->string_value)-3] == ':') ) { poRet->int_value = EQUALN(sub_node_values[0]->string_value, sub_node_values[1]->string_value, strlen(sub_node_values[1]->string_value)); } else if( (sub_node_values[0]->field_type == SWQ_TIMESTAMP || sub_node_values[0]->field_type == SWQ_STRING) && (sub_node_values[1]->field_type == SWQ_TIMESTAMP || sub_node_values[1]->field_type == SWQ_STRING) && strlen(sub_node_values[0]->string_value) > 3 && strlen(sub_node_values[1]->string_value) > 3 && (sub_node_values[0]->string_value[strlen(sub_node_values[0]->string_value)-3] == ':') && strcmp(sub_node_values[1]->string_value + strlen(sub_node_values[1]->string_value)-3, "+00") == 0) { poRet->int_value = EQUALN(sub_node_values[0]->string_value, sub_node_values[1]->string_value, strlen(sub_node_values[0]->string_value)); } else { poRet->int_value = strcasecmp(sub_node_values[0]->string_value, sub_node_values[1]->string_value) == 0; } break; } case SWQ_NE: poRet->int_value = strcasecmp(sub_node_values[0]->string_value, sub_node_values[1]->string_value) != 0; break; case SWQ_GT: poRet->int_value = strcasecmp(sub_node_values[0]->string_value, sub_node_values[1]->string_value) > 0; break; case SWQ_LT: poRet->int_value = strcasecmp(sub_node_values[0]->string_value, sub_node_values[1]->string_value) < 0; break; case SWQ_GE: poRet->int_value = strcasecmp(sub_node_values[0]->string_value, sub_node_values[1]->string_value) >= 0; break; case SWQ_LE: poRet->int_value = strcasecmp(sub_node_values[0]->string_value, sub_node_values[1]->string_value) <= 0; break; case SWQ_IN: { poRet->int_value = 0; for( int i = 1; i < node->nSubExprCount; i++ ) { if( strcasecmp(sub_node_values[0]->string_value, sub_node_values[i]->string_value) == 0 ) { poRet->int_value = 1; break; } } } break; case SWQ_BETWEEN: poRet->int_value = strcasecmp(sub_node_values[0]->string_value, sub_node_values[1]->string_value) >= 0 && strcasecmp(sub_node_values[0]->string_value, sub_node_values[2]->string_value) <= 0; break; case SWQ_LIKE: { char chEscape = '\0'; if( node->nSubExprCount == 3 ) chEscape = sub_node_values[2]->string_value[0]; poRet->int_value = swq_test_like(sub_node_values[0]->string_value, sub_node_values[1]->string_value, chEscape); break; } case SWQ_ISNULL: poRet->int_value = sub_node_values[0]->is_null; break; case SWQ_CONCAT: case SWQ_ADD: { CPLString osResult = sub_node_values[0]->string_value; for( int i = 1; i < node->nSubExprCount; i++ ) osResult += sub_node_values[i]->string_value; poRet->string_value = CPLStrdup(osResult); poRet->is_null = sub_node_values[0]->is_null; break; } case SWQ_SUBSTR: { int nOffset, nSize; const char *pszSrcStr = sub_node_values[0]->string_value; if( SWQ_IS_INTEGER(sub_node_values[1]->field_type) ) nOffset = (int)sub_node_values[1]->int_value; else if( sub_node_values[1]->field_type == SWQ_FLOAT ) nOffset = (int) sub_node_values[1]->float_value; else nOffset = 0; if( node->nSubExprCount < 3 ) nSize = 100000; else if( SWQ_IS_INTEGER(sub_node_values[2]->field_type) ) nSize = (int)sub_node_values[2]->int_value; else if( sub_node_values[2]->field_type == SWQ_FLOAT ) nSize = (int) sub_node_values[2]->float_value; else nSize = 0; int nSrcStrLen = (int)strlen(pszSrcStr); /* In SQL, the first character is at offset 1 */ /* And 0 is considered as 1 */ if (nOffset > 0) nOffset --; /* Some implementations allow negative offsets, to start */ /* from the end of the string */ else if( nOffset < 0 ) { if( nSrcStrLen + nOffset >= 0 ) nOffset = nSrcStrLen + nOffset; else nOffset = 0; } if( nSize < 0 || nOffset > nSrcStrLen ) { nOffset = 0; nSize = 0; } else if( nOffset + nSize > nSrcStrLen ) nSize = nSrcStrLen - nOffset; CPLString osResult = pszSrcStr + nOffset; if( (int)osResult.size() > nSize ) osResult.resize( nSize ); poRet->string_value = CPLStrdup(osResult); poRet->is_null = sub_node_values[0]->is_null; break; } case SWQ_HSTORE_GET_VALUE: { const char *pszHStore = sub_node_values[0]->string_value; const char *pszSearchedKey = sub_node_values[1]->string_value; char* pszRet = OGRHStoreGetValue(pszHStore, pszSearchedKey); poRet->string_value = pszRet ? pszRet : CPLStrdup(""); poRet->is_null = (pszRet == NULL); break; } default: CPLAssert( false ); delete poRet; poRet = NULL; break; } } return poRet; }