From e669064452e0087106fb999a519afaa69d41437e Mon Sep 17 00:00:00 2001 From: malte_langkabel Date: Mon, 24 Apr 2017 17:38:16 +0200 Subject: [PATCH] logic: Add unique constraints to SQLite tables --- src/lib/data/PersistentStorage.cpp | 5 - src/lib/data/PersistentStorage.h | 1 - src/lib/data/SqliteIndexStorage.cpp | 130 ++++++++++-------- src/lib/data/SqliteIndexStorage.h | 1 - src/lib/data/SqliteStorage.cpp | 8 +- src/lib/data/SqliteStorage.h | 4 +- src/lib/data/access/StorageAccess.h | 1 - src/lib/data/access/StorageAccessProxy.cpp | 9 -- src/lib/data/access/StorageAccessProxy.h | 1 - .../messaging/type/MessageActivateEdge.h | 14 +- 10 files changed, 88 insertions(+), 86 deletions(-) diff --git a/src/lib/data/PersistentStorage.cpp b/src/lib/data/PersistentStorage.cpp index c83cab3f..bd929231 100644 --- a/src/lib/data/PersistentStorage.cpp +++ b/src/lib/data/PersistentStorage.cpp @@ -619,11 +619,6 @@ Node::NodeType PersistentStorage::getNodeTypeForNodeWithId(Id nodeId) const return Node::intToType(m_sqliteIndexStorage.getFirstById(nodeId).type); } -bool PersistentStorage::checkNodeExistsByName(const std::string& serializedName) const -{ - return m_sqliteIndexStorage.checkNodeExistsByName(serializedName); -} - Id PersistentStorage::getIdForEdge( Edge::EdgeType type, const NameHierarchy& fromNameHierarchy, const NameHierarchy& toNameHierarchy ) const diff --git a/src/lib/data/PersistentStorage.h b/src/lib/data/PersistentStorage.h index 65ea7620..46759a8e 100644 --- a/src/lib/data/PersistentStorage.h +++ b/src/lib/data/PersistentStorage.h @@ -99,7 +99,6 @@ public: virtual std::vector getNameHierarchiesForNodeIds(const std::vector nodeIds) const; virtual Node::NodeType getNodeTypeForNodeWithId(Id nodeId) const; - virtual bool checkNodeExistsByName(const std::string& serializedName) const; virtual Id getIdForEdge( Edge::EdgeType type, const NameHierarchy& fromNameHierarchy, const NameHierarchy& toNameHierarchy) const; diff --git a/src/lib/data/SqliteIndexStorage.cpp b/src/lib/data/SqliteIndexStorage.cpp index 9466d457..00da61d4 100644 --- a/src/lib/data/SqliteIndexStorage.cpp +++ b/src/lib/data/SqliteIndexStorage.cpp @@ -72,19 +72,21 @@ void SqliteIndexStorage::addFile(const int id, const std::string& filePath, cons std::shared_ptr content = TextAccess::createFromFile(filePath); unsigned int lineCount = content->getLineCount(); - executeStatement( + const bool success = executeStatement( "INSERT INTO file(id, path, modification_time, complete, line_count) VALUES(" + std::to_string(id) + ", '" + filePath + "', '" + modificationTime + "', '" + std::to_string(complete) + "', " + std::to_string(lineCount) + ");" ); - CppSQLite3Statement stmt = m_database.compileStatement(( - "INSERT INTO filecontent(id, content) VALUES(" - + std::to_string(id) + ", ?);" + if (success) + { + CppSQLite3Statement stmt = m_database.compileStatement(( + "INSERT INTO filecontent(id, content) VALUES(" + + std::to_string(id) + ", ?);" ).c_str()); - stmt.bind(1, content->getText().c_str()); - executeStatement(stmt); - + stmt.bind(1, content->getText().c_str()); + executeStatement(stmt); + } } Id SqliteIndexStorage::addLocalSymbol(const std::string& name) @@ -135,60 +137,92 @@ bool SqliteIndexStorage::addOccurrence(Id elementId, Id sourceLocationId) Id SqliteIndexStorage::addComponentAccess(Id nodeId, int type) { - executeStatement( + const bool success = executeStatement( "INSERT INTO component_access(id, node_id, type) " "VALUES (NULL, " + std::to_string(nodeId) + ", " + std::to_string(type) + ");" ); - return m_database.lastRowId(); + Id id = 0; + if (success) + { + id = m_database.lastRowId(); + } + else + { + id = executeStatementScalar("SELECT id FROM component_access WHERE node_id == " + std::to_string(nodeId) + ";"); + } + + return id; } Id SqliteIndexStorage::addCommentLocation(Id fileNodeId, uint startLine, uint startCol, uint endLine, uint endCol) { - executeStatement( + const bool success = executeStatement( "INSERT INTO comment_location(id, file_node_id, start_line, start_column, end_line, end_column) " "VALUES(NULL, " + std::to_string(fileNodeId) + ", " + std::to_string(startLine) + ", " + std::to_string(startCol) + ", " + std::to_string(endLine) + ", " + std::to_string(endCol) + ");" ); - return m_database.lastRowId(); + Id id = 0; + if (success) + { + id = m_database.lastRowId(); + } + else + { + id = executeStatementScalar( + "SELECT id FROM comment_location WHERE " + "file_node_id == " + std::to_string(fileNodeId) + " AND " + "start_line == " + std::to_string(startLine) + " AND " + "start_column == " + std::to_string(startCol) + " AND " + "end_line == " + std::to_string(endLine) + " AND " + "end_column == " + std::to_string(endCol) + ";" + ); + } + + return id; } Id SqliteIndexStorage::addError(const std::string& message, const FilePath& filePath, uint lineNumber, uint columnNumber, bool fatal, bool indexed) { std::string sanitizedMessage = utility::replace(message, "'", "''"); - // check for duplicate CppSQLite3Statement stmt = m_database.compileStatement(( - "SELECT * FROM error WHERE " - "message == ? AND " - "fatal == " + std::to_string(fatal) + " AND " - "file_path == '" + filePath.str() + "' AND " - "line_number == " + std::to_string(lineNumber) + " AND " - "column_number == " + std::to_string(columnNumber) + ";" - ).c_str()); - - stmt.bind(1, sanitizedMessage.c_str()); - CppSQLite3Query q = executeQuery(stmt); - - if (!q.eof()) - { - return q.getIntField(0, -1); - } - - stmt.finalize(); - - stmt = m_database.compileStatement(( "INSERT INTO error(message, fatal, indexed, file_path, line_number, column_number) " "VALUES (?, " + std::to_string(fatal) + ", " + std::to_string(indexed) + ", '" + filePath.str() + "', " + std::to_string(lineNumber) + ", " + std::to_string(columnNumber) + ");" ).c_str()); stmt.bind(1, sanitizedMessage.c_str()); - executeStatement(stmt); + const bool success = executeStatement(stmt); - return m_database.lastRowId(); + Id id = 0; + if (success) + { + id = m_database.lastRowId(); + } + else + { + CppSQLite3Statement selectStmt = m_database.compileStatement(( + "SELECT * FROM error WHERE " + "message == ? AND " + "fatal == " + std::to_string(fatal) + " AND " + "file_path == '" + filePath.str() + "' AND " + "line_number == " + std::to_string(lineNumber) + " AND " + "column_number == " + std::to_string(columnNumber) + ";" + ).c_str()); + + selectStmt.bind(1, sanitizedMessage.c_str()); + CppSQLite3Query q = executeQuery(selectStmt); + + if (!q.eof()) + { + id = q.getIntField(0, -1); + } + } + + return id; } void SqliteIndexStorage::removeElement(Id id) @@ -500,28 +534,6 @@ StorageNode SqliteIndexStorage::getNodeBySerializedName(const std::string& seria return StorageNode(); } -bool SqliteIndexStorage::checkNodeExistsByName(const std::string& serializedName) const -{ - CppSQLite3Statement stmt = m_database.compileStatement( - "SELECT id FROM node WHERE serialized_name == ? LIMIT 1;" - ); - - stmt.bind(1, serializedName.c_str()); - CppSQLite3Query q = executeQuery(stmt); - - if (!q.eof()) - { - const Id id = q.getIntField(0, 0); - - if (id != -1) - { - return true; - } - } - - return false; -} - StorageLocalSymbol SqliteIndexStorage::getLocalSymbolByName(const std::string& name) const { return doGetFirst("WHERE name == '" + name + "'"); @@ -817,6 +829,7 @@ void SqliteIndexStorage::setupTables() "modification_time TEXT, " "complete INTEGER, " "line_count INTEGER, " + "UNIQUE(path) ON CONFLICT FAIL," "PRIMARY KEY(id), " "FOREIGN KEY(id) REFERENCES node(id) ON DELETE CASCADE);" ); @@ -827,8 +840,8 @@ void SqliteIndexStorage::setupTables() "content TEXT, " "FOREIGN KEY(id)" "REFERENCES file(id)" - "ON DELETE CASCADE " - "ON UPDATE CASCADE);" + "ON DELETE CASCADE " + "ON UPDATE CASCADE);" ); m_database.execDML( @@ -866,6 +879,7 @@ void SqliteIndexStorage::setupTables() "id INTEGER NOT NULL, " "node_id INTEGER, " "type INTEGER NOT NULL, " + "UNIQUE(node_id) ON CONFLICT FAIL," "PRIMARY KEY(id), " "FOREIGN KEY(node_id) REFERENCES node(id) ON DELETE CASCADE);" ); @@ -878,6 +892,7 @@ void SqliteIndexStorage::setupTables() "start_column INTEGER, " "end_line INTEGER, " "end_column INTEGER, " + "UNIQUE(file_node_id, start_line, start_column, end_line, end_column) ON CONFLICT FAIL," "PRIMARY KEY(id), " "FOREIGN KEY(file_node_id) REFERENCES node(id) ON DELETE CASCADE);" ); @@ -891,6 +906,7 @@ void SqliteIndexStorage::setupTables() "file_path TEXT, " "line_number INTEGER, " "column_number INTEGER, " + "UNIQUE(message, fatal, file_path, line_number, column_number) ON CONFLICT FAIL," "PRIMARY KEY(id));" ); } diff --git a/src/lib/data/SqliteIndexStorage.h b/src/lib/data/SqliteIndexStorage.h index a6d5db9e..4f13855b 100644 --- a/src/lib/data/SqliteIndexStorage.h +++ b/src/lib/data/SqliteIndexStorage.h @@ -71,7 +71,6 @@ public: StorageNode getNodeById(Id id) const; StorageNode getNodeBySerializedName(const std::string& serializedName) const; - bool checkNodeExistsByName(const std::string& serializedName) const; StorageLocalSymbol getLocalSymbolByName(const std::string& name) const; diff --git a/src/lib/data/SqliteStorage.cpp b/src/lib/data/SqliteStorage.cpp index a385db50..c3fdc4ba 100644 --- a/src/lib/data/SqliteStorage.cpp +++ b/src/lib/data/SqliteStorage.cpp @@ -152,7 +152,7 @@ void SqliteStorage::clearMetaTable() } } -void SqliteStorage::executeStatement(const std::string& statement) const +bool SqliteStorage::executeStatement(const std::string& statement) const { try { @@ -161,10 +161,12 @@ void SqliteStorage::executeStatement(const std::string& statement) const catch (CppSQLite3Exception e) { LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage()); + return false; } + return true; } -void SqliteStorage::executeStatement(CppSQLite3Statement& statement) const +bool SqliteStorage::executeStatement(CppSQLite3Statement& statement) const { try { @@ -173,7 +175,9 @@ void SqliteStorage::executeStatement(CppSQLite3Statement& statement) const catch (CppSQLite3Exception e) { LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage()); + return false; } + return true; } int SqliteStorage::executeStatementScalar(const std::string& statement) const diff --git a/src/lib/data/SqliteStorage.h b/src/lib/data/SqliteStorage.h index f578d8c0..83ec2161 100644 --- a/src/lib/data/SqliteStorage.h +++ b/src/lib/data/SqliteStorage.h @@ -43,8 +43,8 @@ protected: void setupMetaTable(); void clearMetaTable(); - void executeStatement(const std::string& statement) const; - void executeStatement(CppSQLite3Statement& statement) const; + bool executeStatement(const std::string& statement) const; + bool executeStatement(CppSQLite3Statement& statement) const; int executeStatementScalar(const std::string& statement) const; CppSQLite3Query executeQuery(const std::string& statement) const; CppSQLite3Query executeQuery(CppSQLite3Statement& statement) const; diff --git a/src/lib/data/access/StorageAccess.h b/src/lib/data/access/StorageAccess.h index 2fd8dc53..34b4110c 100644 --- a/src/lib/data/access/StorageAccess.h +++ b/src/lib/data/access/StorageAccess.h @@ -38,7 +38,6 @@ public: virtual std::vector getNameHierarchiesForNodeIds(const std::vector nodeIds) const = 0; virtual Node::NodeType getNodeTypeForNodeWithId(Id id) const = 0; - virtual bool checkNodeExistsByName(const std::string& serializedName) const = 0; virtual Id getIdForEdge( Edge::EdgeType type, const NameHierarchy& fromNameHierarchy, const NameHierarchy& toNameHierarchy) const = 0; diff --git a/src/lib/data/access/StorageAccessProxy.cpp b/src/lib/data/access/StorageAccessProxy.cpp index 6f1e98d6..74072ddd 100644 --- a/src/lib/data/access/StorageAccessProxy.cpp +++ b/src/lib/data/access/StorageAccessProxy.cpp @@ -93,15 +93,6 @@ Node::NodeType StorageAccessProxy::getNodeTypeForNodeWithId(Id id) const return Node::NODE_NON_INDEXED; } -bool StorageAccessProxy::checkNodeExistsByName(const std::string& serializedName) const -{ - if (hasSubject()) - { - return m_subject->checkNodeExistsByName(serializedName); - } - return false; -} - Id StorageAccessProxy::getIdForEdge( Edge::EdgeType type, const NameHierarchy& fromNameHierarchy, const NameHierarchy& toNameHierarchy ) const { diff --git a/src/lib/data/access/StorageAccessProxy.h b/src/lib/data/access/StorageAccessProxy.h index de05bf7c..42ee90a3 100644 --- a/src/lib/data/access/StorageAccessProxy.h +++ b/src/lib/data/access/StorageAccessProxy.h @@ -26,7 +26,6 @@ public: virtual std::vector getNameHierarchiesForNodeIds(const std::vector nodeIds) const; virtual Node::NodeType getNodeTypeForNodeWithId(Id id) const; - virtual bool checkNodeExistsByName(const std::string& serializedName) const; virtual Id getIdForEdge( Edge::EdgeType type, const NameHierarchy& fromNameHierarchy, const NameHierarchy& toNameHierarchy) const; diff --git a/src/lib/utility/messaging/type/MessageActivateEdge.h b/src/lib/utility/messaging/type/MessageActivateEdge.h index 0097f36c..a8775b38 100644 --- a/src/lib/utility/messaging/type/MessageActivateEdge.h +++ b/src/lib/utility/messaging/type/MessageActivateEdge.h @@ -11,11 +11,11 @@ class MessageActivateEdge : public Message { public: - MessageActivateEdge(Id tokenId, Edge::EdgeType type, const NameHierarchy& fromName, const NameHierarchy& toName) + MessageActivateEdge(Id tokenId, Edge::EdgeType type, const NameHierarchy& sourceNameHierarchy, const NameHierarchy& targetNameHierarchy) : tokenId(tokenId) , type(type) - , fromNameHierarchy(fromName) - , toNameHierarchy(toName) + , sourceNameHierarchy(sourceNameHierarchy) + , targetNameHierarchy(targetNameHierarchy) { if (!isAggregation()) { @@ -36,8 +36,8 @@ public: std::string getFullName() const { std::string name = Edge::getReadableTypeString(type) + ":"; - name += fromNameHierarchy.getQualifiedNameWithSignature() + "->"; - name += toNameHierarchy.getQualifiedNameWithSignature(); + name += sourceNameHierarchy.getQualifiedNameWithSignature() + "->"; + name += targetNameHierarchy.getQualifiedNameWithSignature(); return name; } @@ -48,8 +48,8 @@ public: const Id tokenId; const Edge::EdgeType type; - const NameHierarchy fromNameHierarchy; - const NameHierarchy toNameHierarchy; + const NameHierarchy sourceNameHierarchy; + const NameHierarchy targetNameHierarchy; std::vector aggregationIds; };