📄 swq.c
字号:
/******************************************************************************
*
* Component: OGDI Driver Support Library
* Purpose: Generic SQL WHERE Expression Implementation.
* Author: Frank Warmerdam <warmerdam@pobox.com>
*
******************************************************************************
* Copyright (C) 2001 Information Interoperability Institute (3i)
*
* Permission to use, copy, modify and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appear in all copies, that
* both the copyright notice and this permission notice appear in
* supporting documentation, and that the name of 3i not be used
* in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. 3i makes no
* representations about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "swq.h"
#ifndef SWQ_MALLOC
#define SWQ_MALLOC(x) malloc(x)
#define SWQ_FREE(x) free(x)
#endif
#ifdef _MSC_VER
# define FORCE_CDECL __cdecl
#else
# define FORCE_CDECL
#endif
#ifndef TRUE
# define TRUE 1
#endif
#ifndef FALSE
# define FALSE 0
#endif
#if defined(_WIN32) && !defined(_WIN32_WCE)
# define strcasecmp stricmp
#elif defined(_WIN32_WCE)
# define strcasecmp _stricmp
#endif
static char swq_error[1024];
#define SWQ_OP_IS_LOGICAL(op) ((op) == SWQ_OR || (op) == SWQ_AND || (op) == SWQ_NOT)
#define SWQ_OP_IS_POSTUNARY(op) ((op) == SWQ_ISNULL || (op) == SWQ_ISNOTNULL)
/************************************************************************/
/* swq_free() */
/************************************************************************/
void swq_free( void *pMemory )
{
SWQ_FREE( pMemory );
}
/************************************************************************/
/* swq_malloc() */
/************************************************************************/
void *swq_malloc( int nSize )
{
return SWQ_MALLOC(nSize);
}
/************************************************************************/
/* swq_realloc() */
/************************************************************************/
void *swq_realloc( void *old_mem, int old_size, int new_size )
{
void *new_mem;
new_mem = swq_malloc( new_size );
if( old_mem != NULL )
{
memcpy( new_mem, old_mem, old_size < new_size ? old_size : new_size);
SWQ_FREE( old_mem );
}
if (old_size <= new_size )
memset( ((char *) new_mem) + old_size, 0, new_size - old_size );
return new_mem;
}
/************************************************************************/
/* swq_isalphanum() */
/* */
/* Is the passed character in the set of things that could */
/* occur in an alphanumeric token, or a number? */
/************************************************************************/
static int swq_isalphanum( char c )
{
if( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
|| (c >= '0' && c <= '9') || c == '.' || c == '+' || c == '-'
|| c == '_' || c == '*' )
return TRUE;
else
return FALSE;
}
/************************************************************************/
/* swq_token() */
/************************************************************************/
static char *swq_token( const char *expression, char **next, int *is_literal )
{
char *token;
int i_token;
if( is_literal != NULL )
*is_literal = 0;
while( *expression == ' ' || *expression == '\t'
|| *expression == 10 || *expression == 13 )
expression++;
if( *expression == '\0' )
{
*next = (char *) expression;
return NULL;
}
/* -------------------------------------------------------------------- */
/* Handle string constants. */
/* -------------------------------------------------------------------- */
if( *expression == '"' || *expression == '\'' )
{
expression++;
token = (char *) SWQ_MALLOC(strlen(expression)+1);
i_token = 0;
while( *expression != '\0' )
{
if( *expression == '\\' && expression[1] == '"' )
expression++;
else if( *expression == '\\' && expression[1] == '\'' )
expression++;
else if( *expression == '"' )
{
expression++;
break;
}
else if( *expression == '\'' )
{
expression++;
break;
}
token[i_token++] = *(expression++);
}
token[i_token] = '\0';
if( is_literal != NULL )
*is_literal = 1;
}
/* -------------------------------------------------------------------- */
/* Handle alpha-numerics. */
/* -------------------------------------------------------------------- */
else if( swq_isalphanum( *expression ) )
{
token = (char *) SWQ_MALLOC(strlen(expression)+1);
i_token = 0;
while( swq_isalphanum( *expression ) )
{
token[i_token++] = *(expression++);
}
token[i_token] = '\0';
}
/* -------------------------------------------------------------------- */
/* Handle special tokens. */
/* -------------------------------------------------------------------- */
else
{
token = (char *) SWQ_MALLOC(3);
token[0] = *expression;
token[1] = '\0';
expression++;
/* special logic to group stuff like '>=' into one token. */
if( (*token == '<' || *token == '>' || *token == '=' || *token == '!')
&& (*expression == '<' || *expression == '>' || *expression == '='))
{
token[1] = *expression;
token[2] = '\0';
expression++;
}
}
*next = (char *) expression;
return token;
}
/************************************************************************/
/* swq_strdup() */
/************************************************************************/
static char *swq_strdup( const char *input )
{
char *result;
result = (char *) SWQ_MALLOC(strlen(input)+1);
strcpy( result, input );
return result;
}
/************************************************************************/
/* ==================================================================== */
/* WHERE clause parsing */
/* ==================================================================== */
/************************************************************************/
/************************************************************************/
/* swq_test_like() */
/* */
/* Does input match pattern? */
/************************************************************************/
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_identify_op() */
/************************************************************************/
static swq_op swq_identify_op( char **tokens, int *tokens_consumed )
{
const char *token = tokens[*tokens_consumed];
if( strcasecmp(token,"OR") == 0 )
return SWQ_OR;
if( strcasecmp(token,"AND") == 0 )
return SWQ_AND;
if( strcasecmp(token,"NOT") == 0 )
{
if( tokens[*tokens_consumed+1] != NULL
&& (strcasecmp(tokens[*tokens_consumed+1],"LIKE") == 0
|| strcasecmp(tokens[*tokens_consumed+1],"ILIKE") == 0) )
{
*tokens_consumed += 1;
return SWQ_NOTLIKE;
}
else if( tokens[*tokens_consumed+1] != NULL
&& strcasecmp(tokens[*tokens_consumed+1],"IN") == 0 )
{
*tokens_consumed += 1;
return SWQ_NOTIN;
}
else
return SWQ_NOT;
}
if( strcasecmp(token,"<=") == 0 )
return SWQ_LE;
if( strcasecmp(token,">=") == 0 )
return SWQ_GE;
if( strcasecmp(token,"=") == 0 )
return SWQ_EQ;
if( strcasecmp(token,"!=") == 0 )
return SWQ_NE;
if( strcasecmp(token,"<>") == 0 )
return SWQ_NE;
if( strcasecmp(token,"<") == 0 )
return SWQ_LT;
if( strcasecmp(token,">") == 0 )
return SWQ_GT;
if( strcasecmp(token,"LIKE") == 0 )
return SWQ_LIKE;
if( strcasecmp(token,"ILIKE") == 0 )
return SWQ_LIKE;
if( strcasecmp(token,"IN") == 0 )
return SWQ_IN;
if( strcasecmp(token,"IS") == 0 )
{
if( tokens[*tokens_consumed+1] == NULL )
return SWQ_UNKNOWN;
else if( strcasecmp(tokens[*tokens_consumed+1],"NULL") == 0 )
{
*tokens_consumed += 1;
return SWQ_ISNULL;
}
else if( strcasecmp(tokens[*tokens_consumed+1],"NOT") == 0
&& tokens[*tokens_consumed+2] != NULL
&& strcasecmp(tokens[*tokens_consumed+2],"NULL") == 0 )
{
*tokens_consumed += 2;
return SWQ_ISNOTNULL;
}
else
return SWQ_UNKNOWN;
}
return SWQ_UNKNOWN;
}
/************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -