⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 build.c

📁 在VC6环境下开发
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "eDbInit.h"

void eDbBeginParse(Parser *pParse, int explainFlag){
	pParse->explain = explainFlag;  
	pParse->nVar = 0;
}

void eDbExec(Parser *pParse){
	
}

Table *eDbFindTable(eDb *db, const char *zName, const char *zDatabase){
	Table *p = 0;
	p = eDbHashFind(&db->tblHash, zName, strlen(zName)+1);
	return p;
}

Table *eDbLocateTable(Parser *pParse, const char *zName, const char *zDbase){
	Table *p;
	p = eDbFindTable(pParse->db, zName, zDbase);
	if( p==0 ){
		if( zDbase ){
			eDbErrorMsg(pParse, "no such table: %s.%s", zDbase, zName);
		}else if( eDbFindTable(pParse->db, zName, 0)!=0 ){
			eDbErrorMsg(pParse, "table \"%s\" is not in database \"%s\"",
			zName, zDbase);
		}else{
			eDbErrorMsg(pParse, "no such table: %s", zName);
		}
	}
	return p;
}

Index *eDbFindIndex(eDb *db, const char *zName, const char *zDb){
	Index *p = 0;
	p = eDbHashFind(&db->idxHash, zName, strlen(zName)+1);
	return p;
}

void eDbDeleteIndex(eDb *db, Index *p){
	Index *pOld;
	assert( db!=0 && p->zName!=0 );
	pOld = eDbHashInsert(&db->idxHash, p->zName,
						  strlen(p->zName)+1, 0);
	if( pOld!=0 && pOld!=p ){
		eDbHashInsert(&db->idxHash, pOld->zName,
						 strlen(pOld->zName)+1, pOld);
	}
	eDbFree(p);
}

void eDbUnlinkAndDeleteIndex(eDb *db, Index *pIndex){
	if( pIndex->pTable->pIndex==pIndex ){
		pIndex->pTable->pIndex = pIndex->pNext;
	}else{
		Index *p;
		for(p=pIndex->pTable->pIndex; p && p->pNext!=pIndex; p=p->pNext){}
		if( p && p->pNext==pIndex ){
			p->pNext = pIndex->pNext;
		}
	}
	eDbDeleteIndex(db, pIndex);
}
void eDbUnlinkIndex(eDb *db, Index *pIndex){
	if( pIndex->pTable->pIndex==pIndex ){
		pIndex->pTable->pIndex = pIndex->pNext;
	}else{
		Index *p;
		for(p=pIndex->pTable->pIndex; p && p->pNext!=pIndex; p=p->pNext){}
		if( p && p->pNext==pIndex ){
			p->pNext = pIndex->pNext;
		}
	}
}

void eDbDeleteTable(eDb *db, Table *pTable){
	int i;
	Index *pIndex, *pNext;
	if( pTable==0 ) return;

	/* Delete all indices associated with this table
	*/
	for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){
		pNext = pIndex->pNext;
		eDbDeleteIndex(db, pIndex);
	}

	/* Delete the Table structure itself.
	*/
	for(i=0; i<pTable->nCol; i++){
		eDbFree(pTable->aCol[i].zName);
		eDbFree(pTable->aCol[i].zDflt);
		eDbFree(pTable->aCol[i].zType);
	}
	eDbFree(pTable->zName);
	eDbFree(pTable->aCol);
	eDbSelectDelete(pTable->pSelect);
	eDbFree(pTable);
}

void eDbUnlinkAndDeleteTable(eDb *db, Table *p){
	Table *pOld;
	assert( db!=0 );
	pOld = eDbHashInsert(&db->tblHash, p->zName, strlen(p->zName)+1, 0);
	assert( pOld==0 || pOld==p );
	eDbDeleteTable(db, p);
}

void eDbUnlinkTable(eDb *db, Table *p){
	Table *pOld;
	assert( db!=0 );
	pOld = eDbHashInsert(&db->tblHash, p->zName, strlen(p->zName)+1, 0);
	assert( pOld==0 || pOld==p );
}

char *eDbTableNameFromToken(Token *pName){
	char *zName = eDbStrNDup(pName->z, pName->n);
	eDbDequote(zName);
	return zName;
}

