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

📄 subsql.cpp

📁 实现内存数据库的源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
	    return NULL;
	}
	while ((tkn = scan()) != tkn_semi) { 
	    if (tkn != tkn_dot) { 
		error("'.' expected");
		return NULL;
	    }	
	    if (expect("field name", tkn_ident)) { 
		if ((fd = fd->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 { 
		return NULL;
	    }
	}
	if (fd->type == dbField::tpReference) { 
	    error("References can not be indexed");
	    return NULL;
	} 	
	if (fd->type == dbField::tpStructure) { 
	    error("Structures can not be indexed");
	    return NULL;
	} 
	return fd;
    }
    return NULL;
}


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:
		 *(int8*)dst = sattr.ivalue;
		 continue;
	       case tpBoolean:
		 *(int8*)dst = sattr.bvalue ? 1 : 0;
		 continue;
	       case tpReal:
		 *(int8*)dst = (int8)sattr.fvalue;
		 continue;
	       case tpString:
		 *(int8*)dst = (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;
	 }
	 assert(false);
     } while ((elems = elems->next) != NULL);

     return true;
}

bool dbSubSql::parse() 
{
    dbTableDescriptor* desc;
    dbFieldDescriptor* fd;
    int tkn;
    bool 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->find(name);
			if (fd == NULL) { 
			    error("No such field in the table");
			    goto updateCleanup;
			}
			if (fd->type > dbField::tpString) { 
			    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);
		    } else { 
			select(&cursor);
		    }
		    if (!query.compiled()) { 
			goto updateCleanup;
		    }		 		    
		    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;
	    if ((tkn = scan()) == tkn_all) { 
		outputOid = false;
		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 (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();

⌨️ 快捷键说明

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