subsql.cpp

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

CPP
1,947
字号
		if (expect("table name", tkn_ident)) { 		    desc = findTable(name);		    if (desc == NULL) { 			error("No such table in database");		    } else { 			dropTable(desc);			if (desc == existedTables) { 			    existedTables = desc->nextDbTable;			}			unlinkTable(desc);			desc->nextDbTable = droppedTables;			droppedTables = desc;		    }		}		continue;	      case tkn_hash:		fd = readFieldName();		if (fd != NULL) { 		    if (fd->hashTable == 0) { 			error("This field is not hashed");		    } else { 			dropHashTable(fd);		    }		}		continue;	      case tkn_index:		fd = readFieldName();		if (fd != NULL) { 		    if (fd->tTree == 0) { 			error("There is no index for this field");		    } else { 			dropIndex(fd);		    }		}		continue;	      default:		error("Expecting 'table', 'hash' or 'index' keyword");	    }	    continue;	  case tkn_backup:	    if (!opened) { 		error("Database not opened");		continue;	    }	    compactify = false;	    if ((tkn = scan()) == tkn_compactify) {		compactify = true;		tkn = scan();	    }	    if (tkn != tkn_sconst) { 		 error("Backup file name expected");	    } else { 		if (!backup(buf, compactify)) { 		    printf("Backup failed\n");		} else { 		    while (droppedTables != NULL) { 			dbTableDescriptor* next = droppedTables->nextDbTable;			delete droppedTables; 			droppedTables = next;		    }		    commit();		    existedTables = tables;		}	    }	    continue;	    	  case tkn_create:	    if (!opened) { 		error("Database not opened");		continue;	    }	    if (monitor->users != 1) { 		error("Can not perform operation with active appliations\n");		continue;	    }	    switch (scan()) { 	      case tkn_hash:		if (!expect("on", tkn_on)) { 		    continue;		}		fd = readFieldName();		if (fd != NULL) { 		    if (fd->hashTable != 0) { 			error("This field is already hashed");		    } else { 			createHashTable(fd);		    }		}		continue;	      case tkn_index:		if (!expect("on", tkn_on)) { 		    continue;		}		fd = readFieldName();		if (fd != NULL) { 		    if (fd->tTree != 0) { 			error("Index already exists");		    } else { 			createIndex(fd);		    }		}		continue;			      case tkn_table:		createTable();		continue;	      default:		error("Expecting 'table', 'hash' or 'index' keyword");	    }	    continue;	  case tkn_insert:	    if (!opened) { 		error("Database not opened");		continue;	    }	    if (expect("into", tkn_into) && expect("table name", tkn_ident)) {		if ((desc = findTable(name)) == NULL) { 		    error("No such table in database");		    continue;		}		if (!expect("values", tkn_values)) { 		    continue;		}		beginTransaction(dbExclusiveLock);		modified = true;		while (expect("(", tkn_lpar)) { 		    dbList* list = NULL;		    int n = readValues(&list);		    if (n <= 0 || !insertRecord(list, desc)) { 			if (n == 0) { 			    error("Empty fields list");			}			tkn = tkn_semi; // just avoid extra error messages		    } else { 			tkn = scan();		    }		    while (list != NULL) { 			dbList* tail = list->next;			delete list;			list = tail;		    }		    if (tkn == tkn_semi) { 			break;		    } else if (tkn != tkn_comma) { 			error("';' or ',' expected");		    }		}	    }	    continue;	  case tkn_delete:	    if (!opened) { 		error("Database not opened");		continue;	    }	    if (expect("FROM", tkn_from) && expect("table name", tkn_ident)) {                if ((desc = findTable(name)) == NULL) {                    error("No such table in database");                    continue;                }                 dbAnyCursor cursor(*desc, dbCursorForUpdate, NULL);                dbDatabaseThreadContext* ctx = threadContext.get();                ctx->interactive = true;                ctx->catched = true;        #ifdef THROW_EXCEPTION_ON_ERROR                try {#else                if (setjmp(ctx->unwind) == 0) {#endif                    if (readCondition()) {                        query = buf;                        cursor.reset();                        select(&cursor, query);                        if (!query.compiled()) {                            dbExprNode::cleanup();                            ctx->catched = false;                            continue;                        }                    } else {                        ctx->catched = false;                        continue;                    }                    int n_deleted = cursor.getNumberOfRecords();                    cursor.removeAllSelected();                    printf("\n\t%d records deleted\n", n_deleted);#ifdef THROW_EXCEPTION_ON_ERROR                } catch(dbException const&) {}#else                } else {                     if (query.mutexLocked) {                         query.mutexLocked = false;                        query.mutex.unlock();                    }                }#endif                if (!modified) {                     commit(); // release locks                }                ctx->catched = false;            }	    continue;	  case tkn_commit:	    if (!opened) { 		error("Database not opened");	    } else { 		while (droppedTables != NULL) { 		    dbTableDescriptor* next = droppedTables->nextDbTable;		    delete droppedTables; 		    droppedTables = next;		}		commit();		existedTables = tables;	    }	    continue;	  case tkn_rollback:	    if (!opened) { 		error("Database not opened");	    } else { 		while (droppedTables != NULL) { 		    dbTableDescriptor* next = droppedTables->nextDbTable;		    linkTable(droppedTables, droppedTables->tableId); 		    droppedTables = next;		}		rollback();		while (tables != existedTables) { 		    dbTableDescriptor* table = tables;		    unlinkTable(table);		    delete table;		}	    } 	    continue;	  case tkn_show:	    if (!opened) { 		error("Database not opened");	    } else { 		printf("Database file size: %lu Kb\n"		       "Object index size : %lu handles\n"		       "Used part of index: %lu handles\n"		       "Number of users   : %d\n"		       "Number of readers : %d\n" 		       "Number of writers : %d\n" 		       "Number of blocked readers : %d\n" 		       "Number of blocked writers : %d\n", 		       (unsigned long)(header->size/1024),		       (unsigned long)header->root[1-header->curr].indexSize, 		       (unsigned long)header->root[1-header->curr].indexUsed,		       monitor->users,		       monitor->nReaders,		       monitor->nWriters,		       monitor->nWaitReaders,		       monitor->nWaitWriters + monitor->waitForUpgrade);		printf("\nTABLES:\n");		printf("OID       FixedSize   Fields  Columns  TableName\n");		printf("---------------------------------------------------------\n");		for (dbTableDescriptor* desc=tables; desc != NULL; desc=desc->nextDbTable)		{ 		    printf("0x%06x  %8d %8d %8d   %s\n",			   desc->tableId, desc->fixedSize,			   desc->nFields, desc->nColumns, desc->name);		}	    } 	    continue;		        	  case tkn_describe:	    if (!opened) {		error("Database not opened");		continue;	    }		    if (expect("table name", tkn_ident)) {		if ((desc = findTable(name)) == NULL) {		    error("No such table in database");		    continue;		}                printf("\nOID=0x%06x, TableName=%s\n",desc->tableId, desc->name);                printf("FieldNo  FieldType        RefTableName     FieldName\n");                printf("----------------------------------------------------\n");                dbFieldDescriptor* fd = desc->columns; 		for (int i = desc->nColumns; --i >= 0;) { 		    printf("%6d   %-16s %-16s %s\n", fd->fieldNo, 			   typeMnem[fd->type],			   fd->refTableName ? fd->refTableName : "(null)", 			   fd->name);		    fd = fd->next;                }	    }	    continue;	  case tkn_help:	    fprintf(stderr, "SubSQL commands:\n\n\open 'database-name' ( 'database-file-name' ) ';'\n\select ('*') from <table-name> where <condition> ';'\n\update <table-name> set <field-name> '=' <expression> {',' <field-name> '=' <expression>} where <condition> ';'\n\create  <table-name> '('<field-name> <field-type> {',' <field-name> <field-type>}')' ';' \n\delete from <table-name>\n\drop table <table-name>\n\drop index <table-name> {'.' <field-name>} ';'\n\create index on <table-name> {'.' <field-name>} ';'\n\drop hash <table-name> {'.' <field-name>};\n\create hash on <table-name> {'.' <field-name>}field> ';'\n\insert into <table-name> values '(' <value>{',' <value>} ')' ';'\n\backup [compactify] 'file-name'\n\start server URL number-of-threads\n\stop server URL\n\describe <table-name>\n\show\n\commit\n\rollback\n\exit\n\help\n\n");	    continue;	  case tkn_start:	    if (!opened) { 		error("Database not opened");	    } else { 		commit(); // allow server threads to process		existedTables = tables;		if (expect("server", tkn_server) 		    && expect("server URL", tkn_sconst))		{#if !THREADS_SUPPORTED		    error("Database was build without pthread support");#else		    dbServer* server = dbServer::find(buf);		    if (server == NULL) { 			char* serverURL = new char[strlen(buf)+1];			strcpy(serverURL, buf);			if (expect("number of threads", tkn_iconst)) { 			    server = new dbServer(this, serverURL, (int)ival);			    printf("Server started for URL %s\n", serverURL);			}			delete[] serverURL;		    }		    if (server != NULL) { 			server->start();		    }#endif		}	    }	    continue;	  case tkn_stop:	    if (expect("server", tkn_server) 		&& expect("server URL", tkn_sconst))	    {#if !THREADS_SUPPORTED		error("Database was build without pthread support");#else		dbServer* server = dbServer::find(buf);		if (server != NULL) { 		    server->stop();		    printf("Server stopped for URL %s\n", buf);		} else { 		    fprintf(stderr, "No server was started for URL %s\n", buf);		}#endif	    }	    continue;	  case tkn_semi:	    putchar('\n');	    // no break	  case tkn_error:	    continue;	  case tkn_exit:	    return false;	  case tkn_eof:	    return true;	  default:	    error("Unexpected token");	}    }}	    void dbSubSql::handleError(dbErrorClass error, char const* msg, int arg){    dbDatabaseThreadContext* ctx = threadContext.get();    if (ctx == NULL || ctx->interactive) { 	const int screenWidth = 80;	int col;	switch (error) { 	  case QueryError:	    col = arg % screenWidth;	    if (in == stdin) { 		while (--col >= 0) putc('-', stderr);		fprintf(stderr, "^\n%s\n", msg);	    } else { 		fprintf(stderr, "%s at line %d position %d\n", msg, line, arg);	    }	    break;	  case ArithmeticError:	    fprintf(stderr, "%s\n", msg);	    break;	  case IndexOutOfRangeError:	    fprintf(stderr, "Index %d is out of range\n", arg);	    break;	  case NullReferenceError:	    fprintf(stderr, "Null object reference is accessed\n");	    break;	  default:	    dbDatabase::handleError(error, msg, arg);	}	//	// Recovery	//	if (in == stdin) { 	    int ch;	    while ((ch = get()) != '\n' && ch != EOF); 	} else { 	    fseek(in, 0, SEEK_END);	}    }#ifdef THROW_EXCEPTION_ON_ERROR    throw dbException(error, msg, arg);#else    if (ctx != NULL) { 	if (ctx->catched) {		    longjmp(ctx->unwind, error);	} else { 	    abort();	}    }#endif}void dbSubSql::run(int argc, char* argv[]){    for (int i = 1; i < argc; i++) {         in = fopen(argv[i], "r");	if (in == NULL) { 	    fprintf(stderr, "Failed to open '%s' file\n", argv[i]);	} else { 	    if (!parse()) { 		if (opened) { 		    close();		}#if THREADS_SUPPORTED		dbServer::cleanup();#endif		return;	    }	}    }    in = stdin;    parse();    if (opened) { 	close();    }#if THREADS_SUPPORTED    dbServer::cleanup();#endif}int main(int argc, char* argv[]) {    printf("SubSQL interactive utility for FastDB\n"	   "Type 'help' for more information\n");    char* subsqlAccessType = getenv("SUBSQL_ACCESS_TYPE");        dbDatabase::dbAccessType accessType = dbDatabase::dbAllAccess;    if (subsqlAccessType != NULL) {         if (strcmp(subsqlAccessType, "read-only") == 0) {             accessType = dbDatabase::dbReadOnly;        } else if (strcmp(subsqlAccessType, "concurrent-read") == 0) {             accessType = dbDatabase::dbConcurrentRead;        } else if (strcmp(subsqlAccessType, "concurrent-update") == 0) {             accessType = dbDatabase::dbConcurrentUpdate;        } else if (strcmp(subsqlAccessType, "normal") && strcmp(subsqlAccessType, "all-access")                    && strcmp(subsqlAccessType, "read-write") && strcmp(subsqlAccessType, "update"))        {            fprintf(stderr, "Invalid access type: '%s'\n", subsqlAccessType);            return 1;        }    }    dbSubSql db(accessType);    db.run(argc, argv);    return 0;}    

⌨️ 快捷键说明

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