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

📄 subsql.cpp

📁 实现内存数据库的源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
	    offs -= sizeof(dbField);
	}
	table->fields.size = nFields;
	table->fixedSize = size;
	table->nRows = 0;
	table->nColumns = nColumns;
	table->firstRow = 0;
	table->lastRow = 0;

	linkTable(new dbTableDescriptor(table), oid);
	if (!completeDescriptorsInitialization()) { 
	    error("Reference to undefined table");
	}
    }
    return tkn == tkn_rpar;
}

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,	*(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;    
}

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;
		}
		*(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:
		*(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:
		*(oid_t*)(dst+fd->dbsOffs) = 0;
		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->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 { 

⌨️ 快捷键说明

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