diff --git a/include/mdbsql.h b/include/mdbsql.h index 48a6bf8..ceb6c48 100644 --- a/include/mdbsql.h +++ b/include/mdbsql.h @@ -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); diff --git a/src/sql/lexer.l b/src/sql/lexer.l index 5bea481..11df9c2 100644 --- a/src/sql/lexer.l +++ b/src/sql/lexer.l @@ -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] ; diff --git a/src/sql/mdbsql.c b/src/sql/mdbsql.c index 5ed284e..9acaeab 100644 --- a/src/sql/mdbsql.c +++ b/src/sql/mdbsql.c @@ -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 diff --git a/src/sql/parser.y b/src/sql/parser.y index 0524bf1..84185a1 100644 --- a/src/sql/parser.y +++ b/src/sql/parser.y @@ -62,7 +62,7 @@ typedef struct sql_context %token 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 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: diff --git a/src/util/mdb-queries.c b/src/util/mdb-queries.c index d3b9925..2690c02 100644 --- a/src/util/mdb-queries.c +++ b/src/util/mdb-queries.c @@ -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);