void eDbStartTable(
	Parser *pParse,   /* Parser context */
	Token *pStart,   /* The "CREATE" token */
	Token *pName     /* Name of table or view to create */
){
	char *zName;
	Table *pTable;
	Index *pIdx;
	eDb *db = pParse->db;
	
	pParse->sFirstToken = *pStart;
	zName = eDbTableNameFromToken(pName);
	if( zName==0 ) return;

	/* Make sure the new table name does not collide with an existing
	** index or table name.  Issue an error message if it does.
	**
	** If we are re-reading the eDb_master table because of a schema
	** change and a new permanent table is found whose name collides with
	** an existing temporary table, that is not an error.
	*/
	pTable = eDbFindTable(db, zName, 0);
	if( pTable != 0){
		eDbErrorMsg(pParse, "table %s already exists", pTable->zName);
		eDbFree(zName);
		return;
	}
	if( (pIdx = eDbFindIndex(db, zName, 0))!=0){
		eDbErrorMsg(pParse, "there is already an index named %s", zName);
		eDbFree(zName);
		return;
	}
	pTable = eDbMalloc( sizeof(Table) );
	if( pTable==0 ){
		eDbFree(zName);
		return;
	}
	pTable->zName = zName;
	pTable->nCol = 0;
	pTable->aCol = 0;
	pTable->iPKey = -1;
	pTable->pIndex = 0;
	if( pParse->pNewTable ) eDbDeleteTable(db, pParse->pNewTable);
	pParse->pNewTable = pTable;
}

/*
** Add a new column to the table currently being constructed.
*/
void eDbAddColumn(Parser *pParse, Token *pName){
	Table *p;
	int i;
	char *z = 0;
	Column *pCol;
	if( (p = pParse->pNewTable)==0 ) return;
	eDbSetNString(&z, pName->z, pName->n, 0);
	if( z==0 ) return;
	eDbDequote(z);
	for(i=0; i<p->nCol; i++){
		if( eDbStrICmp(z, p->aCol[i].zName)==0 ){
			eDbErrorMsg(pParse, "duplicate column name: %s", z);
			eDbFree(z);
			return;
		}
	}
	if( (p->nCol & 0x7)==0 ){
		Column *aNew;
		aNew = eDbRealloc( p->aCol, (p->nCol+8)*sizeof(p->aCol[0]));
		if( aNew==0 ) return;
		p->aCol = aNew;
	}
	pCol = &p->aCol[p->nCol];
	memset(pCol, 0, sizeof(p->aCol[0]));
	pCol->zName = z;
	pCol->type = eDb_SO_UNK;
	p->nCol++;
}

/*
** This routine is called by the parser while in the middle of
** parsing a CREATE TABLE statement.  The pFirst token is the first
** token in the sequence of tokens that describe the type of the
** column currently under construction.   pLast is the last token
** in the sequence.  Use this information to construct a string
** that contains the typename of the column and store that string
** in zType.
*/ 
void eDbAddColumnType(Parser *pParse, Token *pFirst, Token *pLast){
	Table *p;
	int i, j;
	int n;
	char *z, **pz;
	Column *pCol;
	if( (p = pParse->pNewTable)==0 ) return;
	i = p->nCol-1;
	if( i<0 ) return;
	pCol = &p->aCol[i];
	pz = &pCol->zType;
	n = pLast->n + Addr(pLast->z) - Addr(pFirst->z);
	eDbSetNString(pz, pFirst->z, n, 0);
	z = *pz;
	if( z==0 ) return;
	for(i=j=0; z[i]; i++){
		int c = z[i];
		if( isspace(c) ) continue;
		z[j++] = c;
	}
	z[j] = 0;
	pCol->type = eDbCollateType(z, n);
}

/*
** The given token is the default value for the last column added to
** the table currently under construction.  If "minusFlag" is true, it
** means the value token was preceded by a minus sign.
**
** This routine is called by the parser while in the middle of
** parsing a CREATE TABLE statement.
*/
void eDbAddDefaultValue(Parser *pParse, Token *pVal, int minusFlag){
	Table *p;
	int i;
	char **pz;
	if( (p = pParse->pNewTable)==0 ) return;
	i = p->nCol-1;
	if( i<0 ) return;
	pz = &p->aCol[i].zDflt;
	if( minusFlag ){
		eDbSetNString(pz, "-", 1, pVal->z, pVal->n, 0);
	}else{
		eDbSetNString(pz, pVal->z, pVal->n, 0);
	}
	eDbDequote(*pz);
}

