| 108 | } |
| 109 | |
| 110 | void DatabaseManager::createGraph(const std::string& graphName, |
| 111 | storage::MemoryManager* memoryManager, main::ClientContext* clientContext, bool isAnyGraph) { |
| 112 | if (StringUtils::caseInsensitiveEquals(graphName, "main")) { |
| 113 | throw RuntimeException{"MAIN is a reserved graph name."}; |
| 114 | } |
| 115 | |
| 116 | auto upperCaseName = StringUtils::getUpper(graphName); |
| 117 | |
| 118 | // Check if graph already exists in system catalog |
| 119 | auto mainCatalog = clientContext->getDatabase()->getCatalog(); |
| 120 | auto transaction = TransactionContext::Get(*clientContext)->getActiveTransaction(); |
| 121 | if (mainCatalog->containsGraph(transaction, graphName)) { |
| 122 | throw RuntimeException{std::format("Graph {} already exists.", graphName)}; |
| 123 | } |
| 124 | |
| 125 | // Also check in-memory graphs vector (for any edge cases) |
| 126 | for (auto& graph : graphs) { |
| 127 | auto graphNameUpper = StringUtils::getUpper(graph->getCatalogName()); |
| 128 | if (graphNameUpper == upperCaseName) { |
| 129 | throw RuntimeException{std::format("Graph {} already exists.", graphName)}; |
| 130 | } |
| 131 | } |
| 132 | |
| 133 | // Add to system catalog first (for transactional durability) |
| 134 | mainCatalog->createGraph(transaction, graphName, isAnyGraph); |
| 135 | |
| 136 | auto catalog = std::make_unique<catalog::Catalog>(); |
| 137 | catalog->setCatalogName(graphName); |
| 138 | auto dbPath = clientContext->getDatabasePath(); |
| 139 | auto graphPath = DBConfig::isDBPathInMemory(dbPath) ? |
| 140 | ":" + graphName : |
| 141 | storage::StorageUtils::getGraphPath(dbPath, graphName); |
| 142 | auto storageManager = std::make_unique<storage::StorageManager>(graphPath, false, false, |
| 143 | *memoryManager, false, clientContext->getDBConfig()->enableDefaultHashIndex, |
| 144 | common::VirtualFileSystem::GetUnsafe(*clientContext)); |
| 145 | storageManager->initDataFileHandle(common::VirtualFileSystem::GetUnsafe(*clientContext), |
| 146 | clientContext); |
| 147 | catalog->setStorageManager(std::move(storageManager)); |
| 148 | |
| 149 | if (isAnyGraph) { |
| 150 | // Use DUMMY_CHECKPOINT_TRANSACTION to create tables |
| 151 | auto* dummyTransaction = &transaction::DUMMY_CHECKPOINT_TRANSACTION; |
| 152 | |
| 153 | // Create serial name for the id column: _nodes_id_serial |
| 154 | auto serialName = "_nodes_id_serial"; |
| 155 | auto serialLiteral = |
| 156 | std::make_unique<parser::ParsedLiteralExpression>(Value(serialName), serialName); |
| 157 | auto serialDefault = std::make_unique<parser::ParsedFunctionExpression>( |
| 158 | function::NextValFunction::name, std::move(serialLiteral), serialName); |
| 159 | |
| 160 | std::vector<binder::PropertyDefinition> nodeProperties; |
| 161 | nodeProperties.emplace_back(binder::PropertyDefinition( |
| 162 | binder::ColumnDefinition("id", common::LogicalType::SERIAL()), |
| 163 | std::move(serialDefault))); |
| 164 | nodeProperties.emplace_back(binder::PropertyDefinition(binder::ColumnDefinition("label", |
| 165 | common::LogicalType::LIST(common::LogicalType::STRING())))); |
| 166 | nodeProperties.emplace_back( |
| 167 | binder::PropertyDefinition(binder::ColumnDefinition("data", LogicalType::JSON()))); |
nothing calls this directly
no test coverage detected