📄 swq.c
字号:
swq_expr_free( op ); return swq_error; } } /* ** Otherwise collect it as a literal value. */ else { op->string_value = swq_strdup(tokens[*tokens_consumed]); op->int_value = atoi(op->string_value); op->float_value = atof(op->string_value); if( op->field_index != -1 && (op->field_type == SWQ_INTEGER || op->field_type == SWQ_FLOAT) && op->string_value[0] != '-' && op->string_value[0] != '+' && op->string_value[0] != '.' && (op->string_value[0] < '0' || op->string_value[0] > '9') ) { /* NOTE: the use of names[] here is wrong. We should be looking up the field that matches op->field_index and op->table_index */ sprintf( swq_error, "Attempt to compare numeric field `%s' to non-numeric" " value `%s' is illegal.", field_list->names[op->field_index], op->string_value ); swq_expr_free( op ); return swq_error; } (*tokens_consumed)++; } *expr_out = op; /* Transform stuff like A NOT LIKE X into NOT (A LIKE X) */ if( op->operation == SWQ_NOTLIKE || op->operation == SWQ_ISNOTNULL || op->operation == SWQ_NOTIN ) { if( op->operation == SWQ_NOTLIKE ) op->operation = SWQ_LIKE; else if( op->operation == SWQ_NOTIN ) op->operation = SWQ_IN; else if( op->operation == SWQ_ISNOTNULL ) op->operation = SWQ_ISNULL; op = (swq_field_op *) SWQ_MALLOC(sizeof(swq_field_op)); memset( op, 0, sizeof(swq_field_op) ); op->field_index = -1; op->second_sub_expr = (struct swq_node_s *) *expr_out; op->operation = SWQ_NOT; *expr_out = op; } op = NULL; /* ** Are we part of an unparantized logical expression chain? If so, ** grab the remainder of the expression at "this level" and add to the ** local tree. */ op_code = SWQ_UNKNOWN; if( tokens[*tokens_consumed] != NULL ) op_code = swq_identify_op( tokens, tokens_consumed ); if( SWQ_OP_IS_LOGICAL(op_code) ) { swq_expr *remainder = NULL; swq_expr *parent; int sub_consumed; error = swq_subexpr_compile( tokens + *tokens_consumed + 1, field_list, &remainder, &sub_consumed ); if( error != NULL ) { swq_expr_free( *expr_out ); *expr_out = NULL; return error; } parent = (swq_field_op *) SWQ_MALLOC(sizeof(swq_field_op)); memset( parent, 0, sizeof(swq_field_op) ); parent->field_index = -1; parent->first_sub_expr = (struct swq_node_s *) *expr_out; parent->second_sub_expr = (struct swq_node_s *) remainder; parent->operation = op_code; *expr_out = parent; *tokens_consumed += sub_consumed + 1; } return NULL;}/************************************************************************//* swq_expr_compile() *//************************************************************************/const char *swq_expr_compile( const char *where_clause, int field_count, char **field_names, swq_field_type *field_types, swq_expr **expr_out ){ swq_field_list field_list; field_list.count = field_count; field_list.names = field_names; field_list.types = field_types; field_list.table_ids = NULL; field_list.ids = NULL; field_list.table_count = 0; field_list.table_defs = NULL; return swq_expr_compile2( where_clause, &field_list, expr_out );}/************************************************************************//* swq_expr_compile2() *//************************************************************************/const char *swq_expr_compile2( const char *where_clause, swq_field_list *field_list, swq_expr **expr_out ){#define MAX_TOKEN 1024 char *token_list[MAX_TOKEN], *rest_of_expr; int token_count = 0; int tokens_consumed, i; const char *error; /* ** Collect token array. */ rest_of_expr = (char *) where_clause; while( token_count < MAX_TOKEN ) { token_list[token_count] = swq_token(rest_of_expr,&rest_of_expr,NULL); if( token_list[token_count] == NULL ) break; token_count++; } token_list[token_count] = NULL; /* ** Parse the expression. */ *expr_out = NULL; error = swq_subexpr_compile( token_list, field_list, expr_out, &tokens_consumed ); for( i = 0; i < token_count; i++ ) SWQ_FREE( token_list[i] ); if( error != NULL ) return error; if( tokens_consumed < token_count ) { swq_expr_free( *expr_out ); *expr_out = NULL; sprintf( swq_error, "Syntax error, %d extra tokens", token_count - tokens_consumed ); return swq_error; } return NULL;}/************************************************************************//* swq_expr_free() *//************************************************************************/void swq_expr_free( swq_expr *expr ){ if( expr == NULL ) return; if( expr->first_sub_expr != NULL ) swq_expr_free( (swq_expr *) expr->first_sub_expr ); if( expr->second_sub_expr != NULL ) swq_expr_free( (swq_expr *) expr->second_sub_expr ); if( expr->string_value != NULL ) SWQ_FREE( expr->string_value ); SWQ_FREE( expr );}/************************************************************************//* swq_expr_evaluate() *//************************************************************************/int swq_expr_evaluate( swq_expr *expr, swq_op_evaluator fn_evaluator, void *record_handle ){ if( expr->operation == SWQ_OR ) { return swq_expr_evaluate( (swq_expr *) expr->first_sub_expr, fn_evaluator, record_handle) || swq_expr_evaluate( (swq_expr *) expr->second_sub_expr, fn_evaluator, record_handle); } else if( expr->operation == SWQ_AND ) { return swq_expr_evaluate( (swq_expr *) expr->first_sub_expr, fn_evaluator, record_handle) && swq_expr_evaluate( (swq_expr *) expr->second_sub_expr, fn_evaluator, record_handle); } else if( expr->operation == SWQ_NOT ) { return !swq_expr_evaluate( (swq_expr *) expr->second_sub_expr, fn_evaluator, record_handle); } else { return fn_evaluator( expr, record_handle ); }}/************************************************************************//* swq_expr_dump() *//************************************************************************/void swq_expr_dump( swq_expr *expr, FILE * fp, int depth ){ char spaces[60]; int i; const char *op_name = "unknown"; for( i = 0; i < depth*2 && i < sizeof(spaces); i++ ) spaces[i] = ' '; spaces[i] = '\0'; /* ** first term. */ if( expr->first_sub_expr != NULL ) swq_expr_dump( (swq_expr *) expr->first_sub_expr, fp, depth + 1 ); else fprintf( fp, "%s Field %d\n", spaces, expr->field_index ); /* ** Operation. */ if( expr->operation == SWQ_OR ) op_name = "OR"; if( expr->operation == SWQ_AND ) op_name = "AND"; if( expr->operation == SWQ_NOT) op_name = "NOT"; if( expr->operation == SWQ_GT ) op_name = ">"; if( expr->operation == SWQ_LT ) op_name = "<"; if( expr->operation == SWQ_EQ ) op_name = "="; if( expr->operation == SWQ_NE ) op_name = "!="; if( expr->operation == SWQ_GE ) op_name = ">="; if( expr->operation == SWQ_LE ) op_name = "<="; if( expr->operation == SWQ_LIKE ) op_name = "LIKE"; if( expr->operation == SWQ_ISNULL ) op_name = "IS NULL"; if( expr->operation == SWQ_IN ) op_name = "IN"; fprintf( fp, "%s%s\n", spaces, op_name ); /* ** Second term. */ if( expr->second_sub_expr != NULL ) swq_expr_dump( (swq_expr *) expr->second_sub_expr, fp, depth + 1 ); else if( expr->operation == SWQ_IN || expr->operation == SWQ_NOTIN ) { const char *src; fprintf( fp, "%s (\"%s\"", spaces, expr->string_value ); src = expr->string_value + strlen(expr->string_value) + 1; while( *src != '\0' ) { fprintf( fp, ",\"%s\"", src ); src += strlen(src) + 1; } fprintf( fp, ")\n" ); } else if( expr->string_value != NULL ) fprintf( fp, "%s %s\n", spaces, expr->string_value );}/************************************************************************//* ==================================================================== *//* SELECT statement parsing *//* ==================================================================== *//************************************************************************//*Supported SQL Syntax:SELECT <field-list> FROM <table_def> [LEFT JOIN <table_def> ON [<table_ref>.]<key_field> = [<table_ref>.].<key_field>]* [WHERE <where-expr>] [ORDER BY <sort specification list>]<field-list> ::= DISTINCT <field_ref> | <field-spec> | <field-spec> , <field-list><field-spec> ::= <field_ref> | <field_func> ( [DISTINCT] <field-func> ) | Count(*)<field-func> ::= AVG | MAX | MIN | SUM | COUNT<field_ref> ::= [<table_ref>.]field_name<sort specification list> ::= <sort specification> [ { <comma> <sort specification> }... ]<sort specification> ::= <sort key> [ <ordering specification> ]<sort key> ::= <field_ref><ordering specification> ::= ASC | DESC<table_def> ::= ['<datasource name>'.]table_name [table_alias]<table_ref> ::= table_name | table_alias */static int swq_parse_table_def( swq_select *select_info, int *is_literal, char **token, char **input );/************************************************************************//* swq_select_preparse() *//************************************************************************/const char *swq_select_preparse( const char *select_statement, swq_select **select_info_ret ){ swq_select *select_info; char *token; char *input; int is_literal; swq_col_def *swq_cols;#define MAX_COLUMNS 250 *select_info_ret = NULL;/* -------------------------------------------------------------------- *//* Get first token. Ensure it is SELECT. *//* -------------------------------------------------------------------- */ token = swq_token( select_statement, &input, NULL ); if( strcasecmp(token,"select") != 0 ) { SWQ_FREE( token ); strcpy( swq_error, "Missing keyword SELECT" ); return swq_error; } SWQ_FREE( token );/* -------------------------------------------------------------------- *//* allocate selection structure. *//* -------------------------------------------------------------------- */ select_info = (swq_select *) SWQ_MALLOC(sizeof(swq_select)); memset( select_info, 0, sizeof(swq_select) ); select_info->raw_select = swq_strdup( select_statement );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -