subsql.cpp

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

CPP
1,947
字号
bool dbSubSql::updateFields(dbAnyCursor* cursor, dbUpdateElement* elems){     char buf[64], *src;     dbInheritedAttribute iattr;     dbSynthesizedAttribute sattr;     iattr.db = this;     iattr.oid = cursor->currId;     iattr.table = (dbTable*)getRow(cursor->table->tableId);     iattr.record = (byte*)getRow(cursor->currId);         iattr.paramBase = (size_t)cursor->paramBase;     do { 	 dbExprNode* expr = elems->value;	 dbFieldDescriptor* fd = elems->field;	 execute(expr, iattr, sattr);	 byte* dst = cursor->record + fd->appOffs;	 switch (fd->type) {	   case dbField::tpBool:	     switch (expr->type) { 	       case tpInteger:		 *(bool*)dst = sattr.ivalue != 0;		 continue;	       case tpBoolean:		 *(bool*)dst = sattr.bvalue;		 continue;	       case tpReal:		 *(bool*)dst = sattr.fvalue != 0;		 continue;	       case tpString:		 *(bool*)dst = *sattr.base == 'T' || *sattr.base == 't' || *sattr.base == '1';		 continue;	     }	     break;	   case dbField::tpInt1:	     switch (expr->type) { 	       case tpInteger:		 *(int1*)dst = (int1)sattr.ivalue;		 continue;	       case tpBoolean:		 *(int1*)dst = sattr.bvalue ? 1 : 0;		 continue;	       case tpReal:		 *(int1*)dst = (int1)sattr.fvalue;		 continue;	       case tpString:		 *(int1*)dst = (int1)atoi((char*)sattr.base);		 continue;	     }	     break;	   case dbField::tpInt2:	     switch (expr->type) { 	       case tpInteger:		 *(int2*)dst = (int2)sattr.ivalue;		 continue;	       case tpBoolean:		 *(int2*)dst = sattr.bvalue ? 1 : 0;		 continue;	       case tpReal:		 *(int2*)dst = (int2)sattr.fvalue;		 continue;	       case tpString:		 *(int2*)dst = (int2)atoi((char*)sattr.base);		 continue;	     }	     break;	   case dbField::tpInt4:	     switch (expr->type) { 	       case tpInteger:		 *(int4*)dst = (int4)sattr.ivalue;		 continue;	       case tpBoolean:		 *(int4*)dst = sattr.bvalue ? 1 : 0;		 continue;	       case tpReal:		 *(int4*)dst = (int4)sattr.fvalue;		 continue;	       case tpString:		 *(int4*)dst = (int1)atoi((char*)sattr.base);		 continue;	     }	     break;	   case dbField::tpInt8:	     switch (expr->type) { 	       case tpInteger:		 *(db_int8*)dst = sattr.ivalue;		 continue;	       case tpBoolean:		 *(db_int8*)dst = sattr.bvalue ? 1 : 0;		 continue;	       case tpReal:		 *(db_int8*)dst = (db_int8)sattr.fvalue;		 continue;	       case tpString:		 *(db_int8*)dst = (db_int8)atoi((char*)sattr.base);		 continue;	     }	     break;	   case dbField::tpReal4:	     switch (expr->type) { 	       case tpInteger:		 *(real4*)dst = (real4)sattr.ivalue;		 continue;	       case tpBoolean:		 *(real4*)dst = sattr.bvalue ? 1.0 : 0.0;		 continue;	       case tpReal:		 *(real4*)dst = (real4)sattr.fvalue;		 continue;	       case tpString:		 *(real4*)dst = (real4)atof((char*)sattr.base);		 continue;	     }	     break;	   case dbField::tpReal8:	     switch (expr->type) { 	       case tpInteger:		 *(real8*)dst = (real8)sattr.ivalue;		 continue;	       case tpBoolean:		 *(real8*)dst = sattr.bvalue ? 1.0 : 0.0;		 continue;	       case tpReal:		 *(real8*)dst = sattr.fvalue;		 continue;	       case tpString:		 *(real8*)dst = atof((char*)sattr.base);		 continue;	     }	     break;	   case dbField::tpString:	     src = buf;	     switch (expr->type) { 	       case tpInteger:		 sprintf(buf, INT8_FORMAT, sattr.ivalue);		 break;	       case tpBoolean:		 strcpy(buf, sattr.bvalue ? "t" : "f");		 break;	       case tpReal:		 sprintf(buf, "%f", sattr.fvalue);		 break;	       case tpString:		 src = (char*)sattr.base;		 break;	     }	     *(char**)dst = new char[strlen(src)+1];	     strcpy(*(char**)dst, src);	     elems->strValue = *(char**)dst;	     continue;	   case dbField::tpReference:	     if (expr->type == tpInteger) { 		 *(oid_t*)dst = sattr.oid;		 continue;	     }	 }	 assert(false);     } while ((elems = elems->next) != NULL);     return true;}bool dbSubSql::parse() {    dbTableDescriptor* desc;    dbFieldDescriptor* fd;    int tkn;    bool count, outputOid, compactify;    line = 1;    pos = 0;    while (true) { 	if (in == stdin) { 	    printf(prompt);	    tkn = scan();	    pos += strlen(prompt);	} else { 	    tkn = scan();	}	    	switch (tkn) { 	  case tkn_update:	    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;		}		if (!expect("set", tkn_set)) { 		    continue;		}		dbDatabaseThreadContext* ctx = threadContext.get();		byte *record = new byte[desc->appSize];		ctx->interactive = true;		ctx->catched = true;		dbUpdateElement* elems = NULL;	        if (!expect("field name", tkn_ident)) { 		    goto updateCleanup;		}	#ifdef THROW_EXCEPTION_ON_ERROR                try {#else		if (setjmp(ctx->unwind) == 0) {#endif		    		    char* condition = NULL;		    int startPos = pos;		    while (true) { 			dbUpdateElement* elem = new dbUpdateElement;			dbFieldDescriptor* fd = desc->findSymbol(name);			if (fd == NULL) { 			    error("No such field in the table");			    goto updateCleanup;			}			if (fd->type > dbField::tpReference) { 			    error("Field can not be updated");			    goto updateCleanup;			}			elem->field = fd;			elem->next = elems;			elems = elem;			if (!expect("=", tkn_eq)) { 			    goto updateCleanup;			}			startPos = pos;			int ch = readExpression();			if (ch == EOF) { 			    error("unexpected end of input");			    goto updateCleanup;			} 			condition = strstr(buf, "where");			if (condition != NULL) {			    *condition = '\0';			}			dbExprNode* expr = ctx->compiler.compileExpression(desc, buf, startPos);			if (expr == NULL) { 			    goto updateCleanup;			}			if (expr->type > tpString) { 			    error("Invalid expression type");			    goto updateCleanup;			}			elem->value = expr;			if (condition == NULL && ch == ',') { 			    if (!expect("field name", tkn_ident)) { 				goto updateCleanup;			    }			} else { 			    break;			}		    }		    dbAnyCursor cursor(*desc, dbCursorForUpdate, record);		    cursor.reset();					    if (condition != NULL) { 			query.pos = startPos + (condition - buf) + 5;			query = condition + 5;			select(&cursor, query);			if (!query.compiled()) { 			    goto updateCleanup;			}		 		    		    } else { 			select(&cursor);		    }		    if (cursor.gotoFirst()) { 			do { 			    cursor.fetch();			    if (!updateFields(&cursor, elems)) { 				goto updateCleanup;			    }				    cursor.update();			} while (cursor.gotoNext());		    }		    printf("\n\t%d records updated\n", cursor.getNumberOfRecords());#ifdef THROW_EXCEPTION_ON_ERROR                } catch(dbException const&) {}#else		} else { 		    if (query.mutexLocked) { 			query.mutexLocked = false;			query.mutex.unlock();		    }		}#endif	      updateCleanup:		query.reset();		while (elems != NULL) { 		    dbUpdateElement* elem = elems;		    elems = elems->next;		    delete elem;		}		if (!modified) { 		    commit(); // release locks		}	        dbExprNode::cleanup();		ctx->catched = false;		delete[] record;	    }	    continue;	  case tkn_select:	    if (!opened) { 		error("Database not opened");		continue;	    }	    outputOid = true;            count = false;	    if ((tkn = scan()) == tkn_all) { 		outputOid = false;		tkn = scan();	    } else if (tkn == tkn_count) {                 if (!expect("'('", tkn_lpar)                    || !expect("'*'", tkn_all)                    || !expect("')'", tkn_rpar))                {                    continue;                }                count = true;                tkn = scan();            }	    if (tkn != tkn_from) { 		error("'from' keyword expected");		continue;	    }	    if (scan() != tkn_ident) { 		error("Table name expected");		continue;	    }	    if ((desc = findTable(name)) != NULL) {     		dbAnyCursor cursor(*desc, dbCursorViewOnly, NULL);		query.pos = pos;		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;		    }                    if (count) {                         printf("%d records selected\n",                               cursor.getNumberOfRecords());                    } else {                         if (cursor.gotoFirst()) {                             dbFieldDescriptor* fd = desc->columns;                             do {                                 printf("%s ", fd->name);                            } while ((fd = fd->next) != desc->columns);                            if (outputOid) { 			    printf("\n#%x: (", cursor.currId);                            } else {                                 printf("\n(");                            }                            dumpRecord((byte*)getRow(cursor.currId),                                        cursor.table->columns);                            printf(")");                            while (cursor.gotoNext()) {                                 if (outputOid) {                                     printf(",\n#%x: (", cursor.currId);                                } else {                                     printf(",\n(");                                }                                dumpRecord((byte*)getRow(cursor.currId),                                           cursor.table->columns);                                printf(")");                            }                            printf("\n\t%d records selected\n",                                    cursor.getNumberOfRecords());                        } else {                             fprintf(stderr, "No records selected\n");                        }                    }#ifdef THROW_EXCEPTION_ON_ERROR                } catch(dbException const&) {}#else		} else { 		    if (query.mutexLocked) { 			query.mutexLocked = false;			query.mutex.unlock();		    }		}#endif		ctx->catched = false;		if (!modified) { 		    commit(); // release locks		}	    } else { 		error("No such table in database");	    }	    continue;			  case tkn_open:	    if (expect("database name", tkn_sconst)) { 		char* databaseName = new char[strlen(buf)+1];		strcpy(databaseName, buf);		char* fileName = NULL;		if ((tkn = scan()) == tkn_sconst) { 		    fileName = buf;		} else if (tkn != tkn_semi) { 		    delete[] databaseName;		    error("database file name expected");		    continue;		}		if (opened) { 		    close();		    while (droppedTables != NULL) { 			dbTableDescriptor* next = droppedTables->nextDbTable;			delete droppedTables; 			droppedTables = next;		    }		    opened = false;		    dbTableDescriptor::cleanup();		}		time_t transactionCommitDelay = 0;		char* delay = getenv("FASTDB_COMMIT_DELAY");		if (delay != NULL) { 		    transactionCommitDelay = atoi(delay);		}		if (!open(databaseName, fileName, INFINITE, transactionCommitDelay)) { 		    fprintf(stderr, "Database not opened\n");		} else { 		    opened = true;		    dbTable* table = (dbTable*)getRow(dbMetaTableId);		    dbTableDescriptor* desc = new dbTableDescriptor(table);		    linkTable(desc, dbMetaTableId);		    oid_t tableId = table->firstRow;		    while (tableId != 0) {						table = (dbTable*)getRow(tableId);			for (desc = tables; desc != NULL && desc->tableId != tableId; desc = desc->nextDbTable);			if (desc == NULL) { 			    dbTableDescriptor* desc = new dbTableDescriptor(table);			    linkTable(desc, tableId);			    desc->setFlags();			}			tableId = table->next;		    }		    existedTables = tables;		    if (!completeDescriptorsInitialization()) {			error("Reference to undefined table");		    }		    char* backupName = getenv("FASTDB_BACKUP_NAME");		    if (backupName != NULL) { 			char* backupPeriod = getenv("FASTDB_BACKUP_PERIOD");			time_t period = 60*60*24; // one day			if (backupPeriod != NULL) { 			    period = atoi(backupPeriod);			}			printf("Schedule backup to file %s each %u seconds\n", 			       backupName, (unsigned)period);				scheduleBackup(backupName, period);					    }		}		delete[] databaseName;	    }	    continue;		    	  case tkn_drop:	    if (!opened) { 		error("Database not opened");		continue;	    }	    if (monitor->users != 1) { 		error("Can not perform operation with active appliations");		continue;	    }	    switch (scan()) { 	      case tkn_table:

⌨️ 快捷键说明

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