Skip to content

Commit

Permalink
feat: support select-where
Browse files Browse the repository at this point in the history
  • Loading branch information
sinkinben committed Feb 2, 2022
1 parent 6ba9f75 commit 4064403
Show file tree
Hide file tree
Showing 7 changed files with 168 additions and 38 deletions.
6 changes: 5 additions & 1 deletion main2.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ int main(int argc, char *argv[])

if (argc < 2)
{
printf("Must supply a database filename.\n");
printf("You must supply a database filename.\n");
exit(EXIT_FAILURE);
}
char *filename = argv[1];
Expand Down Expand Up @@ -38,8 +38,12 @@ int main(int argc, char *argv[])
/* Parse the SQL, and put the result in statement_t `stm` */
statement_init(stm);
sql_parser(input->buffer, stm);

/* Execute the SQL statement, and log the result. */
result = vm_executor(stm, table);
vm_logger(result, stm, input);

/* Free the resources that are allocated in yyparser. */
statement_free(stm);
}
}
141 changes: 131 additions & 10 deletions sql-parser/condition.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@ typedef enum
/**
* A condition_t struct denotes: `lvalue op rvalue`,
* 1) `lvalue` is always the column name.
* 2) `rvalue` could be a integer or a string.
* 2) `rvalue` could be a integer or a string, which is denoted by `rvalue_type`.
* 3) When is_leaf = 1, then we should use lvalue/rvalue.
* 4) When is_leaf = 0, then we should use lchild/rchild.
*/
struct condition_t
{
operator_t op;
bool is_leaf;
column_type_t cmp_type;
union
{
struct condition_t *lchild;
Expand All @@ -43,43 +44,163 @@ struct condition_t
};
typedef struct condition_t condition_t;

static inline condition_t *alloc_condition(uint64_t lchild, operator_t op, uint64_t rchild, bool is_leaf)
static inline condition_t *alloc_condition(
uint64_t lchild,
operator_t op,
uint64_t rchild,
bool is_leaf,
column_type_t cmp_type
)
{
condition_t *cond = (condition_t *)malloc(sizeof(condition_t));
cond->op = op;
cond->is_leaf = is_leaf;
cond->lchild = (condition_t *)(lchild);
cond->rchild = (condition_t *)(rchild);
cond->cmp_type = cmp_type;
return cond;
}

static inline void print_tree(condition_t *node, int depth)
static inline void print_condition_tree(condition_t *node, int depth)
{
if (node == NULL)
return;
for (int i = 0; i < depth; ++i)
printf("\t- ");
if (node->is_leaf)
{
printf("lvalue = %s, op = %d, rvalue = %p \n", node->lvalue->fieldname, node->op, node->rchild);
printf("lvalue = %s, op = %d, rvalue = %p, cmp_type = %d \n",
node->lvalue->fieldname, node->op, node->rchild, node->cmp_type);
}
else
{
printf("op = %d\n", node->op);
print_tree(node->lchild, depth + 1);
print_tree(node->rchild, depth + 1);
print_condition_tree(node->lchild, depth + 1);
print_condition_tree(node->rchild, depth + 1);
}
}

static bool test_condition(condition_t *cond, row_t *row)
static inline bool cmp_int(operator_t op, uint64_t lval, uint64_t rval)
{
return true;
switch (op)
{
case OP_EQUAL:
return lval == rval;
case OP_GREAT:
return lval > rval;
case OP_GREAT_EQUAL:
return lval >= rval;
case OP_LESS:
return lval < rval;
case OP_LESS_EQUAL:
return lval <= rval;
case OP_NOT_EQUAL:
return lval != rval;
default:
printf("[cmp_int] Unknow op %d. \n", op);
assert(0);
}
}

static inline bool cmp_string(operator_t op, const char *lval, const char *rval)
{
int ret = strcmp(lval, rval);
switch (op)
{
case OP_EQUAL:
return ret == 0;
case OP_GREAT:
return ret == 1;
case OP_GREAT_EQUAL:
return ret >= 0;
case OP_LESS:
return ret == -1;
case OP_LESS_EQUAL:
return ret <= 0;
case OP_NOT_EQUAL:
return ret != 0;
default:
break;
}
printf("[cmp_string] Unknow op %d. \n", op);
assert(0);
return -1;
}

static inline bool test_operator(column_type_t type, operator_t op, uint64_t lval, uint64_t rval)
{
if (type == COLUMN_INT)
return cmp_int(op, lval, rval);
else if (type == COLUMN_VARCHAR)
return cmp_string(op, (const char *)(lval), (const char *)(rval));
else
{
switch (op)
{
case OP_AND:
return lval && rval;
case OP_OR:
return lval || rval;
default:
break;
}
printf("[test_operator] Unknow column type %d and op %d. \n", type, op);
assert(0);
return 0;
}
}

static inline uint64_t get_row_field(const char *field, row_t *row)
{
if (strcmp("id", field) == 0)
return (uint64_t)(row->id);
else if (strcmp("username", field) == 0)
return (uint64_t)(row->username);
else if (strcmp("email", field) == 0)
return (uint64_t)(row->email);
else
{
printf("[get_row_field] Unknow field \'%s\' in condition. \n", field);
assert(0);
return -1;
}
}

static inline bool test_condition(condition_t *cond, row_t *row)
{
if (cond == NULL)
return false;
if (!cond->is_leaf)
{
uint64_t lval = test_condition(cond->lchild, row);
uint64_t rval = test_condition(cond->rchild, row);
return test_operator(cond->cmp_type, cond->op, lval, rval);
}
else
{
uint64_t lval = get_row_field(cond->lvalue->fieldname, row);
uint64_t rval = cond->rvalue.intval;
return test_operator(cond->cmp_type, cond->op, lval, rval);
}
}

static inline void destroy_condition_tree(condition_t *node)
{
printf("[destroy_condition_tree]: PLEASE implement me. \n");
// assert(0);
if (node == NULL)
return;
if (!(node->is_leaf))
{
destroy_condition_tree(node->lchild);
destroy_condition_tree(node->rchild);
}
else
{
void *entry_ptr = (void *)(node->lvalue) - sizeof(list_node_t);
free(entry_ptr);
if (node->cmp_type == COLUMN_VARCHAR)
free((void *)(node->rvalue.strval));
free((void *)(node));
}
}


Expand Down
8 changes: 6 additions & 2 deletions sql-parser/schema.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
static const uint32_t TBALE_COLUMN_NAME_MAX_LENGTH = 32;
typedef enum
{
DUMMY = -1,
COLUMN_DUMMY = -1,
COLUMN_INT, // -> uint_t in tinydb kernel
COLUMN_VARCHAR // -> varchar(n) in tinydb kernel
} column_type_t;
Expand All @@ -25,9 +25,12 @@ typedef struct
char fieldname[TBALE_COLUMN_NAME_MAX_LENGTH];
} schema_t;

