| 46 | } |
| 47 | |
| 48 | void CreateIndex::executeInternal(ExecutionContext* context) { |
| 49 | auto clientContext = context->clientContext; |
| 50 | auto catalog = Catalog::Get(*clientContext); |
| 51 | auto transaction = transaction::Transaction::Get(*clientContext); |
| 52 | auto memoryManager = storage::MemoryManager::Get(*clientContext); |
| 53 | auto storageManager = storage::StorageManager::Get(*clientContext); |
| 54 | const auto indexNameExists = catalog->containsIndex(transaction, info.tableID, info.indexName); |
| 55 | const auto indexedPropertyExists = |
| 56 | catalog->containsIndex(transaction, info.tableID, info.propertyID); |
| 57 | if (indexNameExists || indexedPropertyExists) { |
| 58 | const auto existingIndexName = indexNameExists ? info.indexName : |
| 59 | getExistingIndexName(catalog, transaction, |
| 60 | info.tableID, info.propertyID); |
| 61 | switch (info.onConflict) { |
| 62 | case ConflictAction::ON_CONFLICT_DO_NOTHING: { |
| 63 | appendMessage(std::format("Index {} already exists.", existingIndexName), |
| 64 | memoryManager); |
| 65 | return; |
| 66 | } |
| 67 | case ConflictAction::ON_CONFLICT_THROW: { |
| 68 | throw BinderException(existingIndexName + " already exists in catalog."); |
| 69 | } |
| 70 | default: |
| 71 | UNREACHABLE_CODE; |
| 72 | } |
| 73 | } |
| 74 | auto* table = storageManager->getTable(info.tableID)->ptrCast<storage::NodeTable>(); |
| 75 | const auto storageIndexNameExists = table->getIndex(info.indexName).has_value(); |
| 76 | auto storagePKIndexExists = table->tryGetPrimaryKeyIndex() != nullptr; |
| 77 | const auto canCreatePhysicalIndex = |
| 78 | !storageIndexNameExists && (!info.isPrimary || !storagePKIndexExists); |
| 79 | auto indexTypeOptional = storageManager->getIndexType(info.indexType); |
| 80 | if (!indexTypeOptional.has_value()) { |
| 81 | throw BinderException(std::format("Index type {} does not exist.", info.indexType)); |
| 82 | } |
| 83 | const auto& indexType = indexTypeOptional.value().get(); |
| 84 | if (info.isPrimary && storagePKIndexExists && |
| 85 | table->tryGetPrimaryKeyIndex()->getIndexInfo().indexType != indexType.typeName) { |
| 86 | throw BinderException(std::format( |
| 87 | "Cannot create {} index because the table already has a {} primary-key index.", |
| 88 | indexType.typeName, table->tryGetPrimaryKeyIndex()->getIndexInfo().indexType)); |
| 89 | } |
| 90 | if (canCreatePhysicalIndex) { |
| 91 | storage::IndexInfo indexInfo{info.indexName, indexType.typeName, info.tableID, |
| 92 | {info.columnID}, {info.keyDataType}, info.isPrimary, |
| 93 | indexType.definitionType == storage::IndexDefinitionType::BUILTIN}; |
| 94 | std::unique_ptr<storage::Index> index; |
| 95 | if (StringUtils::caseInsensitiveEquals(indexType.typeName, |
| 96 | storage::PrimaryKeyIndex::getIndexType().typeName)) { |
| 97 | index = storage::PrimaryKeyIndex::createNewIndex(std::move(indexInfo), |
| 98 | storageManager->isInMemory(), *memoryManager, |
| 99 | *storageManager->getDataFH()->getPageManager(), &storageManager->getShadowFile()); |
| 100 | } else if (StringUtils::caseInsensitiveEquals(indexType.typeName, |
| 101 | storage::ArtPrimaryKeyIndex::getIndexType().typeName)) { |
| 102 | index = storage::ArtPrimaryKeyIndex::createNewIndex(std::move(indexInfo)); |
| 103 | } else { |
| 104 | throw BinderException( |
| 105 | std::format("Index type {} is not supported by CREATE INDEX.", indexType.typeName)); |
nothing calls this directly
no test coverage detected