/*
** Designate the PRIMARY KEY for the table.  pList is a list of names 
** of columns that form the primary key.  If pList is NULL, then the
** most recently added column of the table is the primary key.
**
** A table can have at most one primary key.  If the table already has
** a primary key (and this is the second primary key) then create an
** error.
**
** If the PRIMARY KEY is on a single column whose datatype is INTEGER,
** then we will try to use that column as the row id.  (Exception:
** For backwards compatibility with older databases, do not do this
** if the file format version number is less than 1.)  Set the Table.iPKey
** field of the table under construction to be the index of the
** INTEGER PRIMARY KEY column.  Table.iPKey is set to -1 if there is
** no INTEGER PRIMARY KEY.
**
** If the key is not an INTEGER PRIMARY KEY, then create a unique
** index for the key.  No index is created for INTEGER PRIMARY KEYs.
*/
void eDbAddPrimaryKey(Parser *pParse, IdList *pList){
	Table *pTab = pParse->pNewTable;
	char *zType = 0;
	int iCol = -1, i;
	if( pTab==0 ) goto primary_key_exit;
	if( pTab->hasPrimKey ){
		eDbErrorMsg(pParse, 
				"table \"%s\" has more than one primary key", pTab->zName);
		goto primary_key_exit;
	}
	pTab->hasPrimKey = 1;
	if( pList==0 ){
		iCol = pTab->nCol - 1;
		pTab->aCol[iCol].isPrimKey = 1;
	}else{
		for(i=0; i<pList->nId; i++){
			for(iCol=0; iCol<pTab->nCol; iCol++){
				if( eDbStrICmp(pList->a[i].zName, pTab->aCol[iCol].zName)==0 ) break;
			}
			if( iCol<pTab->nCol ) pTab->aCol[iCol].isPrimKey = 1;
		}
		if( pList->nId>1 ) iCol = -1;
	}
	if( iCol>=0 && iCol<pTab->nCol ){
		zType = pTab->aCol[iCol].zType;
	}
	if(zType && eDbStrNICmp(zType, "INT",3)==0 ){
		pTab->iPKey = iCol;
	}else{
		eDbCreateIndex(pParse, 0, 0, pList, OP_Unique, 0, 0);
		pList = 0;
	}

primary_key_exit:
	eDbIdListDelete(pList);
	return;
}

/*
** Return the appropriate collating type given a type name.
**
** The collation type is text (eDb_SO_TEXT) if the type
** name contains the character stream "text" or "char".  
** the type is eDb_SO_DEC if name contains the character stream "decimal"
** Any other type name is collated as numeric(eDb_SO_NUM).
*/
int eDbCollateType(const char *zType, int nType){
	int i;
	for(i=0; i<nType-3; i++){
		int c = *(zType++) | 0x60;
		if( c=='c' && eDbStrNICmp(zType, "har", 3)==0 ){
			return eDb_SO_TEXT;
		}
		if( c=='v' && eDbStrNICmp(zType, "archar", 6)==0 ){
			return eDb_SO_TEXT;
		}		
		if( c=='t' && eDbStrNICmp(zType, "ext", 3)==0 ){
			return eDb_SO_TEXT;
		}
		if( c=='i' && eDbStrNICmp(zType, "nt", 2)==0 ){
			return eDb_SO_NUM;
		}
		if( c=='d' && eDbStrNICmp(zType, "ecimal", 6)==0 ){
			return eDb_SO_DEC;
		}
	}
	return eDb_SO_NUM;
}

void eDbEndTable(Parser *pParse, Token *pEnd){
	Table *p;
	ParseResult *pRes;
	eDb *db = pParse->db;
	pParse->pResult = 0;

	if( (pEnd==0) || pParse->nErr || eDb_malloc_failed ) return;
	p = pParse->pNewTable;
	if( p==0 ) return;

	/* 
	** Add the table to hash table.
	*/
	if( pParse->explain==0 && pParse->nErr==0 ){
		Table *pOld;	
		pOld = eDbHashInsert(&db->tblHash, 
								p->zName, strlen(p->zName)+1, p);
		if( pOld ){
			/*
			** error occured while inserting intto hash table
			*/
			return;
		}
		/* need to do create table*/	
		pParse->pNewTable = 0;
		db->nTable++;
		pRes = eDbMalloc(sizeof(ParseResult));
		pRes->pTable = p;
		pRes->op = Op_CreateTable;
		pParse->pResult = pRes;
	}
}

/*
** Given a token, look up a table with that name.  If not found, leave
** an error for the parser to find and return NULL.
*/
Table *eDbTableFromToken(Parser *pParse, Token *pTok){
	char *zName;
	Table *pTab;
	zName = eDbTableNameFromToken(pTok);
	if( zName==0 ) return 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -