📄 parse.c
字号:
/* Module: parse.c * * Description: This module contains routines related to parsing SQL statements. * This can be useful for two reasons: * * 1. So the query does not actually have to be executed to return data about it * * 2. To be able to return information about precision, nullability, aliases, etc. * in the functions SQLDescribeCol and SQLColAttributes. Currently, Postgres * doesn't return any information about these things in a query. * * Classes: none * * API functions: none * * Comments: See "notice.txt" for copyright and license information. * */#include <stdio.h>#include <string.h>#include <ctype.h>#include "statement.h"#include "connection.h"#include "qresult.h"#include "pgtypes.h"#ifndef WIN32#ifndef HAVE_STRICMP#define stricmp(s1,s2) strcasecmp(s1,s2)#define strnicmp(s1,s2,n) strncasecmp(s1,s2,n)#endif#endif#define FLD_INCR 32#define TAB_INCR 8#define COL_INCR 16char *getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dquote, char *numeric);void getColInfo(COL_INFO *col_info, FIELD_INFO *fi, int k);char searchColInfo(COL_INFO *col_info, FIELD_INFO *fi);char *getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dquote, char *numeric){int i = 0;int out = 0;char qc, in_escape = FALSE; if (smax <= 1) return NULL; smax--; /* skip leading delimiters */ while (isspace(s[i]) || s[i] == ',') { // mylog("skipping '%c'\n", s[i]); i++; } if (s[0] == '\0') { token[0] = '\0'; return NULL; } if (quote) *quote = FALSE; if (dquote) *dquote = FALSE; if (numeric) *numeric = FALSE; /* get the next token */ while ( ! isspace(s[i]) && s[i] != ',' && s[i] != '\0' && out != smax) { /* Handle quoted stuff */ if ( out == 0 && (s[i] == '\"' || s[i] == '\'')) { qc = s[i]; if (qc == '\"') { if (dquote) *dquote = TRUE; } if (qc == '\'') { if (quote) *quote = TRUE; } i++; /* dont return the quote */ while (s[i] != '\0' && out != smax) { if (s[i] == qc && ! in_escape) { break; } if (s[i] == '\\' && ! in_escape) { in_escape = TRUE; } else { in_escape = FALSE; token[out++] = s[i]; } i++; } if (s[i] == qc) i++; break; } /* Check for numeric literals */ if ( out == 0 && isdigit(s[i])) { if (numeric) *numeric = TRUE; token[out++] = s[i++]; while ( isalnum(s[i]) || s[i] == '.') token[out++] = s[i++]; break; } if ( ispunct(s[i]) && s[i] != '_') { mylog("got ispunct: s[%d] = '%c'\n", i, s[i]); if (out == 0) { token[out++] = s[i++]; break; } else break; } if (out != smax) token[out++] = s[i]; i++; } // mylog("done -- s[%d] = '%c'\n", i, s[i]); token[out] = '\0'; /* find the delimiter */ while ( isspace(s[i])) i++; /* return the most priority delimiter */ if (s[i] == ',') { if (delim) *delim = s[i]; } else if (s[i] == '\0') { if (delim) *delim = '\0'; } else { if (delim) *delim = ' '; } /* skip trailing blanks */ while ( isspace(s[i])) { i++; } return &s[i];}/*QR_set_num_fields(stmt->result, 14);QR_set_field_info(stmt->result, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);QR_set_field_info(stmt->result, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);QR_set_field_info(stmt->result, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);QR_set_field_info(stmt->result, 3, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);QR_set_field_info(stmt->result, 4, "DATA_TYPE", PG_TYPE_INT2, 2);QR_set_field_info(stmt->result, 5, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);QR_set_field_info(stmt->result, 6, "PRECISION", PG_TYPE_INT4, 4);QR_set_field_info(stmt->result, 7, "LENGTH", PG_TYPE_INT4, 4);QR_set_field_info(stmt->result, 8, "SCALE", PG_TYPE_INT2, 2);QR_set_field_info(stmt->result, 9, "RADIX", PG_TYPE_INT2, 2);QR_set_field_info(stmt->result, 10, "NULLABLE", PG_TYPE_INT2, 2);QR_set_field_info(stmt->result, 11, "REMARKS", PG_TYPE_TEXT, 254);// User defined fieldsQR_set_field_info(stmt->result, 12, "DISPLAY_SIZE", PG_TYPE_INT4, 4);QR_set_field_info(stmt->result, 13, "FIELD_TYPE", PG_TYPE_INT4, 4);*/voidgetColInfo(COL_INFO *col_info, FIELD_INFO *fi, int k){ if (fi->name[0] == '\0') strcpy(fi->name, QR_get_value_manual(col_info->result, k, 3)); fi->type = atoi( QR_get_value_manual(col_info->result, k, 13)); fi->precision = atoi( QR_get_value_manual(col_info->result, k, 6)); fi->length = atoi( QR_get_value_manual(col_info->result, k, 7)); fi->nullable = atoi( QR_get_value_manual(col_info->result, k, 10)); fi->display_size = atoi( QR_get_value_manual(col_info->result, k, 12));}charsearchColInfo(COL_INFO *col_info, FIELD_INFO *fi){int k;char *col; for (k = 0; k < QR_get_num_tuples(col_info->result); k++) { col = QR_get_value_manual(col_info->result, k, 3); if ( ! strcmp(col, fi->name)) { getColInfo(col_info, fi, k); mylog("PARSE: searchColInfo: \n"); return TRUE; } } return FALSE;}charparse_statement(StatementClass *stmt){static char *func="parse_statement";char token[256];char delim, quote, dquote, numeric, unquoted;char *ptr;char in_select = FALSE, in_distinct = FALSE, in_on = FALSE, in_from = FALSE, in_where = FALSE, in_table = FALSE;char in_field = FALSE, in_expr = FALSE, in_func = FALSE, in_dot = FALSE, in_as = FALSE;int j, i, k = 0, n, blevel = 0;FIELD_INFO **fi;TABLE_INFO **ti;char parse;ConnectionClass *conn = stmt->hdbc;HSTMT hcol_stmt;StatementClass *col_stmt;RETCODE result; mylog("%s: entering...\n", func); ptr = stmt->statement; fi = stmt->fi; ti = stmt->ti; stmt->nfld = 0; stmt->ntab = 0; while ((ptr = getNextToken(ptr, token, sizeof(token), &delim, "e, &dquote, &numeric)) != NULL) { unquoted = ! ( quote || dquote ); mylog("unquoted=%d, quote=%d, dquote=%d, numeric=%d, delim='%c', token='%s', ptr='%s'\n", unquoted, quote, dquote, numeric, delim, token, ptr); if ( unquoted && ! stricmp(token, "select")) { in_select = TRUE; mylog("SELECT\n"); continue; } if ( unquoted && in_select && ! stricmp(token, "distinct")) { in_distinct = TRUE; mylog("DISTINCT\n"); continue; } if ( unquoted && ! stricmp(token, "into")) { in_select = FALSE; mylog("INTO\n"); continue; } if ( unquoted && ! stricmp(token, "from")) { in_select = FALSE; in_from = TRUE; mylog("FROM\n"); continue; } if ( unquoted && (! stricmp(token, "where") || ! stricmp(token, "union") || ! stricmp(token, "order") || ! stricmp(token, "group") || ! stricmp(token, "having"))) { in_select = FALSE; in_from = FALSE; in_where = TRUE; mylog("WHERE...\n"); break; } if (in_select) { if ( in_distinct) { mylog("in distinct\n"); if (unquoted && ! stricmp(token, "on")) { in_on = TRUE; mylog("got on\n"); continue; } if (in_on) { in_distinct = FALSE; in_on = FALSE; continue; /* just skip the unique on field */ } mylog("done distinct\n"); in_distinct = FALSE; } if ( in_expr || in_func) { /* just eat the expression */ mylog("in_expr=%d or func=%d\n", in_expr, in_func); if (quote || dquote) continue; if (in_expr && blevel == 0 && delim == ',') { mylog("**** in_expr and Got comma\n"); in_expr = FALSE; in_field = FALSE; } else if (token[0] == '(') { blevel++; mylog("blevel++ = %d\n", blevel); } else if (token[0] == ')') { blevel--; mylog("blevel-- = %d\n", blevel); if (delim==',') { in_func = FALSE; in_expr = FALSE; in_field = FALSE; } } continue; } if ( ! in_field) { if ( ! token[0]) continue; if ( ! (stmt->nfld % FLD_INCR)) { mylog("reallocing at nfld=%d\n", stmt->nfld); fi = (FIELD_INFO **) realloc(fi, (stmt->nfld + FLD_INCR) * sizeof(FIELD_INFO *)); if ( ! fi) { stmt->parse_status = STMT_PARSE_FATAL; return FALSE; } stmt->fi = fi; } fi[stmt->nfld] = (FIELD_INFO *) malloc( sizeof(FIELD_INFO)); if (fi[stmt->nfld] == NULL) { stmt->parse_status = STMT_PARSE_FATAL; return FALSE; } /* Initialize the field info */ memset(fi[stmt->nfld], 0, sizeof(FIELD_INFO)); /* double quotes are for qualifiers */ if (dquote) fi[stmt->nfld]->dquote = TRUE; if (quote) { fi[stmt->nfld++]->quote = TRUE; continue; } else if (numeric) { mylog("**** got numeric: nfld = %d\n", stmt->nfld); fi[stmt->nfld]->numeric = TRUE; } else if (token[0] == '(') { /* expression */ mylog("got EXPRESSION\n"); fi[stmt->nfld++]->expr = TRUE; in_expr = TRUE; blevel = 1; continue; } else { strcpy(fi[stmt->nfld]->name, token); fi[stmt->nfld]->dot[0] = '\0'; } mylog("got field='%s', dot='%s'\n", fi[stmt->nfld]->name, fi[stmt->nfld]->dot); if (delim == ',') { mylog("comma (1)\n"); } else { in_field = TRUE; } stmt->nfld++; continue; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -