Skip to content

Commit

Permalink
feat: support update-where
Browse files Browse the repository at this point in the history
  • Loading branch information
sinkinben committed Feb 2, 2022
1 parent ef0d99b commit 4d4ee52
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 12 deletions.
20 changes: 17 additions & 3 deletions sql-parser/schema.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,33 @@ typedef struct
char fieldname[TBALE_COLUMN_NAME_MAX_LENGTH];
} schema_t;

/* We should keep `entry, schema` these two members in order,
/* 1) We should keep `entry, schema` these two members in order,
* see `destroy_condition_tree()`.
*
* 2) schema_value is used by `update` SQL statement, e.g.
* > update table set schema = schema_value where `conditions`
*/
struct schema_node_t
{
list_node_t entry;
schema_t schema;
uint64_t schema_value;
};
typedef struct schema_node_t schema_node_t;


static inline schema_node_t *alloc_schema_node(const char *filedname, uint32_t width, column_type_t column_type)
static inline schema_node_t *alloc_schema_node(
const char *filedname,
uint32_t width,
column_type_t column_type,
uint64_t schema_value
)
{
schema_node_t *node = (schema_node_t *)malloc(sizeof(schema_node_t));
strcpy(node->schema.fieldname, filedname);
node->schema.width = width;
node->schema.column_type = column_type;
node->schema_value = schema_value;
init_list_head(&(node->entry));
return node;
}
Expand All @@ -54,8 +64,12 @@ static inline void free_schema_list(schema_node_t *schemas)
list_node_t *pos, *next;
list_for_each_safe(pos, next, &schemas->entry)
{
schema_node_t *node = list_entry(pos, schema_node_t, entry);
schema_t *schema = &(node->schema);
if (schema->column_type == COLUMN_VARCHAR)
free((void *)(node->schema_value));
list_del(pos);
free(list_entry(pos, schema_node_t, entry));
free((void *)(node));
}
init_list_head(&(schemas->entry));
}
Expand Down
6 changes: 6 additions & 0 deletions sql-parser/sqlex.l
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
"delete" |
"DELETE" { return DELETE; }

"update" |
"UPDATE" { return UPDATE; }

"create" |
"CREATE" { return CREATE; }

Expand All @@ -34,6 +37,9 @@
"values" |
"VALUES" { return VALUES; }

"set" |
"SET" { return SET; }

"TABLE" { return TABLE; }

"int" |
Expand Down
56 changes: 49 additions & 7 deletions sql-parser/sqlparser.y
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ void yyerror(const char *);

schema_node_t *schema_list; // create table tbl (`schema_list`)
schema_node_t *select_list; // select `select_list` from tbl
schema_node_t *update_list; // update table set `update_list` where `condition_tree`
condition_t *condition_tree; // select `select_list` from tbl where `condition_tree`

