📄 subsql.cpp
字号:
}
return true;
}
bool dbSubSql::updateTable(bool create)
{
int tkn;
dotIsPartOfIdentifier = true;
if (!expect("table name", tkn_ident) || !expect("(", tkn_lpar)) {
return false;
}
char* name = this->name;
int varyingLength = strlen(name)+1;
static const struct {
int size;
int alignment;
} typeDesc[] = {
{ sizeof(bool), sizeof(bool) },
{ sizeof(int1), sizeof(int1) },
{ sizeof(int2), sizeof(int2) },
{ sizeof(int4), sizeof(int4) },
{ sizeof(db_int8), sizeof(db_int8) },
{ sizeof(real4), sizeof(real4) },
{ sizeof(real8), sizeof(real8) },
{ sizeof(dbVarying), 4 },
{ sizeof(oid_t), sizeof(oid_t) },
{ sizeof(dbVarying), 4 },
{0}, // tpMethodBool,
{0}, // tpMethodInt1,
{0}, // tpMethodInt2,
{0}, // tpMethodInt4,
{0}, // tpMethodInt8,
{0}, // tpMethodReal4,
{0}, // tpMethodReal8,
{0}, // tpMethodString,
{0}, // tpMethodReference,
{0}, // tpStructure,
{0}, // tpRawBinary,
{0}, // tpStdString,
{ sizeof(rectangle), sizeof(coord_t) }, // tpRectangle,
{0} // tpUnknown
};
const int maxFields = 256;
tableField fields[maxFields];
int nFields = 0;
int nColumns = 0;
tkn = tkn_comma;
while (tkn == tkn_comma) {
if (nFields+1 == maxFields) {
error("Too many fields");
break;
}
if (!expect("field name", tkn_ident)) {
break;
}
int nameLen = strlen(buf)+1;
fields[nFields].name = new char[nameLen];
strcpy(fields[nFields].name, buf);
varyingLength += nameLen + 2;
char* refTableName;
char* inverseRefName;
int type = parseType(refTableName, inverseRefName);
fields[nFields++].type = type;
if (type == dbField::tpUnknown) {
break;
}
nColumns += 1;
if (type == dbField::tpArray) {
if (nFields+1 == maxFields) {
error("Too many fields");
break;
}
fields[nFields].name = new char[nameLen+2];
sprintf(fields[nFields].name, "%s[]", fields[nFields-1].name);
varyingLength += nameLen+2+2;
type = parseType(refTableName, inverseRefName);
if (type == dbField::tpUnknown) {
break;
}
if (type == dbField::tpArray) {
error("Arrays of arrays are not supported by CLI");
break;
}
if (type == dbField::tpReference) {
fields[nFields].refTableName = refTableName;
varyingLength += strlen(refTableName);
if (inverseRefName != NULL) {
fields[nFields-1].inverseRefName = inverseRefName;
varyingLength += strlen(inverseRefName);
}
}
fields[nFields++].type = type;
} else if (type == dbField::tpReference) {
fields[nFields-1].refTableName = refTableName;
varyingLength += strlen(refTableName);
if (inverseRefName != NULL) {
fields[nFields-1].inverseRefName = inverseRefName;
varyingLength += strlen(inverseRefName);
}
}
tkn = scan();
}
if (tkn == tkn_rpar) {
beginTransaction(dbExclusiveLock);
dbTableDescriptor* oldDesc = findTable(name);
if (oldDesc != NULL) {
if (create) {
error("Table already exists");
return false;
}
} else {
if (!create) {
error("Table not found");
return false;
}
}
dbTable* table;
oid_t oid;
if (create) {
modified = true;
oid = allocateRow(dbMetaTableId,
sizeof(dbTable) + sizeof(dbField)*nFields + varyingLength);
table = (dbTable*)getRow(oid);
} else {
oid = oldDesc->tableId;
table = (dbTable*)new char[sizeof(dbTable) + sizeof(dbField)*nFields + varyingLength];
}
int offs = sizeof(dbTable) + sizeof(dbField)*nFields;
table->name.offs = offs;
table->name.size = strlen(name)+1;
strcpy((char*)table + offs, name);
offs += table->name.size;
size_t size = sizeof(dbRecord);
table->fields.offs = sizeof(dbTable);
dbField* field = (dbField*)((char*)table + table->fields.offs);
offs -= sizeof(dbTable);
bool arrayComponent = false;
for (int i = 0; i < nFields; i++) {
field->name.offs = offs;
field->name.size = strlen(fields[i].name) + 1;
strcpy((char*)field + offs, fields[i].name);
offs += field->name.size;
field->tableName.offs = offs;
if (fields[i].refTableName) {
field->tableName.size = strlen(fields[i].refTableName) + 1;
strcpy((char*)field + offs, fields[i].refTableName);
offs += field->tableName.size;
} else {
field->tableName.size = 1;
*((char*)field + offs++) = '\0';
}
field->inverse.offs = offs;
if (fields[i].inverseRefName) {
field->inverse.size = strlen(fields[i].inverseRefName) + 1;
strcpy((char*)field + offs, fields[i].inverseRefName);
offs += field->inverse.size;
} else {
field->inverse.size = 1;
*((char*)field + offs++) = '\0';
}
field->flags = 0;
field->type = fields[i].type;
field->size = typeDesc[fields[i].type].size;
if (!arrayComponent) {
size = DOALIGN(size, typeDesc[fields[i].type].alignment);
field->offset = size;
size += field->size;
} else {
field->offset = 0;
}
field->hashTable = 0;
field->tTree = 0;
arrayComponent = field->type == dbField::tpArray;
field += 1;
offs -= sizeof(dbField);
}
table->fields.size = nFields;
table->fixedSize = size;
table->nRows = 0;
table->nColumns = nColumns;
table->firstRow = 0;
table->lastRow = 0;
if (create) {
linkTable(new dbTableDescriptor(table), oid);
} else {
dbTableDescriptor* newDesc = new dbTableDescriptor(table);
delete[] (char*)table;
dbTable* oldTable = (dbTable*)getRow(oid);
if (!newDesc->equal(oldTable)) {
bool saveConfirmDeleteColumns = confirmDeleteColumns;
confirmDeleteColumns = true;
modified = true;
schemeVersion += 1;
unlinkTable(oldDesc);
if (oldTable->nRows == 0) {
updateTableDescriptor(newDesc, oid);
} else {
reformatTable(oid, newDesc);
}
delete oldDesc;
confirmDeleteColumns = saveConfirmDeleteColumns;
}
}
completeDescriptorsInitialization();
}
return tkn == tkn_rpar;
}
int dbSubSql::parseType(char*& refTableName, char*& inverseFieldName)
{
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:
if (expect("to", tkn_to) && expect("referenced table name", tkn_ident)) {
refTableName = new char[strlen(buf)+1];
strcpy(refTableName, buf);
int tkn = scan();
if (tkn == tkn_inverse) {
if (!expect("inverse reference field name", tkn_ident)) {
return dbField::tpUnknown;
}
inverseFieldName = new char[strlen(buf)+1];
strcpy(inverseFieldName, buf);
} else {
inverseFieldName = NULL;
ungetToken = tkn;
}
return dbField::tpReference;
} else {
return dbField::tpUnknown;
}
case tkn_rectangle:
return dbField::tpRectangle;
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);
delete[] buf;
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);
delete[] buf;
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("#%lx", (unsigned long)*(oid_t*)(base + fd->dbsOffs));
continue;
case dbField::tpRectangle:
{
int i, sep = '(';
rectangle& r = *(rectangle*)(base + fd->dbsOffs);
for (i = 0; i < rectangle::dim*2; i++) {
printf("%c%f", sep, (double)r.boundary[i]);
sep = ',';
}
printf(")");
}
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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -