| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "impeller/archivist/archive_class_registration.h" |
| |
| #include <sstream> |
| |
| #include "impeller/archivist/archive_database.h" |
| #include "impeller/archivist/archive_statement.h" |
| #include "impeller/base/validation.h" |
| |
| namespace impeller { |
| |
| static constexpr const char* kArchivePrimaryKeyColumnName = "primary_key"; |
| |
| ArchiveClassRegistration::ArchiveClassRegistration(ArchiveDatabase& database, |
| ArchiveDef definition) |
| : database_(database), definition_(std::move(definition)) { |
| for (size_t i = 0; i < definition_.members.size(); i++) { |
| // The first index entry is the primary key. So add one to the index. |
| column_map_[definition_.members[i]] = i + 1; |
| } |
| is_valid_ = CreateTable(); |
| } |
| |
| const std::string& ArchiveClassRegistration::GetClassName() const { |
| return definition_.table_name; |
| } |
| |
| size_t ArchiveClassRegistration::GetMemberCount() const { |
| return column_map_.size(); |
| } |
| |
| bool ArchiveClassRegistration::IsValid() const { |
| return is_valid_; |
| } |
| |
| std::optional<size_t> ArchiveClassRegistration::FindColumnIndex( |
| const std::string& member) const { |
| auto found = column_map_.find(member); |
| if (found == column_map_.end()) { |
| VALIDATION_LOG << "No member named '" << member << "' in class '" |
| << definition_.table_name |
| << "'. Did you forget to register it?"; |
| return std::nullopt; |
| } |
| return found->second; |
| } |
| |
| bool ArchiveClassRegistration::CreateTable() { |
| if (definition_.table_name.empty() || definition_.members.empty()) { |
| return false; |
| } |
| |
| std::stringstream stream; |
| |
| /* |
| * Table names cannot participate in parameter substitution, so we prepare |
| * a statement and check its validity before running. |
| */ |
| stream << "CREATE TABLE IF NOT EXISTS " << definition_.table_name << " (" |
| << kArchivePrimaryKeyColumnName << " INTEGER PRIMARY KEY, "; |
| |
| for (size_t i = 0, columns = definition_.members.size(); i < columns; i++) { |
| stream << definition_.members[i]; |
| if (i != columns - 1) { |
| stream << ", "; |
| } |
| } |
| stream << ");"; |
| |
| auto statement = database_.CreateStatement(stream.str()); |
| |
| if (!statement.IsValid()) { |
| return false; |
| } |
| |
| if (!statement.Reset()) { |
| return false; |
| } |
| |
| return statement.Execute() == ArchiveStatement::Result::kDone; |
| } |
| |
| ArchiveStatement ArchiveClassRegistration::CreateQueryStatement( |
| bool single) const { |
| std::stringstream stream; |
| stream << "SELECT " << kArchivePrimaryKeyColumnName << ", "; |
| for (size_t i = 0, columns = definition_.members.size(); i < columns; i++) { |
| stream << definition_.members[i]; |
| if (i != columns - 1) { |
| stream << ","; |
| } |
| } |
| stream << " FROM " << definition_.table_name; |
| |
| if (single) { |
| stream << " WHERE " << kArchivePrimaryKeyColumnName << " = ?"; |
| } else { |
| stream << " ORDER BY " << kArchivePrimaryKeyColumnName << " ASC"; |
| } |
| |
| stream << ";"; |
| |
| return database_.CreateStatement(stream.str()); |
| } |
| |
| ArchiveStatement ArchiveClassRegistration::CreateInsertStatement() const { |
| std::stringstream stream; |
| stream << "INSERT OR REPLACE INTO " << definition_.table_name |
| << " VALUES ( ?, "; |
| for (size_t i = 0, columns = definition_.members.size(); i < columns; i++) { |
| stream << "?"; |
| if (i != columns - 1) { |
| stream << ", "; |
| } |
| } |
| stream << ");"; |
| |
| return database_.CreateStatement(stream.str()); |
| } |
| |
| } // namespace impeller |