server.cpp

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

CPP
1,520
字号
    dbColumnBinding* cb;        stmt->firstFetch = false;    if (stmt->cursor->isEmpty()) { 	response = cli_not_found;	pack4(response);	return session->sock->write(&response, sizeof response);    }    int msg_size = sizeof(cli_oid_t) + 4;    char* data = (char*)db->getRow(stmt->cursor->currId);    for (cb = stmt->columns; cb != NULL; cb = cb->next) { 	if (cb->cliType == cli_autoincrement) {	    msg_size += 4;	} else if (cb->cliType >= cli_array_of_oid) { 	    msg_size += 4 + ((dbVarying*)(data + cb->fd->dbsOffs))->size		            * sizeof_type[cb->cliType - cli_array_of_oid];	} else if (cb->cliType >= cli_asciiz) { 	    msg_size += 4 + ((dbVarying*)(data + cb->fd->dbsOffs))->size;	} else { 	    msg_size += sizeof_type[cb->cliType];	}    }    if (stmt->buf_size < msg_size) { 	delete[] stmt->buf;	stmt->buf = new char[msg_size];	stmt->buf_size = msg_size;    }    char* p = stmt->buf;    p = pack4(p, msg_size);    p = pack_oid(p, stmt->cursor->currId);    for (cb = stmt->columns; cb != NULL; cb = cb->next) { 	char* src = data + cb->fd->dbsOffs;	switch (cb->fd->type) { 	  case dbField::tpBool:	  case dbField::tpInt1:	    switch (sizeof_type[cb->cliType]) { 	      case 1:		*p++ = *src;		break;	      case 2:		p = pack2(p, (int2)*(char*)src);		break;	      case 4:		p = pack4(p, (int4)*(char*)src);		break;	      case 8:		p = pack8(p, (db_int8)*(char*)src);		break;	      default:		assert(false);	    }	    break;			  case dbField::tpInt2:	    switch (sizeof_type[cb->cliType]) { 	      case 1:		*p++ = (char)*(int2*)src;		break;	      case 2:		p = pack2(p, src);		break;	      case 4:		p = pack4(p, (int4)*(int2*)src);		break;	      case 8:		p = pack8(p, (db_int8)*(int2*)src);		break;	      default:		assert(false);	    }	    break;	  case dbField::tpInt4:	    switch (sizeof_type[cb->cliType]) { 	      case 1:		*p++ = (char)*(int4*)src;		break;	      case 2:		p = pack2(p, (int2)*(int4*)src);		break;	      case 4:		p = pack4(p, src);		break;	      case 8:		p = pack8(p, (db_int8)*(int4*)src);		break;	      default:		assert(false);	    }	    break;	  case dbField::tpInt8:	    switch (sizeof_type[cb->cliType]) { 	      case 1:		*p++ = (char)*(db_int8*)src;		break;	      case 2:		p = pack2(p, (int2)*(db_int8*)src);		break;	      case 4:		p = pack4(p, (int4)*(db_int8*)src);		break;	      case 8:		p = pack8(p, src);		break;	      default:		assert(false);	    }	    break;	  case dbField::tpReal4:	    switch (cb->cliType) { 	      case cli_real4:		p = pack4(p, src);		break;	      case cli_real8:		{		    real8 temp = *(real4*)src;		    p = pack8(p, (char*)&temp);		}		break;	      default:		assert(false);	    }	    break;	  case dbField::tpReal8:	    switch (cb->cliType) { 	      case cli_real4:		{		    real4 temp = (real4)*(real8*)src;		    p = pack4(p, (char*)&temp);		}		break;	      case cli_real8:		p = pack8(p, src);		break;	      default:		assert(false);	    }	    break;	  case dbField::tpString:	    {		dbVarying* v = (dbVarying*)src;		p = pack4(p, v->size);		memcpy(p, data + v->offs, v->size);		p += v->size;	    }	    break;	  case dbField::tpReference:	    p = pack_oid(p, *(oid_t*)src);	    break;	  case dbField::tpArray:	    {		dbVarying* v = (dbVarying*)src;		int n = v->size;		p = pack4(p, n);		src = data + v->offs;		switch (sizeof_type[cb->cliType-cli_array_of_oid]) { 		  case 2:		    while (--n >= 0) { 			p = pack2(p, src);			src += 2;		    }		    break;		  case 4:		    while (--n >= 0) { 			p = pack4(p, src);			src += 4;		    }		    break;		  case 8:		    while (--n >= 0) { 			p = pack8(p, src);			src += 8;		    }		    break;		  default:		    memcpy(p, src, n);		    p += n;		}		break;	    }	  default:	    assert(false);	}    }    assert(p - stmt->buf == msg_size);    return session->sock->write(stmt->buf, msg_size);}    bool dbServer::remove(dbSession* session, int stmt_id){    dbStatement* stmt = findStatement(session, stmt_id);    int4 response;    if (stmt == NULL) { 	response = cli_bad_descriptor;    } else { 	if (stmt->cursor->isEmpty()) { 	    response = cli_not_found;	} else { 	    stmt->cursor->removeAllSelected();	    response = cli_ok;	}    }    pack4(response);    return session->sock->write(&response, sizeof response);}bool dbServer::update(dbSession* session, int stmt_id, char* new_data){    dbStatement* stmt = findStatement(session, stmt_id);    dbColumnBinding* cb;    int4 response;    if (stmt == NULL) { 	response = cli_bad_descriptor;	pack4(response);	return session->sock->write(&response, sizeof response);    }    if (stmt->cursor->isEmpty()) { 	response = cli_not_found;	pack4(response);	return session->sock->write(&response, sizeof response);    }    char* old_data = stmt->buf + sizeof(cli_oid_t) + 4;    for (cb = stmt->columns; cb != NULL; cb = cb->next) { 	cb->ptr = new_data;	if (cb->cliType >= cli_asciiz) { 	    int new_len = unpack4(new_data);	    int old_len = unpack4(old_data);	    cb->len = new_len;	    if (cb->fd->indexType & (HASHED|INDEXED) 		&& memcmp(new_data, old_data, new_len+4) != 0)	    {		cb->fd->attr |= dbFieldDescriptor::Updated;	    }	    if (cb->cliType >= cli_array_of_oid) { 		new_len *= sizeof_type[cb->cliType - cli_array_of_oid];		old_len *= sizeof_type[cb->cliType - cli_array_of_oid];	    }	    new_data += 4 + new_len;	    old_data += 4 + old_len;	} else { 	    int size = sizeof_type[cb->cliType];	    if (cb->fd->indexType & (HASHED|INDEXED) 		&& memcmp(new_data, old_data, size) != 0)	    {		cb->fd->attr |= dbFieldDescriptor::Updated;	    }	    	    new_data += size;	    old_data += size;	}    }    db->beginTransaction(dbDatabase::dbExclusiveLock);    dbRecord* rec = db->getRow(stmt->cursor->currId);    dbTableDescriptor* table = stmt->query.table;    dbFieldDescriptor *first = table->columns, *fd = first;    size_t offs = table->fixedSize;    do { 	if (fd->type == dbField::tpArray || fd->type == dbField::tpString) 	{ 	    int len = ((dbVarying*)((char*)rec + fd->dbsOffs))->size;	    for (cb = stmt->columns; cb != NULL; cb = cb->next) { 		if (cb->fd == fd) { 		    len = cb->len;		    break;		}	    }	    offs = DOALIGN(offs, fd->components->alignment)		+ len*fd->components->dbsSize;	}    } while ((fd = fd->next) != first);    old_data = new char[rec->size];    memcpy(old_data, rec, rec->size);    for (cb = stmt->columns; cb != NULL; cb = cb->next) { 	if (cb->fd->attr & dbFieldDescriptor::Updated) {	    	    if (cb->fd->indexType & HASHED) { 		dbHashTable::remove(db, cb->fd->hashTable, 				    stmt->cursor->currId,				    cb->fd->type, cb->fd->dbsSize, cb->fd->dbsOffs);	    }	    if (cb->fd->indexType & INDEXED) { 		dbTtree::remove(db, cb->fd->tTree, stmt->cursor->currId, 				cb->fd->type, cb->fd->dbsSize, cb->fd->comparator, cb->fd->dbsOffs);	    }	}    }        db->modified = true;    new_data = (char*)db->putRow(stmt->cursor->currId, offs);        fd = first;    offs = table->fixedSize;    do { 	if (fd->type == dbField::tpArray|| fd->type == dbField::tpString) 	{ 	    int len = ((dbVarying*)(old_data + fd->dbsOffs))->size;	    offs = DOALIGN(offs, fd->components->alignment);	    for (cb = stmt->columns; cb != NULL; cb = cb->next) { 		if (cb->fd == fd) { 		    len = cb->unpackArray(new_data, offs);		    break;		}	    }	    if (cb == NULL) { 		memcpy(new_data + offs, 		       old_data + ((dbVarying*)(old_data + fd->dbsOffs))->offs,		       len*fd->components->dbsSize);	    }	    ((dbVarying*)(new_data + fd->dbsOffs))->size = len;	    ((dbVarying*)(new_data + fd->dbsOffs))->offs = offs;	    offs += len*fd->components->dbsSize;	} else { 	    	    for (cb = stmt->columns; cb != NULL; cb = cb->next) { 		if (cb->fd == fd) { 		    cb->unpackScalar(new_data);		    break;		}	    }	    if (cb == NULL) { 		memcpy(new_data + fd->dbsOffs, old_data + fd->dbsOffs, 		       fd->dbsSize);	    }	}    } while ((fd = fd->next) != first);    delete[] old_data;    for (cb = stmt->columns; cb != NULL; cb = cb->next) { 	if (cb->fd->attr & dbFieldDescriptor::Updated) {	    	    cb->fd->attr &= ~dbFieldDescriptor::Updated;	    if (cb->fd->indexType & HASHED) { 		dbHashTable::insert(db, cb->fd->hashTable, 				    stmt->cursor->currId,				    cb->fd->type, cb->fd->dbsSize, cb->fd->dbsOffs, 0);	    }	    if (cb->fd->indexType & INDEXED) { 		dbTtree::insert(db, cb->fd->tTree, stmt->cursor->currId, 				cb->fd->type, cb->fd->dbsSize, cb->fd->comparator, cb->fd->dbsOffs);	    }	}    }    response = cli_ok;    pack4(response);    return session->sock->write(&response, sizeof response);}    	    char* dbServer::checkColumns(dbStatement* stmt, int n_columns, 			     dbTableDescriptor* desc, char* data, 			     int4& response){    dbColumnBinding** cpp = &stmt->columns;    response = cli_ok;    while (--n_columns >= 0) {	int cliType = *data++;	char* columnName = data;	dbSymbolTable::add(columnName, tkn_ident, true);    	dbFieldDescriptor* fd = desc->findSymbol(columnName);	data += strlen(data) + 1;	if (fd != NULL) { 	    if ((cliType == cli_oid 		 && fd->type == dbField::tpReference)		|| (cliType >= cli_bool && cliType <= cli_int8		    && fd->type >= dbField::tpBool 		    && fd->type <= dbField::tpInt8)		|| (cliType >= cli_real4 && cliType <= cli_real8 		    && fd->type >= dbField::tpReal4		    && fd->type <= dbField::tpReal8)		|| ((cliType == cli_asciiz || cliType == cli_pasciiz) 		    && fd->type == dbField::tpString)		|| (cliType == cli_array_of_oid && 		    fd->type == dbField::tpArray && 		    fd->components->type == dbField::tpReference)		|| (cliType >= cli_array_of_bool		    && fd->type  == dbField::tpArray		    && cliType-cli_array_of_bool 		    == fd->components->type-dbField::tpBool))	    {		dbColumnBinding* cb = new dbColumnBinding(fd, cliType);		*cpp = cb;		cpp = &cb->next;	    } else { 		response = cli_incompatible_type;		break;	    }	} else { 	    TRACE_MSG(("Field '%s' not found\n", columnName));	    response = cli_column_not_found;	    break;	}    }    return data;}bool dbServer::insert(dbSession* session, int stmt_id, char* data, bool prepare){    dbStatement* stmt = findStatement(session, stmt_id);    dbTableDescriptor* desc = NULL;    dbColumnBinding* cb;    int4   response;    char   reply_buf[sizeof(cli_oid_t) + 8];    char*  dst;    oid_t  oid = 0;    size_t offs;    int    n_columns;    if (stmt == NULL) { 	if (!prepare) { 	    response = cli_bad_statement;	    goto return_response;	}	stmt = new dbStatement(stmt_id);	stmt->next = session->stmts;	session->stmts = stmt;    } else {	if (prepare) { 	    stmt->reset();	} else if ((desc = stmt->table) == NULL) {	    response = cli_bad_descriptor;	    goto return_response;	}    }    if (prepare) { 	session->scanner.reset(data);	if (session->scanner.get() != tkn_insert 	    || session->scanner.get() != tkn_into	    || session->scanner.get() != tkn_ident) 	{	    response = cli_bad_statement;	    goto return_response;	}	desc = db->findTable(session->scanner.ident);	if (desc == NULL) { 		    response = cli_table_not_found;	    goto return_response;	}	data += strlen(data)+1;	n_columns = *data++;	data = checkColumns(stmt, n_columns, desc, data, response);	if (response != cli_ok) { 	    goto return_response;	}	stmt->table = desc;    }     offs = desc->fixedSize;    for (cb = stmt->columns; cb != NULL; cb = cb->next) { 	cb->ptr = data;	if (cb->cliType == cli_autoincrement) {	    ;	} else if (cb->cliType >= cli_asciiz) { 	    cb->len = unpack4(data);	    data += 4 + cb->len*cb->fd->components->dbsSize;	    offs = DOALIGN(offs, cb->fd->components->alignment)		 + cb->len*cb->fd->components->dbsSize;	} else { 	    data += sizeof_type[cb->cliType];	}    }    db->beginTransaction(dbDatabase::dbExclusiveLock);    db->modified = true;    oid = db->allocateRow(desc->tableId, offs);    dst = (char*)db->getRow(oid);            offs = desc->fixedSize;    for (cb = stmt->columns; cb != NULL; cb = cb->next) { 	dbFieldDescriptor* fd = cb->fd;	if (fd->type == dbField::tpArray || fd->type == dbField::tpString) {	    offs = DOALIGN(offs, fd->components->alignment);	    ((dbVarying*)(dst + fd->dbsOffs))->offs = offs;	    ((dbVarying*)(dst + fd->dbsOffs))->size = cb->len;	    offs += cb->unpackArray(dst, offs)*fd->components->dbsSize;	} else { 	    cb->unpackScalar(dst);	}    }    for (cb = stmt->columns; cb != NULL; cb = cb->next) { 	if (cb->fd->indexType & HASHED) { 	    dbHashTable::insert(db, cb->fd->hashTable, oid,				cb->fd->type, cb->fd->dbsSize, cb->fd->dbsOffs, 0);	}	if (cb->fd->indexType & INDEXED) { 	    dbTtree::insert(db, cb->fd->tTree, oid, 			    cb->fd->type, cb->fd->dbsSize, cb->fd->comparator, cb->fd->dbsOffs);	}    }    response = cli_ok;  return_response:    pack4(reply_buf, response);    if (desc == NULL) { 	pack4(reply_buf+4, 0);    } else { #ifdef AUTOINCREMENT_SUPPORT	pack4(reply_buf+4, desc->autoincrementCount);#else	pack4(reply_buf+4, ((dbTable*)db->getRow(desc->tableId))->nRows);#endif    }    pack_oid(reply_buf+8, oid);    return session->sock->write(reply_buf, sizeof reply_buf);}    bool dbServer::describe_table(dbSession* session, char const* table)

⌨️ 快捷键说明

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