借助flex和bison实现解释器功能是个挑战。本博客,下载一开源项目分析开发流程。
myDBMS
linux–Flex and Bison
#ifndef _SQL_H
#define _SQL_H
#include
#include
#include
#include
#include
#include
#include
typedef union KEY{
int intkey;
char skey[64];
}KEY;
typedef struct field{ /*field structure 字段结构体*/
char name[64]; /*字段名*/
int type; /*INT:0 STRING:1*/
union KEY key[100]; /*key 键值*/
}field;
typedef struct table{ /*table structure 表结构体*/
char name[64]; /*表名*/
struct field *ffield; /*fields 字段数组指针*/
int flen; /*fields length 字段数目*/
int ilen; /*items length 记录条数*/
struct table *next;
}table;
typedef struct mydb{ /*database structure 数据库结构体*/
char name[64]; /*数据库名称*/
struct table *tbroot; /*table root 下属表链表的根节点*/
struct mydb *next;
}mydb;
typedef struct hyper_items_def /*CREATE语句后的字段和类型链表节点结构*/
{
char *field; /*字段名称*/
int type; /*INT:0 STRING:1*/
struct hyper_items_def *next;
}hyper_items_def;
typedef struct value_def /*INSERT语句的键值链表节点结构,包括值和类型*/
{
union KEY value; /*值*/
int type; /*类型,INT:0 STRING:1*/
struct value_def *next;
}value_def;
typedef struct item_def /*INSERT,SELECT语句的选择字段链表节点结构,包括字段名,字段位置指针*/
{
char *field; /*字段名*/
struct field *pos; /*字段在实际数据库中的位置指针*/
struct item_def *next;
}field_def;
typedef struct conditions_def /*SELECT,UPDATE,DELETE语句的条件二叉树节点结构*/
{
int type; /*键值类型,INT:0 STRING:1*/
struct item_def *litem; /*条件表达式左部的字段指针*/
int intv; /*整型键值存储处*/
char *strv; /*字符串键值*/
int cmp_op; /*操作符类型, '=':1 | '>':2 | '<':3 | '>=':4 | '<=':5 | '!=':6 | 'AND':7 | 'OR':8 */
struct conditions_def *left; /*左子树指针*/
struct conditions_def *right; /*右子树指针*/
}conditions_def;
typedef struct table_def /*多表SELECT语句的表链表节点结构*/
{
char *table; /*表名*/
struct table *pos; /*表在实际数据库中的位置指针*/
struct table_def *next;
}table_def;
typedef struct upcon_def /*UPDATE语句的赋值链表节点结构*/
{
char *field; /*字段名*/
int type; /*类型,INT:0 STRING:1*/
union KEY value; /*值*/
struct field *pos; /*字段在实际数据库中的位置指针*/
struct upcon_def *next;
}upcon_def;
void createDB();
void showDB();
void useDB(char *dbname);
void createTable(char *tableval, struct hyper_items_def *Hitemroot);
void showTable();
void multiInsert(char *tableval, struct item_def *itemroot, struct value_def *valroot);
void selectWhere(struct item_def *itemroot, struct table_def *tableroot, struct conditions_def *conroot);
void deletes(char *tableval, struct conditions_def *conroot);
void updates(char *tableval, struct upcon_def *uproot, struct conditions_def *conroot);
void dropTable(char *tableval);
void dropDB(char *dbname);
#endif
#include "sql.h"
#define TRUE 1
#define FALSE 0
extern char database[64];
struct mydb *dbroot = NULL;
/*item链表就地逆置*/
struct item_def *converseItems(struct item_def *ppHead){
struct item_def *pCurNode = ppHead;
struct item_def *pPrevNode = NULL;
struct item_def *pTmpNode = NULL;
while(pCurNode)
{
pPrevNode = pCurNode;
pCurNode = pCurNode->next;
pPrevNode->next = pTmpNode;
pTmpNode = pPrevNode;
}
return pTmpNode;
}
/*各种结构链表的内存释放*/
void freeHItems(struct hyper_items_def *Hitemroot){
struct hyper_items_def *Hitemtemp;
while(Hitemroot != NULL){
Hitemtemp = Hitemroot->next;
free(Hitemroot);
Hitemroot = Hitemtemp;
}
}
void freeCons(struct conditions_def *conroot){
if(conroot == NULL)
return;
if (conroot->left != NULL)
freeCons(conroot->left);
else if (conroot->right != NULL)
freeCons(conroot->right);
else
free(conroot);
}
void freeItems(struct item_def *itemroot){
struct item_def *itemtemp;
while(itemroot != NULL){
itemtemp = itemroot->next;
free(itemroot);
itemroot = itemtemp;
}
}
void freeTables(struct table_def *tableroot){
struct table_def *tableptr;
while(tableroot != NULL){
tableptr = tableroot->next;
free(tableroot);
tableroot = tableptr;
}
}
void freeUpcon(struct upcon_def *uproot){
struct upcon_def *uptemp;
while(uproot != NULL){
uptemp = uproot->next;
free(uptemp);
uproot = uptemp;
}
}
void freeVal(struct value_def *valroot){
struct value_def *valtemp;
while(valroot != NULL){
valtemp = valroot->next;
free(valroot);
valroot = valtemp;
}
}
/*创建数据库。若数据库根节点为空,则在根结点处创建数据库,若不为空则遍历数据库链表,
若找到同名数据库,提示已存在,返回,若没找到,在链表尾部插入新的数据库*/
void createDB(){
if(dbroot == NULL){
dbroot = (struct mydb *)malloc(sizeof(struct mydb));
strcpy(dbroot->name,database);
dbroot->tbroot = NULL;
dbroot->next = NULL;
if(dbroot != NULL);
printf("Database %s created successfully!\n", database);
return;
}
struct mydb *newdb;
newdb = dbroot;
while(newdb->next != NULL){
if(strcmp(newdb->name,database) == 0){
printf("error: The database already exists!\n");
return;
}
newdb = newdb->next;
}
if(strcmp(newdb->name,database) == 0){
printf("error: The database already exists!\n");
return;
}
newdb->next = (struct mydb *)malloc(sizeof(struct mydb));
strcpy(newdb->next->name,database);
newdb->next->tbroot = NULL;
newdb->next->next = NULL;
if(dbroot->next != NULL);
printf("Database %s created successfully!\n", database);
}
/*展示所有数据库。若根节点为空,提示数据库列表为空请先创建一个数据库,否则遍历数据库链表,打印数据库名*/
void showDB(){
struct mydb *dbtemp = NULL;
if(dbroot != NULL)
dbtemp = dbroot;
else{
printf("Database list is NULL, Please create a database first!\n");
return;
}
while(dbtemp != NULL){
printf("%s ", dbtemp->name);
dbtemp = dbtemp->next;
}
printf("\n");
}
/*指定使用的数据库,若数据库根节点为空,提示请先创建一个数据库,遍历数据库链表,找到对应数据库,
将全局变量database更新为当前数据库名,否则提示数据库不存在,返回*/
void useDB(char *dbname){
struct mydb *dbtemp = NULL;
if(dbroot != NULL)
dbtemp = dbroot;
else{
printf("error: Please create a database first!\n");
return;
}
while(dbtemp != NULL){
if(strcmp(dbtemp->name, dbname) == 0){
strcpy(database, dbname);
printf("Using database %s\n", dbname);
return;
}
dbtemp = dbtemp->next;
}
printf("error: Database %s doesn't exist!\n", dbname);
}
/*创建表。若数据库根节点为空,提示先创建数据库,否则遍历数据库列表,查找当前使用的数据库,若未找到,提示数据库不存在,
若找到,再看当前数据库下的表根节点是否为空,若为空,在根节点处创建新表,否则遍历表链表,若找到名字相同的表,提示
该表已存在,返回,否则在链表尾部建立新表*/
void createTable(char *tableval, struct hyper_items_def *Hitemroot){
int i;
struct mydb *dbtemp = NULL;
struct table *newtable = NULL;
struct table *tabletemp = NULL;
struct hyper_items_def *itemstemp = Hitemroot;
if(dbroot != NULL)
dbtemp = dbroot;
else{
printf("error: Please create a database first!\n");
freeHItems(Hitemroot);
return;
}
while(dbtemp != NULL){
if(strcmp(dbtemp->name,database) == 0){
if(dbtemp->tbroot == NULL){
dbtemp->tbroot = (struct table *)malloc(sizeof(struct table));
strcpy(dbtemp->tbroot->name, tableval);
dbtemp->tbroot->ffield = (struct field *)malloc(10*sizeof(struct field));
i = 0;
while(itemstemp != NULL && i<10){
strcpy(dbtemp->tbroot->ffield[i].name, itemstemp->field);
if(itemstemp->type == 0)
dbtemp->tbroot->ffield[i].type = 0;
else
dbtemp->tbroot->ffield[i].type = 1;
itemstemp = itemstemp->next;
i++;
}
dbtemp->tbroot->flen = i;
dbtemp->tbroot->ilen = 0;
dbtemp->tbroot->next = NULL;
if(dbtemp->tbroot != NULL)
printf("Table %s created successfully!\n", tableval);
freeHItems(Hitemroot);
return;
}
newtable = dbtemp->tbroot;
while(newtable->next != NULL){
if(strcmp(newtable->name,tableval) == 0){
printf("error: The table already exists!\n");
freeHItems(Hitemroot);
return;
}
newtable = newtable->next;
}
if(strcmp(newtable->name,tableval) == 0){
printf("error: The table already exists!\n");
freeHItems(Hitemroot);
return;
}
newtable->next = (struct table *)malloc(sizeof(struct table));
strcpy(newtable->next->name, tableval);
newtable->next->ffield = (struct field *)malloc(10*sizeof(struct field));
i = 0;
while(itemstemp != NULL && i<10){
strcpy(newtable->next->ffield[i].name, itemstemp->field);
if(itemstemp->type == 0)
newtable->next->ffield[i].type = 0;
else
newtable->next->ffield[i].type = 1;
itemstemp = itemstemp->next;
i++;
}
newtable->next->flen = i;
newtable->next->next = NULL;
printf("Table %s created successfully!\n", tableval);
freeHItems(Hitemroot);
return;
}
dbtemp = dbtemp->next;
}
freeHItems(Hitemroot);
printf("error: Database %s doesn't exist!\n", database);
}
/*展示表。遍历当前选用的数据库下的表链表,打印表名*/
void showTable(){
struct mydb *dbtemp = NULL;
struct table *tabletemp = NULL;
int i,j,temp;
if(dbroot != NULL)
dbtemp = dbroot;
else{
printf("error: Please create a database first!\n");
return;
}
while(dbtemp != NULL){
if(strcmp(dbtemp->name,database) == 0){
tabletemp = dbtemp->tbroot;
while(tabletemp != NULL){
printf("%s ", tabletemp->name);
tabletemp = tabletemp->next;
}
printf("\n");
return;
}
dbtemp = dbtemp->next;
}
printf("error: Database %s doesn't exist!\n", database);
}
/*插入记录。找到插入的表,若未找到,提示不存在,找到以后,若未指定字段及其顺序,将value list中的值依次插入到每个字段的最后,
若指定了字段和顺序,则按顺序查找字段,并依次追加记录,若未查找到对应字段,则提示字段与表不匹配,返回。完成插值以后,
判断itemlist和valuelist是否同时为空,若不是,则提示两者不匹配,返回,若是,则提示成功,并将该表的条数值加一*/
void multiInsert(char *tableval, struct item_def *itemroot, struct value_def *valroot){
struct mydb *dbtemp = NULL;
struct table *tabletemp = NULL;
struct item_def *itemtemp = NULL;
struct value_def *valtemp = NULL;
int i,j,temp;
if(dbroot != NULL)
dbtemp = dbroot;
else{
printf("error: Please create a database first!\n");
freeItems(itemroot);
freeVal(valroot);
return;
}
while(dbtemp != NULL){
if(strcmp(dbtemp->name,database) == 0){
tabletemp = dbtemp->tbroot;
while(tabletemp != NULL){
if(strcmp(tabletemp->name, tableval) == 0){
i = 0;
temp = tabletemp->ilen;
valtemp = valroot;
if(itemroot == NULL){
while(valtemp != NULL){
if(valtemp->type == 0){
tabletemp->ffield[i].type = 0;
tabletemp->ffield[i].key[temp].intkey = valtemp->value.intkey;
}
else{
tabletemp->ffield[i].type = 1;
strcpy(tabletemp->ffield[i].key[temp].skey, valtemp->value.skey);
}
i++;
valtemp = valtemp->next;
}
}
else{
itemtemp = itemroot;
while(itemtemp != NULL && valtemp != NULL){
for(j = 0; j < tabletemp->flen; j++){
if(strcmp(tabletemp->ffield[j].name, itemtemp->field) == 0){
if(valtemp->type == 0){
tabletemp->ffield[j].type = 0;
tabletemp->ffield[j].key[temp].intkey = valtemp->value.intkey;
}
else{
tabletemp->ffield[j].type = 1;
strcpy(tabletemp->ffield[j].key[temp].skey, valtemp->value.skey);
}
i++;
break;
}
}
if(j == tabletemp->flen){
printf("error: Column name does not match the table definition!\n");
freeItems(itemroot);
freeVal(valroot);
return;
}
itemtemp = itemtemp->next;
valtemp = valtemp->next;
}
}
if(i <= tabletemp->flen && itemtemp == NULL && valtemp == NULL){
temp++;
tabletemp->ilen = temp;
printf("Insert successfully!\n");
}
else{
printf("error: The number of supplied values does not match the table definition!\n");
}
freeItems(itemroot);
freeVal(valroot);
return;
}
tabletemp = tabletemp->next;
}
printf("error: The table doesn't exist!\n");
freeItems(itemroot);
freeVal(valroot);
return;
}
dbtemp = dbtemp->next;
}
freeItems(itemroot);
freeVal(valroot);
printf("error: Database %s doesn't exist!\n", database);
}
/*二叉树递归判断条件正误,i是当前判断的一条记录在表中的位置索引,tabletemp是用于判断的临时表,单表查询时它指向单表,
多表查询时它是多表的笛卡尔乘积,conroot是条件二叉树根节点,当conroot为空时直接判断为TRUE,这个主要用于无条件的查询和更新,
删除等操作,有条件时,即最初传入的conroot不为空时,不会触发这条判断执行*/
_Bool whereTF(int i, struct table *tabletemp, struct conditions_def *conroot){
if(conroot == NULL){
return TRUE;
}
if(conroot->cmp_op == 7){
return whereTF(i, tabletemp, conroot->left) && whereTF(i, tabletemp, conroot->right);
}
else if(conroot->cmp_op == 8){
return whereTF(i, tabletemp, conroot->left) || whereTF(i, tabletemp, conroot->right);
}
else{
if(conroot->litem->pos == NULL){
int k;
for(k = 0; k < tabletemp->flen; k++){
if(strcmp(tabletemp->ffield[k].name, conroot->litem->field) == 0){
conroot->litem->pos = &tabletemp->ffield[k];
break;
}
}
if(conroot->litem->pos == NULL){
printf("error: Field %s doesn't exist!\n", conroot->litem->field);
return FALSE;
}
}
if(conroot->cmp_op == 1){
if(conroot->type == 0)
return conroot->litem->pos->key[i].intkey == conroot->intv;
else
return strcmp(conroot->litem->pos->key[i].skey, conroot->strv) == 0;
}
else if(conroot->cmp_op == 2){
if(conroot->type == 0){
return conroot->litem->pos->key[i].intkey > conroot->intv;
}
else{
printf("error: String can not compare!\n");
return FALSE;
}
}
else if(conroot->cmp_op == 3){
if(conroot->type == 0)
return conroot->litem->pos->key[i].intkey < conroot->intv;
else{
printf("error: String can not compare!\n");
return FALSE;
}
}
else if(conroot->cmp_op == 4){
if(conroot->type == 0)
return conroot->litem->pos->key[i].intkey >= conroot->intv;
else{
printf("error: String can not compare!\n");
return FALSE;
}
}
else if(conroot->cmp_op == 5){
if(conroot->type == 0)
return conroot->litem->pos->key[i].intkey <= conroot->intv;
else{
printf("error: String can not compare!\n");
return FALSE;
}
}
else {
if(conroot->type == 0)
return conroot->litem->pos->key[i].intkey != conroot->intv;
else
return strcmp(conroot->litem->pos->key[i].skey, conroot->strv) != 0;
}
}
}
/*查询操作,目前仅支持最多2个表查询。itemroot是选择的字段链表根节点,若为*即全选则传入NULL,tableroot是选择的表根节点,
conroot是条件二叉树根节点,若无条件则传入NULL,首先找到查询的表,找到以后更新每个table_def结构的pos变量,指向对应的表,
然后判断是否是单表,若为单表,tabletemp指向该表,再判断itemroot是否为空,若为空表示全选,依次将整个表打印出来,
提示成功,返回。若不为单表,即为2个表联合查询,那么先遍历两个表,找到第一组名称相同且数据类型相同的字段,作为主码,
将字段值相同的记录进行合并,构成新表,存入tabletemp中,若没有字段相同的,将笛卡尔乘积存入tabletemp中,然后判断itemroot
是否为空,若为空,判断并打印所有字段记录,若不为空,判断并打印对应的字段记录*/
void selectWhere(struct item_def *itemroot, struct table_def *tableroot, struct conditions_def *conroot){
struct mydb *dbtemp = NULL;
struct table_def *tableptr = NULL;
struct table *tabletemp = NULL;
struct item_def *itemtemp = NULL;
int i, j, k, m, n, len1, len2, pk1 = -1, pk2 = -1;
itemroot = converseItems(itemroot);
if(dbroot != NULL)
dbtemp = dbroot;
else{
printf("error: Please create a database first!\n");
freeCons(conroot);
freeItems(itemroot);
freeTables(tableroot);
return;
}
while(dbtemp != NULL){
if(strcmp(dbtemp->name,database) == 0){
tableptr = tableroot;
while(tableptr != NULL){
tabletemp = dbtemp->tbroot;
while(tabletemp != NULL){
if(strcmp(tabletemp->name, tableptr->table) == 0){
tableptr->pos = tabletemp;
break;
}
tabletemp = tabletemp->next;
}
if(tabletemp == NULL){
printf("error: Table %s doesn't exist!\n", tableptr->table);
freeCons(conroot);
freeItems(itemroot);
freeTables(tableroot);
return;
}
tableptr = tableptr->next;
}
if(tableroot->next == NULL){
tabletemp = tableroot->pos;
if(itemroot == NULL){
for(j = tabletemp->flen - 1; j >= 0; j--){
printf("%-20s ", tabletemp->ffield[j].name);
}
printf("\n");
for(i = 0; i < tabletemp->ilen; i++){
if(whereTF(i, tabletemp, conroot) == TRUE){
for(j = tabletemp->flen - 1; j >= 0 ; j--){
if(tabletemp->ffield[j].type == 0)
printf("%-20d ", tabletemp->ffield[j].key[i].intkey);
else
printf("%-20s ", tabletemp->ffield[j].key[i].skey);
}
printf("\n");
}
}
freeCons(conroot);
freeTables(tableroot);
return;
}
}
else{
tableroot->next->next = tableroot;
tableroot = tableroot->next;
tableroot->next->next = NULL;
len1 = tableroot->pos->flen;
len2 = tableroot->next->pos->flen;
tabletemp = (struct table *)malloc(sizeof(struct table));
for(i = len1 - 1; i >= 0; i--){
for(j = len2 - 1; j >= 0; j--){
if(strcmp(tableroot->pos->ffield[i].name, tableroot->next->pos->ffield[j].name) == 0 && tableroot->pos->ffield[i].type == tableroot->next->pos->ffield[j].type){
pk1 = i;
pk2 = j;
break;
}
}
if(strcmp(tableroot->pos->ffield[i].name, tableroot->next->pos->ffield[j].name) == 0)
break;
}
if(pk2 == -1){
tabletemp->ffield = (struct field *)malloc((len1 + len2)*sizeof(struct field));
tabletemp->flen = len1 + len2;
k = 0;
for(i = len1 - 1; i >= 0; i--){
strcpy(tabletemp->ffield[k].name, tableroot->pos->ffield[i].name);
k++;
}
for(i = len2 - 1; i >= 0; i--){
strcpy(tabletemp->ffield[k].name, tableroot->next->pos->ffield[i].name);
k++;
}
n = 0;
for(i = 0; i < tableroot->pos->ilen; i++){
for(j = 0; j < tableroot->next->pos->ilen; j++){
k = 0;
for(m = len1 - 1; m >= 0; m--){
tabletemp->ffield[k].type = tableroot->pos->ffield[m].type;
if(tableroot->pos->ffield[m].type == 0)
tabletemp->ffield[k].key[n].intkey = tableroot->pos->ffield[m].key[i].intkey;
else
strcpy(tabletemp->ffield[k].key[n].skey, tableroot->pos->ffield[m].key[i].skey);
k++;
}
for(m = len2 - 1; m >= 0; m--){
tabletemp->ffield[k].type = tableroot->next->pos->ffield[m].type;
if(tableroot->next->pos->ffield[m].type == 0)
tabletemp->ffield[k].key[n].intkey = tableroot->next->pos->ffield[m].key[j].intkey;
else
strcpy(tabletemp->ffield[k].key[n].skey, tableroot->next->pos->ffield[m].key[j].skey);
k++;
}
n++;
}
}
tabletemp->ilen = n;
}
else{
tabletemp->ffield = (struct field *)malloc((len1 + len2 - 1)*sizeof(struct field));
tabletemp->flen = len1 + len2 - 1;
k = 0;
for(i = len1 - 1; i >= 0; i--){
strcpy(tabletemp->ffield[k].name, tableroot->pos->ffield[i].name);
k++;
}
for(i = len2 - 1; i >= 0; i--){
if(i == pk2)
continue;
strcpy(tabletemp->ffield[k].name, tableroot->next->pos->ffield[i].name);
k++;
}
n = 0;
for(i = 0; i < tableroot->pos->ilen; i++){
for(j = 0; j < tableroot->next->pos->ilen; j++){
if(tableroot->pos->ffield[pk1].type == 0 && tableroot->pos->ffield[pk1].key[i].intkey == tableroot->next->pos->ffield[pk2].key[j].intkey || tableroot->pos->ffield[pk1].type == 1 && strcmp(tableroot->pos->ffield[pk1].key[i].skey, tableroot->next->pos->ffield[pk2].key[j].skey) == 0){
k = 0;
for(m = len1 - 1; m >= 0; m--){
tabletemp->ffield[k].type = tableroot->pos->ffield[m].type;
if(tableroot->pos->ffield[m].type == 0)
tabletemp->ffield[k].key[n].intkey = tableroot->pos->ffield[m].key[i].intkey;
else
strcpy(tabletemp->ffield[k].key[n].skey, tableroot->pos->ffield[m].key[i].skey);
k++;
}
for(m = len2 - 1; m >= 0; m--){
if(m == pk2)
continue;
tabletemp->ffield[k].type = tableroot->next->pos->ffield[m].type;
if(tableroot->next->pos->ffield[m].type == 0)
tabletemp->ffield[k].key[n].intkey = tableroot->next->pos->ffield[m].key[j].intkey;
else
strcpy(tabletemp->ffield[k].key[n].skey, tableroot->next->pos->ffield[m].key[j].skey);
k++;
}
n++;
}
}
}
tabletemp->ilen = n;
}
}
itemtemp = itemroot;
while(itemtemp != NULL){
for(i = 0; i < tabletemp->flen; i++){
if(strcmp(itemtemp->field, tabletemp->ffield[i].name) == 0){
itemtemp->pos = &tabletemp->ffield[i];
break;
}
}
if(i == tabletemp->flen){
printf("error: Column name does not match the table definition!\n");
freeCons(conroot);
freeItems(itemroot);
freeTables(tableroot);
return;
}
itemtemp = itemtemp->next;
}
if(itemroot == NULL){
for(j = 0; j < tabletemp->flen; j++){
printf("%-20s ", tabletemp->ffield[j].name);
}
printf("\n");
}
else{
itemtemp = itemroot;
while(itemtemp != NULL){
printf("%-20s ", itemtemp->field);
itemtemp = itemtemp->next;
}
printf("\n");
}
for(i = 0; i < tabletemp->ilen; i++){
if(whereTF(i, tabletemp, conroot) == TRUE){
if(itemroot == NULL){
for(j = 0; j < tabletemp->flen; j++){
if(tabletemp->ffield[j].type == 0)
printf("%-20d ", tabletemp->ffield[j].key[i].intkey);
else
printf("%-20s ", tabletemp->ffield[j].key[i].skey);
}
printf("\n");
}
else{
itemtemp = itemroot;
while(itemtemp != NULL){
if(itemtemp->pos->type == 0)
printf("%-20d ", itemtemp->pos->key[i].intkey);
else
printf("%-20s ", itemtemp->pos->key[i].skey);
itemtemp = itemtemp->next;
}
printf("\n");
}
}
}
freeCons(conroot);
freeItems(itemroot);
freeTables(tableroot);
return;
}
dbtemp = dbtemp->next;
}
freeCons(conroot);
freeItems(itemroot);
freeTables(tableroot);
printf("error: Database %s doesn't exist!\n", database);
}
/*删除操作。tableval为做删除的表的名称,conroot为条件二叉树的根节点,若为NULL,表示删除全部记录,
首先找到表,然后遍历表的每一条记录,若符合条件,则将后面的记录统一往前移动一条,将原纪录覆盖*/
void deletes(char *tableval, struct conditions_def *conroot){
struct mydb *dbtemp = NULL;
struct table *tabletemp = NULL;
int i,j,k;
if(dbroot != NULL)
dbtemp = dbroot;
else{
printf("error: Please create a database first!\n");
freeCons(conroot);
return;
}
while(dbtemp != NULL){
if(strcmp(dbtemp->name,database) == 0){
tabletemp = dbtemp->tbroot;
while(tabletemp != NULL){
if(strcmp(tabletemp->name, tableval) == 0){
for(i = 0; i < tabletemp->ilen; i++){
if(whereTF(i, tabletemp, conroot) == TRUE){
for(k = i; k < tabletemp->ilen-1; k++){
for(j = 0; j < tabletemp->flen; j++){
if(tabletemp->ffield[j].type == 0)
tabletemp->ffield[j].key[k].intkey = tabletemp->ffield[j].key[k+1].intkey;
else
strcpy(tabletemp->ffield[j].key[k].skey, tabletemp->ffield[j].key[k+1].skey);
}
}
tabletemp->ilen--;
i--;
}
}
printf("Delete successfully!\n");
freeCons(conroot);
return;
}
tabletemp = tabletemp->next;
}
printf("error: The table doesn't exist!\n");
freeCons(conroot);
return;
}
dbtemp = dbtemp->next;
}
freeCons(conroot);
printf("error: Database %s doesn not exist!\n", database);
}
/*更新操作。tableval是要更新的表名称,uproot为赋值结构链表,conroot为条件二叉树的根节点。
先找到要更新的表,然后遍历赋值结构链表,找到对应的字段,并将其地址赋给每个赋值结构的pos变量,
便于后续操作,然后遍历表的每一条记录,判断符合条件则将对应的字段更新为对应的值*/
void updates(char *tableval, struct upcon_def *uproot, struct conditions_def *conroot){
struct mydb *dbtemp = NULL;
struct table *tabletemp = NULL;
struct upcon_def *uptemp = NULL;
int i,j;
if(dbroot != NULL)
dbtemp = dbroot;
else{
printf("error: Please create a database first!\n");
freeCons(conroot);
freeUpcon(uproot);
return;
}
while(dbtemp != NULL){
if(strcmp(dbtemp->name,database) == 0){
tabletemp = dbtemp->tbroot;
while(tabletemp != NULL){
if(strcmp(tabletemp->name, tableval) == 0){
uptemp = uproot;
while(uptemp != NULL){
for(i = 0; i < tabletemp->flen; i++){
if(strcmp(tabletemp->ffield[i].name, uptemp->field) == 0){
uptemp->pos = &tabletemp->ffield[i];
break;
}
}
if(i == tabletemp->flen){
printf("error: Field %s does not exist!\n", uptemp->field);
freeCons(conroot);
freeUpcon(uproot);
return;
}
uptemp = uptemp->next;
}
for(i = 0; i < tabletemp->ilen; i++){
if(whereTF(i, tabletemp, conroot) == TRUE){
uptemp = uproot;
while(uptemp != NULL){
if(uptemp->pos->type == 0 && uptemp->type == 0)
uptemp->pos->key[i].intkey = uptemp->value.intkey;
else if(uptemp->pos->type == 1 && uptemp->type == 1)
strcpy(uptemp->pos->key[i].skey, uptemp->value.skey);
else{
printf("error: Data type mismatch!\n");
freeCons(conroot);
freeUpcon(uproot);
return;
}
uptemp = uptemp->next;
}
}
}
printf("Update successfully!\n");
freeCons(conroot);
freeUpcon(uproot);
return;
}
tabletemp = tabletemp->next;
}
printf("error: The table doesn't exist!\n");
freeCons(conroot);
freeUpcon(uproot);
return;
}
dbtemp = dbtemp->next;
}
freeCons(conroot);
printf("error: Database %s doesn not exist!\n", database);
}
/*丢弃表,即链表的删除节点操作,删除时释放内存*/
void dropTable(char *tableval){
struct mydb *dbtemp = NULL;
struct table *tabletemp = NULL;
struct table *tabletod = NULL;
int i,j;
if(dbroot != NULL)
dbtemp = dbroot;
else{
printf("error: Please create a database first!\n");
return;
}
while(dbtemp != NULL){
if(strcmp(dbtemp->name,database) == 0){
tabletemp = dbtemp->tbroot;
if(strcmp(dbtemp->tbroot->name, tableval) == 0){
tabletod = dbtemp->tbroot;
dbtemp->tbroot = dbtemp->tbroot->next;
free(tabletod->ffield);
free(tabletod);
printf("Drop table successfully!\n");
return;
}
if(dbtemp->tbroot->next == NULL)
dbtemp->tbroot = NULL;
while(tabletemp->next != NULL){
if(strcmp(tabletemp->next->name, tableval) == 0){
tabletod = tabletemp->next;
tabletemp->next = tabletemp->next->next;
free(tabletod->ffield);
free(tabletod);
printf("Drop table successfully!\n");
return;
}
tabletemp = tabletemp->next;
}
if(strcmp(tabletemp->name, tableval) == 0){
free(tabletemp->ffield);
free(tabletemp);
printf("Drop table successfully!\n");
return;
}
printf("error: The table doesn't exist!\n");
return;
}
dbtemp = dbtemp->next;
}
printf("error: Database %s doesn not exist!\n", database);
}
/*丢弃数据库,即链表的删除节点操作,删除时释放内存*/
void dropDB(char *dbname){
struct mydb *dbtemp = NULL;
struct mydb *dbtod = NULL;
struct table *tabletemp = NULL;
struct table *tabletod = NULL;
int i,j;
if(dbroot != NULL)
dbtemp = dbroot;
else{
printf("error: Please create a database first!\n");
return;
}
if(strcmp(dbroot->name, dbname) == 0){
tabletemp = dbroot->tbroot;
while(tabletemp != NULL){
tabletod = tabletemp->next;
free(tabletemp->ffield);
free(tabletemp);
tabletemp = tabletod;
}
dbtod = dbroot;
dbroot = dbroot->next;
free(dbtod);
printf("Drop database successfully!\n");
return;
}
if(dbroot->next == NULL)
dbroot = NULL;
while(dbtemp->next != NULL){
if(strcmp(dbtemp->next->name, dbname) == 0){
tabletemp = dbtemp->next->tbroot;
while(tabletemp != NULL){
tabletod = tabletemp->next;
free(tabletemp->ffield);
free(tabletemp);
tabletemp = tabletod;
}
dbtod = dbtemp->next;
dbtemp->next = dbtemp->next->next;
free(dbtod);
printf("Drop database successfully!\n");
return;
}
dbtemp = dbtemp->next;
}
if(strcmp(dbtemp->name, dbname) == 0){
tabletemp = dbtemp->tbroot;
while(tabletemp != NULL){
tabletod = tabletemp->next;
free(tabletemp->ffield);
free(tabletemp);
tabletemp = tabletod;
}
free(dbtemp);
printf("Drop database successfully!\n");
return;
}
printf("error: Database %s doesn not exist!\n", database);
}
#include "sql.h"
#define TRUE 1
#define FALSE 0
extern char database[64];
struct mydb *dbroot = NULL;
/*item链表就地逆置*/
struct item_def *converseItems(struct item_def *ppHead){
struct item_def *pCurNode = ppHead;
struct item_def *pPrevNode = NULL;
struct item_def *pTmpNode = NULL;
while(pCurNode)
{
pPrevNode = pCurNode;
pCurNode = pCurNode->next;
pPrevNode->next = pTmpNode;
pTmpNode = pPrevNode;
}
return pTmpNode;
}
/*各种结构链表的内存释放*/
void freeHItems(struct hyper_items_def *Hitemroot){
struct hyper_items_def *Hitemtemp;
while(Hitemroot != NULL){
Hitemtemp = Hitemroot->next;
free(Hitemroot);
Hitemroot = Hitemtemp;
}
}
void freeCons(struct conditions_def *conroot){
if(conroot == NULL)
return;
if (conroot->left != NULL)
freeCons(conroot->left);
else if (conroot->right != NULL)
freeCons(conroot->right);
else
free(conroot);
}
void freeItems(struct item_def *itemroot){
struct item_def *itemtemp;
while(itemroot != NULL){
itemtemp = itemroot->next;
free(itemroot);
itemroot = itemtemp;
}
}
void freeTables(struct table_def *tableroot){
struct table_def *tableptr;
while(tableroot != NULL){
tableptr = tableroot->next;
free(tableroot);
tableroot = tableptr;
}
}
void freeUpcon(struct upcon_def *uproot){
struct upcon_def *uptemp;
while(uproot != NULL){
uptemp = uproot->next;
free(uptemp);
uproot = uptemp;
}
}
void freeVal(struct value_def *valroot){
struct value_def *valtemp;
while(valroot != NULL){
valtemp = valroot->next;
free(valroot);
valroot = valtemp;
}
}
/*创建数据库。若数据库根节点为空,则在根结点处创建数据库,若不为空则遍历数据库链表,
若找到同名数据库,提示已存在,返回,若没找到,在链表尾部插入新的数据库*/
void createDB(){
if(dbroot == NULL){
dbroot = (struct mydb *)malloc(sizeof(struct mydb));
strcpy(dbroot->name,database);
dbroot->tbroot = NULL;
dbroot->next = NULL;
if(dbroot != NULL);
printf("Database %s created successfully!\n", database);
return;
}
struct mydb *newdb;
newdb = dbroot;
while(newdb->next != NULL){
if(strcmp(newdb->name,database) == 0){
printf("error: The database already exists!\n");
return;
}
newdb = newdb->next;
}
if(strcmp(newdb->name,database) == 0){
printf("error: The database already exists!\n");
return;
}
newdb->next = (struct mydb *)malloc(sizeof(struct mydb));
strcpy(newdb->next->name,database);
newdb->next->tbroot = NULL;
newdb->next->next = NULL;
if(dbroot->next != NULL);
printf("Database %s created successfully!\n", database);
}
/*展示所有数据库。若根节点为空,提示数据库列表为空请先创建一个数据库,否则遍历数据库链表,打印数据库名*/
void showDB(){
struct mydb *dbtemp = NULL;
if(dbroot != NULL)
dbtemp = dbroot;
else{
printf("Database list is NULL, Please create a database first!\n");
return;
}
while(dbtemp != NULL){
printf("%s ", dbtemp->name);
dbtemp = dbtemp->next;
}
printf("\n");
}
/*指定使用的数据库,若数据库根节点为空,提示请先创建一个数据库,遍历数据库链表,找到对应数据库,
将全局变量database更新为当前数据库名,否则提示数据库不存在,返回*/
void useDB(char *dbname){
struct mydb *dbtemp = NULL;
if(dbroot != NULL)
dbtemp = dbroot;
else{
printf("error: Please create a database first!\n");
return;
}
while(dbtemp != NULL){
if(strcmp(dbtemp->name, dbname) == 0){
strcpy(database, dbname);
printf("Using database %s\n", dbname);
return;
}
dbtemp = dbtemp->next;
}
printf("error: Database %s doesn't exist!\n", dbname);
}
/*创建表。若数据库根节点为空,提示先创建数据库,否则遍历数据库列表,查找当前使用的数据库,若未找到,提示数据库不存在,
若找到,再看当前数据库下的表根节点是否为空,若为空,在根节点处创建新表,否则遍历表链表,若找到名字相同的表,提示
该表已存在,返回,否则在链表尾部建立新表*/
void createTable(char *tableval, struct hyper_items_def *Hitemroot){
int i;
struct mydb *dbtemp = NULL;
struct table *newtable = NULL;
struct table *tabletemp = NULL;
struct hyper_items_def *itemstemp = Hitemroot;
if(dbroot != NULL)
dbtemp = dbroot;
else{
printf("error: Please create a database first!\n");
freeHItems(Hitemroot);
return;
}
while(dbtemp != NULL){
if(strcmp(dbtemp->name,database) == 0){
if(dbtemp->tbroot == NULL){
dbtemp->tbroot = (struct table *)malloc(sizeof(struct table));
strcpy(dbtemp->tbroot->name, tableval);
dbtemp->tbroot->ffield = (struct field *)malloc(10*sizeof(struct field));
i = 0;
while(itemstemp != NULL && i<10){
strcpy(dbtemp->tbroot->ffield[i].name, itemstemp->field);
if(itemstemp->type == 0)
dbtemp->tbroot->ffield[i].type = 0;
else
dbtemp->tbroot->ffield[i].type = 1;
itemstemp = itemstemp->next;
i++;
}
dbtemp->tbroot->flen = i;
dbtemp->tbroot->ilen = 0;
dbtemp->tbroot->next = NULL;
if(dbtemp->tbroot != NULL)
printf("Table %s created successfully!\n", tableval);
freeHItems(Hitemroot);
return;
}
newtable = dbtemp->tbroot;
while(newtable->next != NULL){
if(strcmp(newtable->name,tableval) == 0){
printf("error: The table already exists!\n");
freeHItems(Hitemroot);
return;
}
newtable = newtable->next;
}
if(strcmp(newtable->name,tableval) == 0){
printf("error: The table already exists!\n");
freeHItems(Hitemroot);
return;
}
newtable->next = (struct table *)malloc(sizeof(struct table));
strcpy(newtable->next->name, tableval);
newtable->next->ffield = (struct field *)malloc(10*sizeof(struct field));
i = 0;
while(itemstemp != NULL && i<10){
strcpy(newtable->next->ffield[i].name, itemstemp->field);
if(itemstemp->type == 0)
newtable->next->ffield[i].type = 0;
else
newtable->next->ffield[i].type = 1;
itemstemp = itemstemp->next;
i++;
}
newtable->next->flen = i;
newtable->next->next = NULL;
printf("Table %s created successfully!\n", tableval);
freeHItems(Hitemroot);
return;
}
dbtemp = dbtemp->next;
}
freeHItems(Hitemroot);
printf("error: Database %s doesn't exist!\n", database);
}
/*展示表。遍历当前选用的数据库下的表链表,打印表名*/
void showTable(){
struct mydb *dbtemp = NULL;
struct table *tabletemp = NULL;
int i,j,temp;
if(dbroot != NULL)
dbtemp = dbroot;
else{
printf("error: Please create a database first!\n");
return;
}
while(dbtemp != NULL){
if(strcmp(dbtemp->name,database) == 0){
tabletemp = dbtemp->tbroot;
while(tabletemp != NULL){
printf("%s ", tabletemp->name);
tabletemp = tabletemp->next;
}
printf("\n");
return;
}
dbtemp = dbtemp->next;
}
printf("error: Database %s doesn't exist!\n", database);
}
/*插入记录。找到插入的表,若未找到,提示不存在,找到以后,若未指定字段及其顺序,将value list中的值依次插入到每个字段的最后,
若指定了字段和顺序,则按顺序查找字段,并依次追加记录,若未查找到对应字段,则提示字段与表不匹配,返回。完成插值以后,
判断itemlist和valuelist是否同时为空,若不是,则提示两者不匹配,返回,若是,则提示成功,并将该表的条数值加一*/
void multiInsert(char *tableval, struct item_def *itemroot, struct value_def *valroot){
struct mydb *dbtemp = NULL;
struct table *tabletemp = NULL;
struct item_def *itemtemp = NULL;
struct value_def *valtemp = NULL;
int i,j,temp;
if(dbroot != NULL)
dbtemp = dbroot;
else{
printf("error: Please create a database first!\n");
freeItems(itemroot);
freeVal(valroot);
return;
}
while(dbtemp != NULL){
if(strcmp(dbtemp->name,database) == 0){
tabletemp = dbtemp->tbroot;
while(tabletemp != NULL){
if(strcmp(tabletemp->name, tableval) == 0){
i = 0;
temp = tabletemp->ilen;
valtemp = valroot;
if(itemroot == NULL){
while(valtemp != NULL){
if(valtemp->type == 0){
tabletemp->ffield[i].type = 0;
tabletemp->ffield[i].key[temp].intkey = valtemp->value.intkey;
}
else{
tabletemp->ffield[i].type = 1;
strcpy(tabletemp->ffield[i].key[temp].skey, valtemp->value.skey);
}
i++;
valtemp = valtemp->next;
}
}
else{
itemtemp = itemroot;
while(itemtemp != NULL && valtemp != NULL){
for(j = 0; j < tabletemp->flen; j++){
if(strcmp(tabletemp->ffield[j].name, itemtemp->field) == 0){
if(valtemp->type == 0){
tabletemp->ffield[j].type = 0;
tabletemp->ffield[j].key[temp].intkey = valtemp->value.intkey;
}
else{
tabletemp->ffield[j].type = 1;
strcpy(tabletemp->ffield[j].key[temp].skey, valtemp->value.skey);
}
i++;
break;
}
}
if(j == tabletemp->flen){
printf("error: Column name does not match the table definition!\n");
freeItems(itemroot);
freeVal(valroot);
return;
}
itemtemp = itemtemp->next;
valtemp = valtemp->next;
}
}
if(i <= tabletemp->flen && itemtemp == NULL && valtemp == NULL){
temp++;
tabletemp->ilen = temp;
printf("Insert successfully!\n");
}
else{
printf("error: The number of supplied values does not match the table definition!\n");
}
freeItems(itemroot);
freeVal(valroot);
return;
}
tabletemp = tabletemp->next;
}
printf("error: The table doesn't exist!\n");
freeItems(itemroot);
freeVal(valroot);
return;
}
dbtemp = dbtemp->next;
}
freeItems(itemroot);
freeVal(valroot);
printf("error: Database %s doesn't exist!\n", database);
}
/*二叉树递归判断条件正误,i是当前判断的一条记录在表中的位置索引,tabletemp是用于判断的临时表,单表查询时它指向单表,
多表查询时它是多表的笛卡尔乘积,conroot是条件二叉树根节点,当conroot为空时直接判断为TRUE,这个主要用于无条件的查询和更新,
删除等操作,有条件时,即最初传入的conroot不为空时,不会触发这条判断执行*/
_Bool whereTF(int i, struct table *tabletemp, struct conditions_def *conroot){
if(conroot == NULL){
return TRUE;
}
if(conroot->cmp_op == 7){
return whereTF(i, tabletemp, conroot->left) && whereTF(i, tabletemp, conroot->right);
}
else if(conroot->cmp_op == 8){
return whereTF(i, tabletemp, conroot->left) || whereTF(i, tabletemp, conroot->right);
}
else{
if(conroot->litem->pos == NULL){
int k;
for(k = 0; k < tabletemp->flen; k++){
if(strcmp(tabletemp->ffield[k].name, conroot->litem->field) == 0){
conroot->litem->pos = &tabletemp->ffield[k];
break;
}
}
if(conroot->litem->pos == NULL){
printf("error: Field %s doesn't exist!\n", conroot->litem->field);
return FALSE;
}
}
if(conroot->cmp_op == 1){
if(conroot->type == 0)
return conroot->litem->pos->key[i].intkey == conroot->intv;
else
return strcmp(conroot->litem->pos->key[i].skey, conroot->strv) == 0;
}
else if(conroot->cmp_op == 2){
if(conroot->type == 0){
return conroot->litem->pos->key[i].intkey > conroot->intv;
}
else{
printf("error: String can not compare!\n");
return FALSE;
}
}
else if(conroot->cmp_op == 3){
if(conroot->type == 0)
return conroot->litem->pos->key[i].intkey < conroot->intv;
else{
printf("error: String can not compare!\n");
return FALSE;
}
}
else if(conroot->cmp_op == 4){
if(conroot->type == 0)
return conroot->litem->pos->key[i].intkey >= conroot->intv;
else{
printf("error: String can not compare!\n");
return FALSE;
}
}
else if(conroot->cmp_op == 5){
if(conroot->type == 0)
return conroot->litem->pos->key[i].intkey <= conroot->intv;
else{
printf("error: String can not compare!\n");
return FALSE;
}
}
else {
if(conroot->type == 0)
return conroot->litem->pos->key[i].intkey != conroot->intv;
else
return strcmp(conroot->litem->pos->key[i].skey, conroot->strv) != 0;
}
}
}
/*查询操作,目前仅支持最多2个表查询。itemroot是选择的字段链表根节点,若为*即全选则传入NULL,tableroot是选择的表根节点,
conroot是条件二叉树根节点,若无条件则传入NULL,首先找到查询的表,找到以后更新每个table_def结构的pos变量,指向对应的表,
然后判断是否是单表,若为单表,tabletemp指向该表,再判断itemroot是否为空,若为空表示全选,依次将整个表打印出来,
提示成功,返回。若不为单表,即为2个表联合查询,那么先遍历两个表,找到第一组名称相同且数据类型相同的字段,作为主码,
将字段值相同的记录进行合并,构成新表,存入tabletemp中,若没有字段相同的,将笛卡尔乘积存入tabletemp中,然后判断itemroot
是否为空,若为空,判断并打印所有字段记录,若不为空,判断并打印对应的字段记录*/
void selectWhere(struct item_def *itemroot, struct table_def *tableroot, struct conditions_def *conroot){
struct mydb *dbtemp = NULL;
struct table_def *tableptr = NULL;
struct table *tabletemp = NULL;
struct item_def *itemtemp = NULL;
int i, j, k, m, n, len1, len2, pk1 = -1, pk2 = -1;
itemroot = converseItems(itemroot);
if(dbroot != NULL)
dbtemp = dbroot;
else{
printf("error: Please create a database first!\n");
freeCons(conroot);
freeItems(itemroot);
freeTables(tableroot);
return;
}
while(dbtemp != NULL){
if(strcmp(dbtemp->name,database) == 0){
tableptr = tableroot;
while(tableptr != NULL){
tabletemp = dbtemp->tbroot;
while(tabletemp != NULL){
if(strcmp(tabletemp->name, tableptr->table) == 0){
tableptr->pos = tabletemp;
break;
}
tabletemp = tabletemp->next;
}
if(tabletemp == NULL){
printf("error: Table %s doesn't exist!\n", tableptr->table);
freeCons(conroot);
freeItems(itemroot);
freeTables(tableroot);
return;
}
tableptr = tableptr->next;
}
if(tableroot->next == NULL){
tabletemp = tableroot->pos;
if(itemroot == NULL){
for(j = tabletemp->flen - 1; j >= 0; j--){
printf("%-20s ", tabletemp->ffield[j].name);
}
printf("\n");
for(i = 0; i < tabletemp->ilen; i++){
if(whereTF(i, tabletemp, conroot) == TRUE){
for(j = tabletemp->flen - 1; j >= 0 ; j--){
if(tabletemp->ffield[j].type == 0)
printf("%-20d ", tabletemp->ffield[j].key[i].intkey);
else
printf("%-20s ", tabletemp->ffield[j].key[i].skey);
}
printf("\n");
}
}
freeCons(conroot);
freeTables(tableroot);
return;
}
}
else{
tableroot->next->next = tableroot;
tableroot = tableroot->next;
tableroot->next->next = NULL;
len1 = tableroot->pos->flen;
len2 = tableroot->next->pos->flen;
tabletemp = (struct table *)malloc(sizeof(struct table));
for(i = len1 - 1; i >= 0; i--){
for(j = len2 - 1; j >= 0; j--){
if(strcmp(tableroot->pos->ffield[i].name, tableroot->next->pos->ffield[j].name) == 0 && tableroot->pos->ffield[i].type == tableroot->next->pos->ffield[j].type){
pk1 = i;
pk2 = j;
break;
}
}
if(strcmp(tableroot->pos->ffield[i].name, tableroot->next->pos->ffield[j].name) == 0)
break;
}
if(pk2 == -1){
tabletemp->ffield = (struct field *)malloc((len1 + len2)*sizeof(struct field));
tabletemp->flen = len1 + len2;
k = 0;
for(i = len1 - 1; i >= 0; i--){
strcpy(tabletemp->ffield[k].name, tableroot->pos->ffield[i].name);
k++;
}
for(i = len2 - 1; i >= 0; i--){
strcpy(tabletemp->ffield[k].name, tableroot->next->pos->ffield[i].name);
k++;
}
n = 0;
for(i = 0; i < tableroot->pos->ilen; i++){
for(j = 0; j < tableroot->next->pos->ilen; j++){
k = 0;
for(m = len1 - 1; m >= 0; m--){
tabletemp->ffield[k].type = tableroot->pos->ffield[m].type;
if(tableroot->pos->ffield[m].type == 0)
tabletemp->ffield[k].key[n].intkey = tableroot->pos->ffield[m].key[i].intkey;
else
strcpy(tabletemp->ffield[k].key[n].skey, tableroot->pos->ffield[m].key[i].skey);
k++;
}
for(m = len2 - 1; m >= 0; m--){
tabletemp->ffield[k].type = tableroot->next->pos->ffield[m].type;
if(tableroot->next->pos->ffield[m].type == 0)
tabletemp->ffield[k].key[n].intkey = tableroot->next->pos->ffield[m].key[j].intkey;
else
strcpy(tabletemp->ffield[k].key[n].skey, tableroot->next->pos->ffield[m].key[j].skey);
k++;
}
n++;
}
}
tabletemp->ilen = n;
}
else{
tabletemp->ffield = (struct field *)malloc((len1 + len2 - 1)*sizeof(struct field));
tabletemp->flen = len1 + len2 - 1;
k = 0;
for(i = len1 - 1; i >= 0; i--){
strcpy(tabletemp->ffield[k].name, tableroot->pos->ffield[i].name);
k++;
}
for(i = len2 - 1; i >= 0; i--){
if(i == pk2)
continue;
strcpy(tabletemp->ffield[k].name, tableroot->next->pos->ffield[i].name);
k++;
}
n = 0;
for(i = 0; i < tableroot->pos->ilen; i++){
for(j = 0; j < tableroot->next->pos->ilen; j++){
if(tableroot->pos->ffield[pk1].type == 0 && tableroot->pos->ffield[pk1].key[i].intkey == tableroot->next->pos->ffield[pk2].key[j].intkey || tableroot->pos->ffield[pk1].type == 1 && strcmp(tableroot->pos->ffield[pk1].key[i].skey, tableroot->next->pos->ffield[pk2].key[j].skey) == 0){
k = 0;
for(m = len1 - 1; m >= 0; m--){
tabletemp->ffield[k].type = tableroot->pos->ffield[m].type;
if(tableroot->pos->ffield[m].type == 0)
tabletemp->ffield[k].key[n].intkey = tableroot->pos->ffield[m].key[i].intkey;
else
strcpy(tabletemp->ffield[k].key[n].skey, tableroot->pos->ffield[m].key[i].skey);
k++;
}
for(m = len2 - 1; m >= 0; m--){
if(m == pk2)
continue;
tabletemp->ffield[k].type = tableroot->next->pos->ffield[m].type;
if(tableroot->next->pos->ffield[m].type == 0)
tabletemp->ffield[k].key[n].intkey = tableroot->next->pos->ffield[m].key[j].intkey;
else
strcpy(tabletemp->ffield[k].key[n].skey, tableroot->next->pos->ffield[m].key[j].skey);
k++;
}
n++;
}
}
}
tabletemp->ilen = n;
}
}
itemtemp = itemroot;
while(itemtemp != NULL){
for(i = 0; i < tabletemp->flen; i++){
if(strcmp(itemtemp->field, tabletemp->ffield[i].name) == 0){
itemtemp->pos = &tabletemp->ffield[i];
break;
}
}
if(i == tabletemp->flen){
printf("error: Column name does not match the table definition!\n");
freeCons(conroot);
freeItems(itemroot);
freeTables(tableroot);
return;
}
itemtemp = itemtemp->next;
}
if(itemroot == NULL){
for(j = 0; j < tabletemp->flen; j++){
printf("%-20s ", tabletemp->ffield[j].name);
}
printf("\n");
}
else{
itemtemp = itemroot;
while(itemtemp != NULL){
printf("%-20s ", itemtemp->field);
itemtemp = itemtemp->next;
}
printf("\n");
}
for(i = 0; i < tabletemp->ilen; i++){
if(whereTF(i, tabletemp, conroot) == TRUE){
if(itemroot == NULL){
for(j = 0; j < tabletemp->flen; j++){
if(tabletemp->ffield[j].type == 0)
printf("%-20d ", tabletemp->ffield[j].key[i].intkey);
else
printf("%-20s ", tabletemp->ffield[j].key[i].skey);
}
printf("\n");
}
else{
itemtemp = itemroot;
while(itemtemp != NULL){
if(itemtemp->pos->type == 0)
printf("%-20d ", itemtemp->pos->key[i].intkey);
else
printf("%-20s ", itemtemp->pos->key[i].skey);
itemtemp = itemtemp->next;
}
printf("\n");
}
}
}
freeCons(conroot);
freeItems(itemroot);
freeTables(tableroot);
return;
}
dbtemp = dbtemp->next;
}
freeCons(conroot);
freeItems(itemroot);
freeTables(tableroot);
printf("error: Database %s doesn't exist!\n", database);
}
/*删除操作。tableval为做删除的表的名称,conroot为条件二叉树的根节点,若为NULL,表示删除全部记录,
首先找到表,然后遍历表的每一条记录,若符合条件,则将后面的记录统一往前移动一条,将原纪录覆盖*/
void deletes(char *tableval, struct conditions_def *conroot){
struct mydb *dbtemp = NULL;
struct table *tabletemp = NULL;
int i,j,k;
if(dbroot != NULL)
dbtemp = dbroot;
else{
printf("error: Please create a database first!\n");
freeCons(conroot);
return;
}
while(dbtemp != NULL){
if(strcmp(dbtemp->name,database) == 0){
tabletemp = dbtemp->tbroot;
while(tabletemp != NULL){
if(strcmp(tabletemp->name, tableval) == 0){
for(i = 0; i < tabletemp->ilen; i++){
if(whereTF(i, tabletemp, conroot) == TRUE){
for(k = i; k < tabletemp->ilen-1; k++){
for(j = 0; j < tabletemp->flen; j++){
if(tabletemp->ffield[j].type == 0)
tabletemp->ffield[j].key[k].intkey = tabletemp->ffield[j].key[k+1].intkey;
else
strcpy(tabletemp->ffield[j].key[k].skey, tabletemp->ffield[j].key[k+1].skey);
}
}
tabletemp->ilen--;
i--;
}
}
printf("Delete successfully!\n");
freeCons(conroot);
return;
}
tabletemp = tabletemp->next;
}
printf("error: The table doesn't exist!\n");
freeCons(conroot);
return;
}
dbtemp = dbtemp->next;
}
freeCons(conroot);
printf("error: Database %s doesn not exist!\n", database);
}
/*更新操作。tableval是要更新的表名称,uproot为赋值结构链表,conroot为条件二叉树的根节点。
先找到要更新的表,然后遍历赋值结构链表,找到对应的字段,并将其地址赋给每个赋值结构的pos变量,
便于后续操作,然后遍历表的每一条记录,判断符合条件则将对应的字段更新为对应的值*/
void updates(char *tableval, struct upcon_def *uproot, struct conditions_def *conroot){
struct mydb *dbtemp = NULL;
struct table *tabletemp = NULL;
struct upcon_def *uptemp = NULL;
int i,j;
if(dbroot != NULL)
dbtemp = dbroot;
else{
printf("error: Please create a database first!\n");
freeCons(conroot);
freeUpcon(uproot);
return;
}
while(dbtemp != NULL){
if(strcmp(dbtemp->name,database) == 0){
tabletemp = dbtemp->tbroot;
while(tabletemp != NULL){
if(strcmp(tabletemp->name, tableval) == 0){
uptemp = uproot;
while(uptemp != NULL){
for(i = 0; i < tabletemp->flen; i++){
if(strcmp(tabletemp->ffield[i].name, uptemp->field) == 0){
uptemp->pos = &tabletemp->ffield[i];
break;
}
}
if(i == tabletemp->flen){
printf("error: Field %s does not exist!\n", uptemp->field);
freeCons(conroot);
freeUpcon(uproot);
return;
}
uptemp = uptemp->next;
}
for(i = 0; i < tabletemp->ilen; i++){
if(whereTF(i, tabletemp, conroot) == TRUE){
uptemp = uproot;
while(uptemp != NULL){
if(uptemp->pos->type == 0 && uptemp->type == 0)
uptemp->pos->key[i].intkey = uptemp->value.intkey;
else if(uptemp->pos->type == 1 && uptemp->type == 1)
strcpy(uptemp->pos->key[i].skey, uptemp->value.skey);
else{
printf("error: Data type mismatch!\n");
freeCons(conroot);
freeUpcon(uproot);
return;
}
uptemp = uptemp->next;
}
}
}
printf("Update successfully!\n");
freeCons(conroot);
freeUpcon(uproot);
return;
}
tabletemp = tabletemp->next;
}
printf("error: The table doesn't exist!\n");
freeCons(conroot);
freeUpcon(uproot);
return;
}
dbtemp = dbtemp->next;
}
freeCons(conroot);
printf("error: Database %s doesn not exist!\n", database);
}
/*丢弃表,即链表的删除节点操作,删除时释放内存*/
void dropTable(char *tableval){
struct mydb *dbtemp = NULL;
struct table *tabletemp = NULL;
struct table *tabletod = NULL;
int i,j;
if(dbroot != NULL)
dbtemp = dbroot;
else{
printf("error: Please create a database first!\n");
return;
}
while(dbtemp != NULL){
if(strcmp(dbtemp->name,database) == 0){
tabletemp = dbtemp->tbroot;
if(strcmp(dbtemp->tbroot->name, tableval) == 0){
tabletod = dbtemp->tbroot;
dbtemp->tbroot = dbtemp->tbroot->next;
free(tabletod->ffield);
free(tabletod);
printf("Drop table successfully!\n");
return;
}
if(dbtemp->tbroot->next == NULL)
dbtemp->tbroot = NULL;
while(tabletemp->next != NULL){
if(strcmp(tabletemp->next->name, tableval) == 0){
tabletod = tabletemp->next;
tabletemp->next = tabletemp->next->next;
free(tabletod->ffield);
free(tabletod);
printf("Drop table successfully!\n");
return;
}
tabletemp = tabletemp->next;
}
if(strcmp(tabletemp->name, tableval) == 0){
free(tabletemp->ffield);
free(tabletemp);
printf("Drop table successfully!\n");
return;
}
printf("error: The table doesn't exist!\n");
return;
}
dbtemp = dbtemp->next;
}
printf("error: Database %s doesn not exist!\n", database);
}
/*丢弃数据库,即链表的删除节点操作,删除时释放内存*/
void dropDB(char *dbname){
struct mydb *dbtemp = NULL;
struct mydb *dbtod = NULL;
struct table *tabletemp = NULL;
struct table *tabletod = NULL;
int i,j;
if(dbroot != NULL)
dbtemp = dbroot;
else{
printf("error: Please create a database first!\n");
return;
}
if(strcmp(dbroot->name, dbname) == 0){
tabletemp = dbroot->tbroot;
while(tabletemp != NULL){
tabletod = tabletemp->next;
free(tabletemp->ffield);
free(tabletemp);
tabletemp = tabletod;
}
dbtod = dbroot;
dbroot = dbroot->next;
free(dbtod);
printf("Drop database successfully!\n");
return;
}
if(dbroot->next == NULL)
dbroot = NULL;
while(dbtemp->next != NULL){
if(strcmp(dbtemp->next->name, dbname) == 0){
tabletemp = dbtemp->next->tbroot;
while(tabletemp != NULL){
tabletod = tabletemp->next;
free(tabletemp->ffield);
free(tabletemp);
tabletemp = tabletod;
}
dbtod = dbtemp->next;
dbtemp->next = dbtemp->next->next;
free(dbtod);
printf("Drop database successfully!\n");
return;
}
dbtemp = dbtemp->next;
}
if(strcmp(dbtemp->name, dbname) == 0){
tabletemp = dbtemp->tbroot;
while(tabletemp != NULL){
tabletod = tabletemp->next;
free(tabletemp->ffield);
free(tabletemp);
tabletemp = tabletod;
}
free(dbtemp);
printf("Drop database successfully!\n");
return;
}
printf("error: Database %s doesn not exist!\n", database);
}
%{
#include "sql.h"
char database[64]={0};
int yylex();
int yyparse();
void yyerror (const char *str)
{
fprintf(stderr, "error: %s\n", str); // error function
}
int yywrap()
{
return 1;
}
// main function
int main()
{
printf("SQL>");
return yyparse(); // calling parse funtion
}
%}
%union{
int intval;
char *strval;
struct hyper_items_def *Citemsval;
struct value_def *valueval;
struct item_def *itemval;
struct conditions_def *conval;
struct table_def *tbval;
struct upcon_def *updateval;
}
%token SELECT FROM WHERE AND OR DROP DELETE TABLE CREATE INTO VALUES INSERT UPDATE SET SHOW DATABASE DATABASES TABLES EXIT USE
%token NUMBER
%token STRING ID INT CHAR
%type comparator
%type hyper_items create_items
%type value_list value
%type item item_list
%type condition conditions
%type tables
%type up_cond up_conds
%left OR
%left AND
%%
/* production for sql grammar */
statements: statements statement | statement
statement: createsql | showsql | selectsql | insertsql | deletesql | updatesql | dropsql | exitsql | usesql
usesql: USE ID ';' '\n' {
printf("\n");
useDB($2);
printf("\nSQL>");
}
showsql: SHOW DATABASES ';' '\n' {
printf("\n");
showDB();
printf("\nSQL>");
}
|SHOW TABLES ';' '\n' {
printf("\n");
showTable();
printf("\nSQL>");
}
createsql: CREATE TABLE ID '(' hyper_items ')' ';' '\n' {
printf("\n");
createTable($3, $5);
printf("\nSQL>");
}
|CREATE DATABASE ID ';' '\n' {
strcpy(database, $3);
printf("\n");
createDB();
printf("\nSQL>");
}
selectsql: SELECT '*' FROM tables ';' '\n'{
printf("\n");
selectWhere(NULL, $4, NULL);
printf("\n");
printf("SQL>");
}
| SELECT item_list FROM tables ';' '\n' {
printf("\n");
selectWhere($2, $4, NULL);
printf("\nSQL>");
}
|SELECT '*' FROM tables WHERE conditions ';' '\n' {
printf("\n");
selectWhere(NULL, $4, $6);
printf("\nSQL>");
}
|SELECT item_list FROM tables WHERE conditions ';' '\n' {
printf("\n");
selectWhere($2, $4, $6);
printf("\nSQL>");
}
deletesql: DELETE FROM ID ';' '\n' {
printf("\n");
deletes($3, NULL);
printf("\n");
printf("SQL>");
}
|DELETE FROM ID WHERE conditions ';' '\n' {
printf("\n");
deletes($3, $5);
printf("\nSQL>");
}
insertsql: INSERT INTO ID VALUES '(' value_list ')' ';' '\n' {
printf("\n");
multiInsert($3, NULL, $6);
printf("\nSQL>");
}
|INSERT INTO ID '(' item_list ')' VALUES '(' value_list ')' ';' '\n' {
printf("\n");
multiInsert($3, $5, $9);
printf("\nSQL>");
}
updatesql: UPDATE ID SET up_conds ';' '\n' {
printf("\n");
updates($2, $4, NULL);
printf("\nSQL>");
}
|UPDATE ID SET up_conds WHERE conditions ';' '\n' {
printf("\n");
updates($2, $4, $6);
printf("\nSQL>");
}
dropsql: DROP TABLE ID ';' '\n' {
printf("\n");
dropTable($3);
printf("\nSQL>");
}
| DROP DATABASE ID ';' '\n' {
printf("\n");
dropDB($3);
printf("\nSQL>");
}
exitsql: EXIT ';' {
printf("\n");
printf("exit with code 0!\n");
exit(0);
}
create_items: ID INT {
$$ = (struct hyper_items_def *)malloc(sizeof(struct hyper_items_def));
$$->field = $1;
$$->type = 0;
$$->next = NULL;
}
| ID CHAR '(' NUMBER ')'{
$$ = (struct hyper_items_def *)malloc(sizeof(struct hyper_items_def));
$$->field = $1;
$$->type = 1;
$$->next = NULL;
}
hyper_items: create_items {
$$ = $1;
}
| hyper_items ',' create_items {
$$ = $3;
$$->next = $1;
}
item: ID {
$$ = (struct item_def *)malloc(sizeof(struct item_def));
$$->field = $1;
$$->pos = NULL;
$$->next = NULL;
}
item_list: item {
$$ = $1;
}
| item_list ',' item{
$$ = $3;
$$->next = $1;
}
value: NUMBER {
$$ = ((struct value_def *)malloc(sizeof(struct value_def)));
$$->value.intkey = $1;
$$->type = 0;
$$->next = NULL;
}
| STRING {
$$ = ((struct value_def *)malloc(sizeof(struct value_def)));
strcpy($$->value.skey, $1);
$$->type = 1;
$$->next = NULL;
}
value_list: value {
$$ = $1;
}
| value_list ',' value {
$$ = $3;
$$->next = $1;
}
comparator: '=' {$$ = 1; }
| '>' {$$ = 2; }
| '<' {$$ = 3; }
| ">=" {$$ = 4; }
| "<=" {$$ = 5; }
| '!' '=' {$$ = 6; }
condition: item comparator NUMBER {
$$ = ((struct conditions_def *)malloc(sizeof(struct conditions_def)));
$$->type = 0;
$$->litem = $1;
$$->intv = $3;
$$->cmp_op = $2;
$$->left = NULL;
$$->right = NULL;
}
| item comparator STRING {
$$ = ((struct conditions_def *)malloc(sizeof(struct conditions_def)));
$$->type = 1;
$$->litem = $1;
$$->strv = $3;
$$->cmp_op = $2;
$$->left = NULL;
$$->right = NULL;
}
conditions: condition {
$$ = $1;
}
|'(' conditions ')' {
$$ = $2;
}
| conditions AND conditions {
$$ = ((struct conditions_def *)malloc(sizeof(struct conditions_def)));
$$->cmp_op = 7;
$$->left = $1;
$$->right = $3;
}
| conditions OR conditions {
$$ = ((struct conditions_def *)malloc(sizeof(struct conditions_def)));
$$->cmp_op = 8;
$$->left = $1;
$$->right = $3;
}
tables: ID {
$$ = ((struct table_def *)malloc(sizeof(struct table_def)));
$$->table = $1;
$$->next = NULL;
}
| tables ',' ID{
$$ = ((struct table_def *)malloc(sizeof(struct table_def)));
$$->table = $3;
$$->next = $1;
}
up_cond: ID '=' NUMBER {
$$ = ((struct upcon_def *)malloc(sizeof(struct upcon_def)));
$$->field = $1;
$$->type = 0;
$$->value.intkey = $3;
$$->next = NULL;
}
| ID '=' STRING {
$$ = ((struct upcon_def *)malloc(sizeof(struct upcon_def)));
$$->field = $1;
$$->type = 1;
strcpy($$->value.skey, $3);
$$->next = NULL;
}
up_conds: up_cond {
$$ = $1;
}
| up_conds ',' up_cond {
$$ = $3;
$$->next = $1;
}
%%
1、myDBMS
2、linux–Flex and Bison
3、卢涛、王哲、贺国睿、王祎,东南大学自动化学院 《新型工业机器人语言及解释器设计与实现》