mirror of
https://github.com/mdbtools/mdbtools.git
synced 2025-04-05 20:31:00 +08:00
Support "SELECT TOP n [PERCENT]... " queries.
Updated the SQL parser to support "SELECT TOP n [PERCENT]... " queries, matching the Mocrosoft Access SQL language. Export these queries from databases with mdb-queries.
This commit is contained in:
parent
8219e4ef7a
commit
eb5dd4d0b7
@ -50,6 +50,7 @@ typedef struct MdbSQL
|
||||
long max_rows;
|
||||
char error_msg[1024];
|
||||
int limit;
|
||||
int limit_percent;
|
||||
long row_count;
|
||||
} MdbSQL;
|
||||
|
||||
@ -103,7 +104,8 @@ void mdb_sql_bind_all(MdbSQL *sql);
|
||||
int mdb_sql_fetch_row(MdbSQL *sql, MdbTableDef *table);
|
||||
int mdb_sql_add_temp_col(MdbSQL *sql, MdbTableDef *ttable, int col_num, char *name, int col_type, int col_size, int is_fixed);
|
||||
void mdb_sql_bind_column(MdbSQL *sql, int colnum, void *varaddr, int *len_ptr);
|
||||
int mdb_sql_add_limit(MdbSQL *sql, char *limit);
|
||||
int mdb_sql_add_limit(MdbSQL *sql, char *limit, int percent);
|
||||
int mdb_sql_get_limit(MdbSQL *sql);
|
||||
|
||||
|
||||
int parse_sql(MdbSQL * mdb, const gchar* str);
|
||||
|
@ -72,6 +72,8 @@ null { return NUL; }
|
||||
">" { return GT; }
|
||||
like { return LIKE; }
|
||||
limit { return LIMIT; }
|
||||
top { return TOP; }
|
||||
percent { return PERCENT; }
|
||||
count { return COUNT; }
|
||||
strptime { return STRPTIME; }
|
||||
[ \t\r] ;
|
||||
|
@ -72,6 +72,7 @@ MdbSQL *sql;
|
||||
sql->sarg_stack = NULL;
|
||||
sql->max_rows = -1;
|
||||
sql->limit = -1;
|
||||
sql->limit_percent = 0;
|
||||
|
||||
return sql;
|
||||
}
|
||||
@ -473,12 +474,23 @@ int mdb_sql_add_column(MdbSQL *sql, char *column_name)
|
||||
sql->num_columns++;
|
||||
return 0;
|
||||
}
|
||||
int mdb_sql_add_limit(MdbSQL *sql, char *limit)
|
||||
int mdb_sql_add_limit(MdbSQL *sql, char *limit, int percent)
|
||||
{
|
||||
sql->limit = atoi(limit);
|
||||
sql->limit_percent = percent;
|
||||
|
||||
if (sql->limit_percent && (sql->limit < 0 || sql->limit > 100)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mdb_sql_get_limit(MdbSQL *sql)
|
||||
{
|
||||
return sql->limit;
|
||||
}
|
||||
|
||||
int mdb_sql_add_function1(MdbSQL *sql, char *func_name, char *arg1)
|
||||
{
|
||||
fprintf(stderr, "calling function %s with %s", func_name, arg1);
|
||||
@ -833,6 +845,13 @@ int found = 0;
|
||||
|
||||
sql->cur_table = table;
|
||||
mdb_index_scan_init(mdb, table);
|
||||
|
||||
/* We know how many rows there are, so convert limit percentage
|
||||
* to an row count */
|
||||
if (sql->limit != -1 && sql->limit_percent) {
|
||||
sql->limit = (int)((double)table->num_rows / 100 * sql->limit);
|
||||
sql->limit_percent = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -62,7 +62,7 @@ typedef struct sql_context
|
||||
|
||||
%token <name> IDENT NAME PATH STRING NUMBER
|
||||
%token SELECT FROM WHERE CONNECT DISCONNECT TO LIST TABLES AND OR NOT LIMIT COUNT STRPTIME
|
||||
%token DESCRIBE TABLE
|
||||
%token DESCRIBE TABLE TOP PERCENT
|
||||
%token LTEQ GTEQ LIKE IS NUL
|
||||
|
||||
%type <name> database
|
||||
@ -91,7 +91,7 @@ stmt:
|
||||
;
|
||||
|
||||
query:
|
||||
SELECT column_list FROM table where_clause limit_clause {
|
||||
SELECT top_clause column_list FROM table where_clause limit_clause {
|
||||
mdb_sql_select(parser_ctx->mdb);
|
||||
}
|
||||
| CONNECT TO database {
|
||||
@ -108,6 +108,17 @@ query:
|
||||
}
|
||||
;
|
||||
|
||||
top_clause:
|
||||
/* empty */
|
||||
| TOP NUMBER { mdb_sql_add_limit(parser_ctx->mdb, $2, 0); free($2); }
|
||||
| TOP NUMBER PERCENT {
|
||||
if (mdb_sql_add_limit(parser_ctx->mdb, $2, 1)) {
|
||||
yyerror(NULL, parser_ctx, "Percent values must be between 0 and 100");
|
||||
}
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
|
||||
where_clause:
|
||||
/* empty */
|
||||
| WHERE sarg_list
|
||||
@ -115,7 +126,14 @@ where_clause:
|
||||
|
||||
limit_clause:
|
||||
/* empty */
|
||||
| LIMIT NUMBER { mdb_sql_add_limit(parser_ctx->mdb, $2); free($2); }
|
||||
| LIMIT NUMBER {
|
||||
if (mdb_sql_get_limit(parser_ctx->mdb) != -1) {
|
||||
yyerror(NULL, parser_ctx, "Can not have TOP and LIMIT clauses");
|
||||
} else {
|
||||
mdb_sql_add_limit(parser_ctx->mdb, $2, 0);
|
||||
}
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
|
||||
sarg_list:
|
||||
|
@ -62,9 +62,11 @@ int main (int argc, char **argv) {
|
||||
|
||||
//variables for the generation of sql
|
||||
char *sql_tables = (char *) malloc(bind_size);
|
||||
char *sql_predicate = (char *) malloc(bind_size);
|
||||
char *sql_columns = (char *) malloc(bind_size);
|
||||
char *sql_where = (char *) malloc(bind_size);
|
||||
char *sql_sorting = (char *) malloc(bind_size);
|
||||
int flagint;
|
||||
|
||||
/* see getopt(3) for more information on getopt and this will become clear */
|
||||
while ((opt=getopt(argc, argv, "L1d:"))!=-1) {
|
||||
@ -148,8 +150,22 @@ int main (int argc, char **argv) {
|
||||
|
||||
while (mdb_fetch_row(table)) {
|
||||
if(strcmp(query_id,objectid) == 0) {
|
||||
flagint = atoi(flag);
|
||||
//we have a row for our query
|
||||
switch(atoi(attribute)) {
|
||||
case 3: // predicate
|
||||
if (flagint & 0x30) {
|
||||
strcpy(sql_predicate, " TOP ");
|
||||
strcat(sql_predicate, name1);
|
||||
if (flagint & 0x20) {
|
||||
strcat(sql_predicate, " PERCENT");
|
||||
}
|
||||
} else if (flagint & 0x8) {
|
||||
strcpy(sql_predicate, " DISTINCTROW");
|
||||
} else if (flagint & 0x2) {
|
||||
strcpy(sql_predicate, " DISTINCT");
|
||||
}
|
||||
break;
|
||||
case 5: // table name
|
||||
if(strcmp(sql_tables,"") == 0) {
|
||||
strcpy(sql_tables,name1);
|
||||
@ -193,9 +209,9 @@ int main (int argc, char **argv) {
|
||||
|
||||
/* print out the sql statement */
|
||||
if(strcmp(sql_where,"") == 0) {
|
||||
fprintf(stdout,"SELECT %s FROM %s %s\n",sql_columns,sql_tables,sql_sorting);
|
||||
fprintf(stdout,"SELECT%s %s FROM %s %s\n",sql_predicate,sql_columns,sql_tables,sql_sorting);
|
||||
} else {
|
||||
fprintf(stdout,"SELECT %s FROM %s WHERE %s %s\n",sql_columns,sql_tables,sql_where,sql_sorting);
|
||||
fprintf(stdout,"SELECT%s %s FROM %s WHERE %s %s\n",sql_predicate,sql_columns,sql_tables,sql_where,sql_sorting);
|
||||
}
|
||||
|
||||
mdb_free_tabledef(table);
|
||||
|
Loading…
Reference in New Issue
Block a user