/* We should keep `entry, schema` these two members in order,
* see `destroy_condition_tree()`.
*/
struct schema_node_t
{
struct list_head entry;
list_node_t entry;
schema_t schema;
};
typedef struct schema_node_t schema_node_t;
Expand All @@ -45,6 +48,7 @@ static inline schema_node_t *alloc_schema_node(const char *filedname, uint32_t w

static inline void free_schema_list(schema_node_t *schemas)
{
assert(schemas != NULL);
if (list_empty(&(schemas->entry)))
return;
list_node_t *pos, *next;
Expand Down
13 changes: 10 additions & 3 deletions sql-parser/sqlex.l
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,16 @@
"or" |
"OR" { return OR; }

[\'][A-Za-z][A-Za-z0-9_]*[\'] { yylval.strval = strdup(yytext); return STRING; }
[A-Za-z][A-Za-z0-9_]* { yylval.strval = strdup(yytext); return IDNAME; }
[0-9]+ { yylval.intval = atoi(yytext); return NUMBER; }
[\'][A-Za-z0-9_@\.]*[\'] {
/* Remove the single quation marks. */
int len = strlen(yytext);
yytext[len - 1] = '\0';
yylval.strval = strdup(yytext + 1);
return STRING;
}

[A-Za-z][A-Za-z0-9_]* { yylval.strval = strdup(yytext); return IDNAME; }
[0-9]+ { yylval.intval = atoi(yytext); return NUMBER; }

\n { return EOL; }
[ \t]+ { /* ignore and do nothing */ }
Expand Down
26 changes: 8 additions & 18 deletions sql-parser/sqlparser.y
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ selectsql:
}
| SELECT '*' FROM IDNAME WHERE conditions ';'
{
statement_set(stm_ptr, STATEMENT_SELECT, $4, select_list, $6);
statement_set(stm_ptr, STATEMENT_SELECT_FIELDS, $4, select_list, $6);
}
| SELECT selectitemlist FROM IDNAME WHERE conditions ';'
{
Expand All @@ -96,7 +96,8 @@ selectsql:
columnitem:
IDNAME
{
$$ = alloc_schema_node($1, 0, -1);
$$ = alloc_schema_node($1, 0, COLUMN_DUMMY);
free((void *)($1));
}
;

Expand Down Expand Up @@ -126,37 +127,26 @@ cmp_op:
conditionitem:
columnitem cmp_op NUMBER
{
$$ = alloc_condition((uint64_t)(&($1->schema)), $2, $3, true);
printf("[conditionitem NUMBER]");
print_tree($$, 0);
$$ = alloc_condition((uint64_t)(&($1->schema)), $2, $3, true, COLUMN_INT);
}
| columnitem cmp_op STRING
{
$$ = alloc_condition((uint64_t)(&($1->schema)), $2, (uint64_t)($3), true);
printf("[conditionitem STRING]");
print_tree($$, 0);
$$ = alloc_condition((uint64_t)(&($1->schema)), $2, (uint64_t)($3), true, COLUMN_VARCHAR);
}
;

conditions:
conditionitem
{
$$ = $1;
printf("[conditionitem]");
print_tree($$, 0);
}
| '(' conditions ')'
{
$$ = $2;
}
| conditions logic_op conditions
{
printf("[logic %d] left: ", $2);
print_tree($1, 0);
printf("[logic %d] right: ", $2);
print_tree($3, 0);

$$ = alloc_condition((uint64_t)($1), $2, (uint64_t)($3), false);
$$ = alloc_condition((uint64_t)($1), $2, (uint64_t)($3), false, COLUMN_DUMMY);
}
;

Expand Down Expand Up @@ -209,12 +199,12 @@ void __attribute__((constructor)) init()
/* used by create sql, e.g. create table tbl (`schema_list`),
* schema_list is a dummy list head node.
*/
schema_list = alloc_schema_node("", 0, DUMMY);
schema_list = alloc_schema_node("", 0, COLUMN_DUMMY);

/* used by select sql, e.g. select `select_list` from tbl,
* select_list is a dummy list head node.
*/
select_list = alloc_schema_node("", 0, DUMMY);
select_list = alloc_schema_node("", 0, COLUMN_DUMMY);

/* used by where condition, e.g.
* select `select_list` from tbl where `condition_tree`,
Expand Down
1 change: 1 addition & 0 deletions sql-statement/statement.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ static inline void statement_init(statement_t *stm)
*/
static inline void statement_free(statement_t *stm)
{
assert(stm != NULL);
if (stm->schemas)
{
free_schema_list(stm->schemas);
Expand Down
11 changes: 7 additions & 4 deletions sql-vm/vm.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,12 @@ execute_result_t execute_select_fields(statement_t *statement, table_t *table)
while (!(cursor->end_of_table))
{
deserialize_row(cursor_value(cursor), &row);
cnt++;
print_fields(&row, flags);

if (test_condition(statement->conditions, &row))
{
cnt++;
print_fields(&row, flags);
}
cursor_advance(cursor);
}
printf("total %u rows\n", cnt);
Expand Down Expand Up @@ -162,7 +166,6 @@ execute_result_t vm_executor(statement_t *statement, table_t *table)
return EXECUTE_UNKNOWN_STATEMENT;
}


void vm_logger(execute_result_t result, statement_t *statement, buffer_t *input)
{
switch (result)
Expand All @@ -185,4 +188,4 @@ void vm_logger(execute_result_t result, statement_t *statement, buffer_t *input)
}
}

#endif
#endif

0 comments on commit 4064403

Please sign in to comment.