int yywrap() { return 1; }
Expand All @@ -35,12 +36,13 @@ void yyerror(const char *msg) { fprintf(stderr, "[tinydb] SQL Parser: %s\n", msg
const char *strval;
struct schema_node_t *schema_node;
struct schema_node_t *select_node;
struct schema_node_t *update_node;
struct condition_t *condition_tree;
}

// sql keywords
%token SELECT INSERT CREATE DELETE
%token FROM TABLE WHERE VALUES INTO
%token SELECT INSERT CREATE DELETE UPDATE
%token FROM TABLE WHERE VALUES INTO SET
%token COMMIT ROLLBACK

// sql operator
Expand All @@ -58,6 +60,9 @@ void yyerror(const char *msg) { fprintf(stderr, "[tinydb] SQL Parser: %s\n", msg
%type <schema_node> createitemlist
%type <select_node> columnitem
%type <select_node> selectitemlist
%type <update_node> updateitem
%type <update_node> updateitemlist

%type <intval> cmp_op logic_op
%type <condition_tree> conditionitem
%type <condition_tree> conditions
Expand All @@ -76,10 +81,18 @@ statement:
| createsql {}
| insertsql {}
| deletesql {}
| updatesql {}
| commitsql {}
| rollbacksql {}
;

updatesql:
UPDATE IDNAME SET updateitemlist WHERE conditions ';'
{
statement_set(stm_ptr, STATEMENT_UPDATE_WHERE, $2, update_list, $6);
}
;

deletesql:
DELETE FROM IDNAME WHERE conditions ';'
{
Expand Down Expand Up @@ -133,10 +146,34 @@ selectsql:
}
;

updateitem:
IDNAME EQUAL NUMBER
{
$$ = alloc_schema_node($1, 4, COLUMN_INT, $3);
free((void *)($1));
}
| IDNAME EQUAL STRING
{
$$ = alloc_schema_node($1, 4, COLUMN_VARCHAR, (uint64_t)($3));
free((void *)($1));
}
;

updateitemlist:
updateitem
{
list_add_tail(&($1->entry), &(update_list->entry));
}
| updateitemlist ',' updateitem
{
list_add_tail(&($3->entry), &(update_list->entry));
}
;

columnitem:
IDNAME
{
$$ = alloc_schema_node($1, 0, COLUMN_DUMMY);
$$ = alloc_schema_node($1, 0, COLUMN_DUMMY, 0);
free((void *)($1));
}
;
Expand Down Expand Up @@ -211,11 +248,11 @@ createsql:
createitem:
IDNAME INT '(' NUMBER ')'
{
$$ = alloc_schema_node($1, $4, COLUMN_INT);
$$ = alloc_schema_node($1, $4, COLUMN_INT, 0);
}
| IDNAME CHAR '(' NUMBER ')'
{
$$ = alloc_schema_node($1, $4, COLUMN_VARCHAR);
$$ = alloc_schema_node($1, $4, COLUMN_VARCHAR, 0);
}

;
Expand All @@ -239,12 +276,17 @@ 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, COLUMN_DUMMY);
schema_list = alloc_schema_node("", 0, COLUMN_DUMMY, 0);

/* 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, COLUMN_DUMMY);
select_list = alloc_schema_node("", 0, COLUMN_DUMMY, 0);

/* used by update sql, e.g. update table set `schema = schema_value`
* update_list is a dummy list head node.
*/
update_list = alloc_schema_node("", 0, COLUMN_DUMMY, 0);

/* 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 @@ -9,6 +9,7 @@ typedef enum
STATEMENT_SELECT,
STATEMENT_SELECT_WHERE,
STATEMENT_UPDATE,
STATEMENT_UPDATE_WHERE,
STATEMENT_DELETE,
STATEMENT_DELETE_WHERE,
STATEMENT_COMMIT,
Expand Down
42 changes: 40 additions & 2 deletions sql-vm/vm.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@
* The parsing result of a SQL statement is stored in statement_t.
* These `execute_xxx` functions are equal to the "Vitrual Machine" in sqlite.
* SQL Statement:
* 1) execute_select, execute_delete are used by the dummy sql parser.
* 1) execute_select, execute_delete, execute_update are used by the dummy sql
* parser.
* > select (this will print all the rows)
* > delete [id] (this will delete the row whose id is `[id]` from B+Tree)
* > update [id] [username] [email]
*
* 2) select_where, delete_where are used by the sql parser based on flex-bison.
* 2) select_where, delete_where, update_where are used by the sql parser
* based on flex-bison.
* > select * from table where id > 10 and id < 30;
* > delete * from table where id > 10 and id < 30;
* > update table set username='skb', email='skn@qq.com' where id < 10;
**/

execute_result_t execute_insert(statement_t *statement, table_t *table)
Expand Down Expand Up @@ -104,6 +108,38 @@ execute_result_t execute_update(statement_t *statement, table_t *table)
return EXECUTE_NO_SUCH_KEY;
}

/**
* @brief Scan all rows in the table to update.
*/
execute_result_t execute_update_where(statement_t *statement, table_t *table)
{
cursor_t *cursor = table_start(table);
schema_node_t *schemas = statement->schemas;
list_node_t *pos;
row_t row;
while (!(cursor->end_of_table))
{
deserialize_row(cursor_value(cursor), &row);
if (test_condition(statement->conditions, &row))
{
list_for_each(pos, &(schemas->entry))
{
schema_t *schema = &(list_entry(pos, schema_node_t, entry)->schema);
uint64_t schema_val = list_entry(pos, schema_node_t, entry)->schema_value;
if (strcmp("id", schema->fieldname) == 0)
row.id = schema_val;
else if (strcmp("username", schema->fieldname) == 0)
strcpy(row.username, (char *)(schema_val));
else if (strcmp("email", schema->fieldname) == 0)
strcpy(row.email, (char *)(schema_val));
}
serialize_row(&row, cursor_value(cursor));
}
cursor_advance(cursor);
}
return EXECUTE_SUCCESS;
}

execute_result_t execute_delete(statement_t *statement, table_t *table)
{
uint32_t key_to_delete = statement->row_value.id;
Expand Down Expand Up @@ -163,6 +199,8 @@ execute_result_t vm_executor(statement_t *statement, table_t *table)
return execute_select_where(statement, table);
case STATEMENT_UPDATE:
return execute_update(statement, table);
case STATEMENT_UPDATE_WHERE:
return execute_update_where(statement, table);
case STATEMENT_DELETE:
return execute_delete(statement, table);
case STATEMENT_DELETE_WHERE:
Expand Down

0 comments on commit 4d4ee52

Please sign in to comment.