From fbb26deb27909f5603746739822c0d9c338955b9 Mon Sep 17 00:00:00 2001 From: rtk0c Date: Sat, 30 Jul 2022 22:09:22 -0700 Subject: Changeset: 88 (untested) replace manual sqlite3_step() calls with SQLiteRunningStatement wrapper --- source/20-codegen-compiler/CodegenModel.cpp | 295 ++++++++-------------------- 1 file changed, 85 insertions(+), 210 deletions(-) (limited to 'source/20-codegen-compiler/CodegenModel.cpp') diff --git a/source/20-codegen-compiler/CodegenModel.cpp b/source/20-codegen-compiler/CodegenModel.cpp index da7a5cc..303ad4e 100644 --- a/source/20-codegen-compiler/CodegenModel.cpp +++ b/source/20-codegen-compiler/CodegenModel.cpp @@ -1,6 +1,7 @@ #include "CodegenModel.hpp" #include "CodegenUtils.hpp" +#include "SQLiteHelper.hpp" #include #include @@ -34,55 +35,6 @@ public: #define CURRENT_DATABASE_VERSION 1 constexpr int64_t kGlobalNamespaceId = 1; -struct SQLiteDatabase { - sqlite3* database = nullptr; - - ~SQLiteDatabase() { - // NOTE: calling with NULL is a harmless no-op - int result = sqlite3_close(database); - assert(result == SQLITE_OK); - } - - operator sqlite3*() const { return database; } - sqlite3** operator&() { return &database; } -}; - -struct SQLiteStatement { - sqlite3_stmt* stmt = nullptr; - - SQLiteStatement(const SQLiteStatement&) = delete; - SQLiteStatement& operator=(const SQLiteStatement&) = delete; - - SQLiteStatement() = default; - - SQLiteStatement(sqlite3* database, std::string_view sql) { - Initialize(database, sql); - } - - ~SQLiteStatement() { - // NOTE: calling with NULL is a harmless no-op - // NOTE: we don't care about the error code, because they are returned if the statement has errored in the most recent execution - // but deleting it will succeeed anyways - sqlite3_finalize(stmt); - } - - operator sqlite3_stmt*() const { return stmt; } - sqlite3_stmt** operator&() { return &stmt; } - - void Initialize(sqlite3* database, std::string_view sql) { - int result = sqlite3_prepare(database, sql.data(), sql.size(), &stmt, nullptr); - assert(result == SQLITE_OK); - } - - bool InitializeLazily(sqlite3* database, std::string_view sql) { - if (!stmt) { - Initialize(database, sql); - return true; - } - return false; - } -}; - namespace { void PrintErrMsgIfPresent(char*& errMsg) { if (errMsg) { @@ -273,19 +225,12 @@ COMMIT TRANSACTION; return rowId; } - sqlite3_stmt* stmt = storeNamespaceStmt; - int64_t parentRowId = FindOrStoreNamespace(ns->container); - sqlite3_bind_int64(stmt, 1, parentRowId); - sqlite3_bind_text(stmt, 2, ns->name.c_str(), ns->name.size(), nullptr); + SQLiteRunningStatement rt(storeNamespaceStmt); + rt.BindArguments(FindOrStoreNamespace(ns->container), ns->name); - int result = sqlite3_step(stmt); - DEFER { - sqlite3_reset(stmt); - sqlite3_clear_bindings(stmt); - }; - assert(result == SQLITE_ROW); + rt.StepAndCheck(SQLITE_ROW); - auto nsId = sqlite3_column_int64(stmt, 0); + auto [nsId] = rt.ResultColumns(); return nsId; } @@ -299,17 +244,13 @@ COMMIT TRANSACTION; /// \return Row ID of the file, or 0 if it currently doesn't exist. int64_t FindFile(std::string_view filename) { - sqlite3_stmt* stmt = findFileStmt; - sqlite3_bind_text(stmt, 1, filename.data(), filename.size(), nullptr); + SQLiteRunningStatement rt(findFileStmt); + rt.BindArguments(filename); - int result = sqlite3_step(stmt); - DEFER { - sqlite3_reset(stmt); - sqlite3_clear_bindings(stmt); - }; + int result = rt.Step(); if (result == SQLITE_ROW) { - auto fileId = sqlite3_column_int64(stmt, 0); + auto [fileId] = rt.ResultColumns(); return fileId; } else { return 0; @@ -322,17 +263,12 @@ COMMIT TRANSACTION; return id; } - sqlite3_stmt* stmt = storeFileStmt; - sqlite3_bind_text(stmt, 1, filename.data(), filename.size(), nullptr); + SQLiteRunningStatement rt(storeFileStmt); + rt.BindArguments(filename); - int result = sqlite3_step(stmt); - DEFER { - sqlite3_reset(stmt); - sqlite3_clear_bindings(stmt); - }; - assert(result == SQLITE_ROW); + rt.StepAndCheck(SQLITE_ROW); - auto fileId = sqlite3_column_int64(stmt, 0); + auto [fileId] = rt.ResultColumns(); return fileId; } @@ -353,21 +289,13 @@ private: sqlite3_stmt* stmt = getNamespaceStmt; int64_t currentNsId = nsId; while (true) { - sqlite3_bind_int64(stmt, 1, currentNsId); - - int result = sqlite3_step(stmt); - DEFER { - sqlite3_reset(stmt); - sqlite3_clear_bindings(stmt); - }; - assert(result == SQLITE_ROW); + SQLiteRunningStatement rt(getNamespaceStmt); + rt.BindArguments(currentNsId); - /* 0th column Id */ - int64_t parentNamespaceId = sqlite3_column_int64(stmt, 1); - auto nameCstr = (const char*)sqlite3_column_text(stmt, 2); + rt.StepAndCheck(SQLITE_ROW); + auto [id, parentNamespaceId, name] = rt.ResultColumns(); currentNsId = parentNamespaceId; - std::string name(nameCstr); fullnameLength += name.size() + 2; namespaceNames.push_back(std::move(name)); @@ -415,17 +343,12 @@ private: int64_t FindNamespaceImpl(const DeclNamespace& ns, int64_t parentNsRowId) { sqlite3_stmt* stmt = findNamespaceStmt; - sqlite3_bind_int64(stmt, 1, parentNsRowId); - sqlite3_bind_text(stmt, 2, ns.name.c_str(), ns.name.size(), nullptr); - - int result = sqlite3_step(stmt); - DEFER { - sqlite3_reset(stmt); - sqlite3_clear_bindings(stmt); - }; + SQLiteRunningStatement rt(findNamespaceStmt); + rt.BindArguments(parentNsRowId, ns.name); + int result = rt.Step(); if (result == SQLITE_ROW) { - int64_t nsId = sqlite3_column_int64(stmt, 0); + auto [nsId] = rt.ResultColumns(); return nsId; } else { return 0; @@ -584,11 +507,9 @@ void CodegenArchiveModel::DeleteDeclsRelatedToFile(std::string_view filename) { m->deleteEnumDeclByFilenameStmt.stmt, }; for (auto& stmt : stmtList) { - sqlite3_bind_text(stmt, 1, filename.data(), filename.size(), nullptr); - int result = sqlite3_step(stmt); - assert(result == SQLITE_DONE); - sqlite3_reset(stmt); - sqlite3_clear_bindings(stmt); + SQLiteRunningStatement rt(stmt); + rt.BindArguments(filename); + rt.StepUntilDone(); } m->CommitTransaction(); } @@ -638,91 +559,67 @@ CodegenRuntimeModel CodegenArchiveModel::Load() const { robin_hood::unordered_map propertiesById; robin_hood::unordered_map methodsById; - // NOTE: this is basically { initializer; while(true) { body; } } in a short form - // Load structs - for (SQLiteStatement stmt(m->database, "SELECT * FROM DeclStructs"sv);;) { - int result = sqlite3_step(stmt); - if (result == SQLITE_DONE) { - break; - } + { // Load structs + SQLiteStatement stmt(m->database, "SELECT * FROM DeclStructs"sv); + SQLiteRunningStatement rt(stmt); + while (true) { + int result = rt.StepAndCheckError(); + if (result == SQLITE_DONE) break; + assert(result == SQLITE_ROW); - if (result == SQLITE_ROW) { - int64_t id = sqlite3_column_int64(stmt, 9); - int64_t fileId = sqlite3_column_int64(stmt, 1); - int64_t nsId = sqlite3_column_int64(stmt, 2); - std::string_view name((const char*)sqlite3_column_text(stmt, 3)); + auto [id, fileId, nsId, name] = rt.ResultColumns(); auto decl = cgModel.AddStruct(m->GetDeclFullName(nsId, name), DeclStruct{}); structsById.try_emplace(id, decl); - - continue; } - - // Executing the statement resulted in an error - assert(false); } - // Load struct's base classes - for (SQLiteStatement stmt(m->database, "SELECT * FROM DeclStructBaseClassRelations");;) { - int result = sqlite3_step(stmt); - if (result == SQLITE_DONE) { - break; - } + { // Load struct's base classes + SQLiteStatement stmt(m->database, "SELECT * FROM DeclStructBaseClassRelations"); + SQLiteRunningStatement rt(stmt); + while (true) { + int result = rt.StepAndCheckError(); + if (result == SQLITE_DONE) break; + assert(result == SQLITE_ROW); - if (result == SQLITE_ROW) { - int64_t structId = sqlite3_column_int64(stmt, 0); - int64_t parentStructNsId = sqlite3_column_int64(stmt, 1); - std::string_view parentStructName((const char*)sqlite3_column_text(stmt, 2)); + auto [structId, parentStructNsId, parentStructName] = rt.ResultColumns(); auto declThis = structsById.at(structId); auto declParent = cgModel.FindStruct(parentStructName); // TODO namespace declThis->baseClasses.push_back(declParent); - - continue; } - - assert(false); } - // Load struct properties - for (SQLiteStatement stmt(m->database, "SELECT * FROM DeclStructProperties"sv);;) { - int result = sqlite3_step(stmt); - if (result == SQLITE_DONE) { - break; - } + { // Load struct properties + SQLiteStatement stmt(m->database, "SELECT * FROM DeclStructProperties"sv); + SQLiteRunningStatement rt(stmt); + while (true) { + int result = rt.StepAndCheckError(); + if (result == SQLITE_DONE) break; + assert(result == SQLITE_ROW); - if (result == SQLITE_ROW) { // TODO - continue; } - - assert(false); } - // Load struct methods - for (SQLiteStatement stmt(m->database, "SELECT * FROM DeclStructMethods"sv);;) { - int result = sqlite3_step(stmt); - if (result == SQLITE_DONE) { - break; - } + { // Load struct methods + SQLiteStatement stmt(m->database, "SELECT * FROM DeclStructMethods"sv); + SQLiteRunningStatement rt(stmt); + while (true) { + int result = rt.StepAndCheckError(); + if (result == SQLITE_DONE) break; + assert(result == SQLITE_ROW); - if (result == SQLITE_ROW) { // TODO - continue; } - - assert(false); } - // Load method params - for (SQLiteStatement stmt(m->database, "SELECT * FROM DeclStructMethodParameters"sv);;) { - int result = sqlite3_step(stmt); - if (result == SQLITE_DONE) { - break; - } + { // Load method params + SQLiteStatement stmt(m->database, "SELECT * FROM DeclStructMethodParameters"sv); + SQLiteRunningStatement rt(stmt); + while (true) { + int result = rt.StepAndCheckError(); + if (result == SQLITE_DONE) break; + assert(result == SQLITE_ROW); - if (result == SQLITE_ROW) { // TODO - continue; } - - assert(false); } return cgModel; @@ -764,40 +661,28 @@ INSERT INTO DeclStructProperties(StructId, Name, Type, GetterName, SetterName, I VALUES (?1, ?2, ?3, ?4, ?5, ?6) )"""sv); - int result; - - sqlite3_bind_int64(m->storeStructStmt, 1, m->FindOrStoreNamespace(decl.container)); - sqlite3_bind_text(m->storeStructStmt, 2, decl.name.c_str(), decl.name.size(), nullptr); - sqlite3_bind_int64(m->storeStructStmt, 3, m->FindOrStoreFile(decl.sourceFile)); - sqlite3_bind_int(m->storeStructStmt, 4, decl.generating); - result = sqlite3_step(m->storeStructStmt); - assert(result == SQLITE_ROW); - int64_t structId = sqlite3_column_int64(m->storeStructStmt, 0); - sqlite3_reset(m->storeStructStmt); - sqlite3_clear_bindings(m->storeStructStmt); + SQLiteRunningStatement rt(m->storeStructStmt); + rt.BindArguments(m->FindOrStoreNamespace(decl.container), decl.name, m->FindOrStoreFile(decl.sourceFile), decl.generating); + rt.StepAndCheck(SQLITE_ROW); + auto [structId] = rt.ResultColumns(); for (auto& baseClass : decl.baseClasses) { - sqlite3_bind_int64(m->storeStructBaseClassStmt, 1, structId); - sqlite3_bind_int64(m->storeStructBaseClassStmt, 2, m->FindOrStoreNamespace(baseClass->container)); - sqlite3_bind_text(m->storeStructBaseClassStmt, 3, baseClass->name.c_str(), baseClass->name.size(), nullptr); - int result = sqlite3_step(m->storeStructBaseClassStmt); - assert(result == SQLITE_DONE); - sqlite3_reset(m->storeStructBaseClassStmt); - sqlite3_clear_bindings(m->storeStructBaseClassStmt); + SQLiteRunningStatement rt(m->storeStructBaseClassStmt); + rt.BindArguments(structId, m->FindOrStoreNamespace(baseClass->container), baseClass->name); + rt.StepUntilDone(); } for (auto& property : decl.memberVariables) { - sqlite3_bind_int64(m->storeStructPropertyStmt, 1, structId); - sqlite3_bind_text(m->storeStructPropertyStmt, 2, property.name.c_str(), property.name.size(), nullptr); - sqlite3_bind_text(m->storeStructPropertyStmt, 3, property.type.c_str(), property.type.size(), nullptr); - sqlite3_bind_text(m->storeStructPropertyStmt, 4, property.getterName.c_str(), property.getterName.size(), nullptr); - sqlite3_bind_text(m->storeStructPropertyStmt, 5, property.setterName.c_str(), property.setterName.size(), nullptr); - // Since DeclMemberVariable entries currently only exist if it's marked BRUSSEL_PROPERTY - sqlite3_bind_int(m->storeStructPropertyStmt, 6, true); - int result = sqlite3_step(m->storeStructPropertyStmt); - assert(result == SQLITE_DONE); - sqlite3_reset(m->storeStructPropertyStmt); - sqlite3_clear_bindings(m->storeStructPropertyStmt); + SQLiteRunningStatement rt(m->storeStructPropertyStmt); + rt.BindArguments( + structId, + property.name, + property.type, + property.getterName, + property.setterName, + // Since DeclMemberVariable entries currently only exist if it's marked BRUSSEL_PROPERTY + true); + rt.StepUntilDone(); } for (auto& method : decl.memberFunctions) { @@ -834,24 +719,14 @@ VALUES (?1, ?2, ?3) ON CONFLICT DO UPDATE SET Value=?3 )"""sv); - sqlite3_bind_int(m->storeEnumStmt, 1, m->FindOrStoreNamespace(decl.container)); - sqlite3_bind_text(m->storeEnumStmt, 2, decl.name.c_str(), decl.name.size(), nullptr); - auto eutName = decl.GetUnderlyingTypeName(); - sqlite3_bind_text(m->storeEnumStmt, 3, eutName.data(), eutName.size(), nullptr); - sqlite3_bind_int64(m->storeEnumStmt, 4, m->FindOrStoreFile(decl.sourceFile)); - int result = sqlite3_step(m->storeEnumStmt); - assert(result == SQLITE_ROW); - auto enumId = sqlite3_column_int64(m->storeEnumStmt, 0); - sqlite3_reset(m->storeEnumStmt); - sqlite3_clear_bindings(m->storeEnumStmt); + SQLiteRunningStatement rt(m->storeEnumStmt); + rt.BindArguments(m->FindOrStoreNamespace(decl.container), decl.name, decl.GetUnderlyingTypeName(), m->FindOrStoreFile(decl.sourceFile)); + rt.StepAndCheck(SQLITE_ROW); + auto [enumId] = rt.ResultColumns(); for (auto& elm : decl.elements) { - sqlite3_bind_int64(m->storeEnumElmStmt, 1, enumId); - sqlite3_bind_text(m->storeEnumElmStmt, 2, elm.name.c_str(), elm.name.size(), nullptr); - sqlite3_bind_int64(m->storeEnumElmStmt, 3, elm.value); - int result = sqlite3_step(m->storeEnumElmStmt); - assert(result == SQLITE_DONE); - sqlite3_reset(m->storeEnumElmStmt); - sqlite3_clear_bindings(m->storeEnumElmStmt); + SQLiteRunningStatement rt(m->storeEnumElmStmt); + rt.BindArguments(enumId, elm.name, elm.value); + rt.StepUntilDone(); } } -- cgit v1.2.3-70-g09d2