subsql.cpp

来自「一个功能强大的内存数据库源代码,c++编写,有详细的注释」· C++ 代码 · 共 1,947 行 · 第 1/4 页

CPP
1,947
字号
int dbSubSql::parseType(){    switch (scan()) {       case tkn_bool:	return dbField::tpBool;      case tkn_int1:	return dbField::tpInt1;      case tkn_int2:	return dbField::tpInt2;      case tkn_int4:	return dbField::tpInt4;      case tkn_int8:	return dbField::tpInt8;      case tkn_real4:	return dbField::tpReal4;      case tkn_real8:	return dbField::tpReal8;      case tkn_array:	return expect("of", tkn_of) ? dbField::tpArray : dbField::tpUnknown;      case tkn_string:	return dbField::tpString;      case tkn_reference:	return 	    expect("to", tkn_to) && expect("referenced table name", tkn_ident) 	    ? dbField::tpReference : dbField::tpUnknown;      default:	error("Field type expected");    }    return dbField::tpUnknown;}int dbSubSql::readExpression(){    int i, ch;    for (i = 0; (ch = get()) != ';' && ch != ',' && ch != EOF; i++) { 	if (i+1 >= buflen) { 	    char* newbuf = new char[buflen*2];	    memcpy(newbuf, buf, buflen);	    buf = newbuf;	    buflen *= 2;	}	buf[i] = ch;    }    buf[i] = '\0';    return ch;}bool dbSubSql::readCondition(){    int i, ch;    for (i = 0; (ch = get()) != ';' && ch !=  EOF; i++) { 	if (i+1 >= buflen) { 	    char* newbuf = new char[buflen*2];	    memcpy(newbuf, buf, buflen);	    buf = newbuf;	    buflen *= 2;	}	buf[i] = ch;    }    buf[i] = '\0';    if (ch != ';') { 	error("unexpected end of input");	return false;    }     return true;}void dbSubSql::dumpRecord(byte* base, dbFieldDescriptor* first){    int i, n;    byte* elem;    dbFieldDescriptor* fd = first;    do { 	if (fd != first) { 	    printf(", ");	}	switch (fd->type) { 	  case dbField::tpBool:	    printf("%s", *(bool*)(base + fd->dbsOffs) 		   ? "true" : "false");	    continue;	  case dbField::tpInt1:	    printf("%d", *(int1*)(base + fd->dbsOffs)); 	    continue;	    	  case dbField::tpInt2:	    printf("%d", *(int2*)(base + fd->dbsOffs)); 	    continue;	  case dbField::tpInt4:	    printf("%d", *(int4*)(base + fd->dbsOffs)); 	    continue;	  case dbField::tpInt8:	    printf(INT8_FORMAT,	*(db_int8*)(base + fd->dbsOffs)); 	    continue;	  case dbField::tpReal4:	    printf("%f", *(real4*)(base + fd->dbsOffs)); 	    continue;	  case dbField::tpReal8:	    printf("%f", *(real8*)(base + fd->dbsOffs)); 	    continue;	  case dbField::tpString:	    printf("'%s'", (char*)base+((dbVarying*)(base+fd->dbsOffs))->offs);	    continue;	  case dbField::tpReference:	    printf("#%x", *(oid_t*)(base + fd->dbsOffs)); 	    continue;	  case dbField::tpRawBinary:	    n = fd->dbsSize;	    elem = base + fd->dbsOffs;	    printf("(");	    for (i = 0; i < n; i++) { 		if (i != 0) { 		    printf(", ");		}		printf("%02x", *elem++);	    }	    printf(")");	    continue;	  case dbField::tpArray:	    n = ((dbVarying*)(base + fd->dbsOffs))->size;	    elem = base + ((dbVarying*)(base + fd->dbsOffs))->offs;	    printf("(");	    for (i = 0; i < n; i++) { 		if (i != 0) { 		    printf(", ");		}		dumpRecord(elem, fd->components);		elem += fd->components->dbsSize;	    }	    printf(")");	    continue;	  case dbField::tpStructure:	    printf("(");	    dumpRecord(base, fd->components);	    printf(")");	}    } while ((fd = fd->next) != first);}int dbSubSql::calculateRecordSize(dbList* node, int offs, 				  dbFieldDescriptor* first){    dbFieldDescriptor* fd = first;    do { 	if (node == NULL) { 	    return -1;	}	if (fd->type == dbField::tpArray) { 	    if (node->type != dbList::nTuple) { 		return -1;	    }	    int nElems = node->aggregate.nComponents;	    offs = DOALIGN(offs, fd->components->alignment) 		 + nElems*fd->components->dbsSize;	    if (fd->attr & dbFieldDescriptor::HasArrayComponents) {		dbList* component = node->aggregate.components;		while (--nElems >= 0) { 		    int d = calculateRecordSize(component,offs,fd->components);		    if (d < 0) return d;		    offs = d;		    component = component->next;		}	    } 	} else if (fd->type == dbField::tpString) { 	    if (node->type != dbList::nString) { 		return -1;	    }	    offs += strlen(node->sval) + 1;	} else if (fd->type == dbField::tpRawBinary) { 	    if (node->type != dbList::nTuple) { 		return -1;	    }	    int nElems = node->aggregate.nComponents;	    dbList* component = node->aggregate.components;	    if (size_t(nElems) > fd->dbsSize) { 		return -1;	    }	    while (--nElems >= 0) { 		if (component->type != dbList::nInteger		    || (component->ival & ~0xFF) != 0) 		{ 		    return -1;		}		component = component->next;	    }	} else { 	    if (!((node->type == dbList::nBool && fd->type == dbField::tpBool)		  || (node->type == dbList::nInteger 		      && (fd->type == dbField::tpInt1			  || fd->type == dbField::tpInt2			  || fd->type == dbField::tpInt4			  || fd->type == dbField::tpInt8			  || fd->type == dbField::tpReference))		  || (node->type == dbList::nReal 		      && (fd->type == dbField::tpReal4			  || fd->type == dbField::tpReal8))		  || (node->type == dbList::nTuple 		      && fd->type == dbField::tpStructure)))	    {		return -1;	    }	    if (fd->attr & dbFieldDescriptor::HasArrayComponents) {		int d = calculateRecordSize(node->aggregate.components,					    offs, fd->components);		if (d < 0) return d;		offs = d;	    }	}	node = node->next;    } while ((fd = fd->next) != first);    return offs;    }bool dbSubSql::isValidOid(oid_t oid) {    return oid == 0 || 	(oid < currIndexSize && (currIndex[oid] & (dbFreeHandleMarker|dbInternalObjectMarker)) == 0);}int dbSubSql::initializeRecordFields(dbList* node, byte* dst, int offs, 				     dbFieldDescriptor* first){    dbFieldDescriptor* fd = first;    dbList* component;    byte* elem;    int len, elemOffs, elemSize;    do { 	if (node->type == dbList::nString && fd->type != dbField::tpString) { 	    char* s = node->sval;	    long  ival;	    switch (fd->type) {	      case dbField::tpBool:		*(bool*)(dst+fd->dbsOffs) = *s == '1' || *s == 't' || *s == 'T';		break;	      case dbField::tpInt1:		if (sscanf(s, "%ld", &ival) != 1) { 		    return -1;		}		*(int1*)(dst+fd->dbsOffs) = (int1)ival;	      case dbField::tpInt2:		if (sscanf(s, "%ld", &ival) != 1) { 		    return -1;		}		*(int2*)(dst+fd->dbsOffs) = (int2)ival;	      case dbField::tpInt4:		if (sscanf(s, "%ld", &ival) != 1) { 		    return -1;		}		*(int4*)(dst+fd->dbsOffs) = (int4)ival;	      case dbField::tpInt8:		if (sscanf(s, "%ld", &ival) != 1) { 		    return -1;		}		*(db_int8*)(dst+fd->dbsOffs) = ival;		break;	      case dbField::tpReal4:		if (sscanf(s, "%f", (real4*)(dst+fd->dbsOffs)) != 1) { 		    return -1;		}		break;	      case dbField::tpReal8:		if (sscanf(s, "%lf", (real8*)(dst+fd->dbsOffs)) != 1) { 		    return -1;		}		break;	    }#ifdef AUTOINCREMENT_SUPPORT	} else if (node->type == dbList::nAutoinc) {	    	    if (fd->type != dbField::tpInt4) {		*(int4*)(dst+fd->dbsOffs) = fd->defTable->autoincrementCount;	    } else { 		return -1;	    }#endif	} else { 	    switch (fd->type) { 	      case dbField::tpBool:		*(bool*)(dst+fd->dbsOffs) = node->bval;		break;	      case dbField::tpInt1:		*(int1*)(dst+fd->dbsOffs) = (int1)node->ival;		break;	      case dbField::tpInt2:		*(int2*)(dst+fd->dbsOffs) = (int2)node->ival;		break;	      case dbField::tpInt4:		*(int4*)(dst+fd->dbsOffs) = (int4)node->ival;		break;	      case dbField::tpInt8:		*(db_int8*)(dst+fd->dbsOffs) = node->ival;		break;	      case dbField::tpReal4:		*(real4*)(dst+fd->dbsOffs) = (real4)node->fval;		break;	      case dbField::tpReal8:		*(real8*)(dst+fd->dbsOffs) = node->fval;		break;	      case dbField::tpReference:		if (isValidOid(node->ival)) { 		    		    *(oid_t*)(dst+fd->dbsOffs) = (oid_t)node->ival;		} else { 		    return -1;		}		break;	      case dbField::tpString:		((dbVarying*)(dst+fd->dbsOffs))->offs = offs;		len = strlen(node->sval) + 1;		((dbVarying*)(dst+fd->dbsOffs))->size = len;		memcpy(dst + offs, node->sval, len);		offs += len;		break;	      case dbField::tpRawBinary:		len = node->aggregate.nComponents;		component = node->aggregate.components;		elem = dst + fd->dbsOffs;		while (--len >= 0) { 		    *elem++ = (byte)component->ival;		    component = component->next;		}		break;	      case dbField::tpArray:		len = node->aggregate.nComponents;		elem = (byte*)DOALIGN(long(dst) + offs, fd->components->alignment);		offs = elem - dst;		((dbVarying*)(dst+fd->dbsOffs))->offs = offs;		((dbVarying*)(dst+fd->dbsOffs))->size = len;		elemSize = fd->components->dbsSize;  		elemOffs = len*elemSize;		offs += elemOffs;		component = node->aggregate.components;		while (--len >= 0) { 		    elemOffs = initializeRecordFields(component, elem, elemOffs, 						      fd->components);		    elemOffs -= elemSize;		    elem += elemSize;		    component = component->next;		}		offs += elemOffs;		break;	      case dbField::tpStructure:		offs = initializeRecordFields(node->aggregate.components, 					      dst, offs, fd->components);	    }	}	node = node->next;    } while ((fd = fd->next) != first);    return offs;}bool dbSubSql::insertRecord(dbList* list, dbTableDescriptor* desc){    int size = calculateRecordSize(list, desc->fixedSize, desc->columns);    if (size < 0) { 	error("Incompatible types in insert statement");	return false;    }    oid_t oid = allocateRow(desc->tableId, size);    byte* dst = (byte*)getRow(oid);        initializeRecordFields(list, dst, desc->fixedSize, desc->columns);    int nRows = ((dbTable*)getRow(desc->tableId))->nRows;    dbFieldDescriptor* fd;    for (fd = desc->hashedFields; fd != NULL; fd = fd->nextHashedField){	dbHashTable::insert(this, fd->hashTable, oid, fd->type, fd->dbsSize, fd->dbsOffs, 			    nRows);    }    for (fd = desc->indexedFields; fd != NULL; fd = fd->nextIndexedField) { 	dbTtree::insert(this, fd->tTree, oid, fd->type, fd->dbsSize, fd->comparator, fd->dbsOffs);    }        return true;}int dbSubSql::readValues(dbList** chain){    int i, n = 0;    int tkn;    dbList* node;    while (true) { 	switch (scan()) { 	  case tkn_lpar:	    node = new dbList(dbList::nTuple);	    node->aggregate.components = NULL;	    i = readValues(&node->aggregate.components);	    if (i < 0) { 		return -1;	    }	    node->aggregate.nComponents = i;	    break;	  case tkn_rpar:	    return -n; // valid only in case of empty list	  case tkn_iconst:	    node = new dbList(dbList::nInteger);	    node->ival = ival;	    break;	  case tkn_true:	    node = new dbList(dbList::nBool);	    node->bval = true;	    break;	  case tkn_false:	    node = new dbList(dbList::nBool);	    node->bval = false;	    break;	    	  case tkn_fconst:	    node = new dbList(dbList::nReal);	    node->fval = fval;	    break;	  case tkn_sconst:	    node = new dbList(dbList::nString);	    node->sval = new char[strlen(buf)+1];	    strcpy(node->sval, buf);	    break;	  case tkn_autoincrement:	    node =  new dbList(dbList::nAutoinc);	    break;	  case tkn_error:	    return -1;	  default:	    error("Syntax error in insert list");	    return -1;	}	*chain = node;	chain = &node->next;	n += 1;	if ((tkn = scan()) == tkn_rpar) { 	    return n;	}	if (tkn != tkn_comma) {   	    error("',' expected");	    return -1;	}    }}dbFieldDescriptor* dbSubSql::readFieldName(){    int tkn;    if (expect("table name", tkn_ident)) { 	dbTableDescriptor* desc;	dbFieldDescriptor* fd;	if ((desc = findTable(name)) == NULL) { 	    error("No such table in database");	    return NULL;	}		if (expect(".", tkn_dot) && expect("field name", tkn_ident)) { 	    if ((fd = desc->findSymbol(name)) == NULL) { 		error("No such field in the table");		return NULL;	    } else if (fd->type == dbField::tpArray) { 			error("Array components can not be indexed");		return NULL;	    }	} else { 	    return NULL;	}	while ((tkn = scan()) != tkn_semi) { 	    if (tkn != tkn_dot) { 		error("'.' expected");		return NULL;	    }		    if (expect("field name", tkn_ident)) { 		if ((fd = fd->find(name)) == NULL) { 		    error("No such field in the table");		    return NULL;		} else if (fd->type == dbField::tpArray) { 			    error("Array components can not be indexed");		    return NULL;		}		    } else { 		return NULL;	    }	}	if (fd->type == dbField::tpStructure) { 	    error("Structures can not be indexed");	    return NULL;	} 	return fd;    }    return NULL;}

⌨️ 快捷键说明

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