| 83 | } |
| 84 | |
| 85 | std::unique_ptr<BoundStatement> Binder::bindImportDatabaseClause(const Statement& statement) { |
| 86 | auto& importDB = statement.constCast<ImportDB>(); |
| 87 | auto fs = VirtualFileSystem::GetUnsafe(*clientContext); |
| 88 | auto boundFilePath = fs->expandPath(clientContext, importDB.getFilePath()); |
| 89 | if (!fs->fileOrPathExists(boundFilePath, clientContext)) { |
| 90 | throw BinderException(std::format("Directory {} does not exist.", boundFilePath)); |
| 91 | } |
| 92 | std::string finalQueryStatements; |
| 93 | finalQueryStatements += |
| 94 | getQueryFromFile(fs, boundFilePath, PortDBConstants::SCHEMA_FILE_NAME, clientContext); |
| 95 | // replace the path in copy from statements with the bound path |
| 96 | auto copyQuery = |
| 97 | getQueryFromFile(fs, boundFilePath, PortDBConstants::COPY_FILE_NAME, clientContext); |
| 98 | if (!copyQuery.empty()) { |
| 99 | auto parsedStatements = Parser::parseQuery(copyQuery); |
| 100 | for (auto& parsedStatement : parsedStatements) { |
| 101 | DASSERT(parsedStatement->getStatementType() == StatementType::COPY_FROM); |
| 102 | auto& copyFromStatement = parsedStatement->constCast<CopyFrom>(); |
| 103 | DASSERT(copyFromStatement.getSource()->type == ScanSourceType::FILE); |
| 104 | auto filePaths = |
| 105 | copyFromStatement.getSource()->constPtrCast<FileScanSource>()->filePaths; |
| 106 | DASSERT(filePaths.size() == 1); |
| 107 | auto fileTypeInfo = bindFileTypeInfo(filePaths); |
| 108 | std::string query; |
| 109 | auto copyFilePath = getCopyFilePath(boundFilePath, filePaths[0]); |
| 110 | auto columnNames = getColumnNamesToCopy(copyFromStatement); |
| 111 | auto parsingOptions = bindParsingOptions(copyFromStatement.getParsingOptions()); |
| 112 | std::unordered_map<std::string, std::string> copyFromOptions; |
| 113 | if (parsingOptions.contains(CopyConstants::FROM_OPTION_NAME)) { |
| 114 | DASSERT(parsingOptions.contains(CopyConstants::TO_OPTION_NAME)); |
| 115 | copyFromOptions[CopyConstants::FROM_OPTION_NAME] = std::format("'{}'", |
| 116 | parsingOptions.at(CopyConstants::FROM_OPTION_NAME).getValue<std::string>()); |
| 117 | copyFromOptions[CopyConstants::TO_OPTION_NAME] = std::format("'{}'", |
| 118 | parsingOptions.at(CopyConstants::TO_OPTION_NAME).getValue<std::string>()); |
| 119 | parsingOptions.erase(CopyConstants::FROM_OPTION_NAME); |
| 120 | parsingOptions.erase(CopyConstants::TO_OPTION_NAME); |
| 121 | } |
| 122 | if (fileTypeInfo.fileType == FileType::CSV) { |
| 123 | auto csvConfig = CSVReaderConfig::construct(parsingOptions); |
| 124 | csvConfig.option.autoDetection = false; |
| 125 | auto optionsMap = csvConfig.option.toOptionsMap(csvConfig.parallel); |
| 126 | if (!copyFromOptions.empty()) { |
| 127 | optionsMap.insert(copyFromOptions.begin(), copyFromOptions.end()); |
| 128 | } |
| 129 | query = |
| 130 | std::format("COPY `{}` {} FROM \"{}\" {};", copyFromStatement.getTableName(), |
| 131 | columnNames, copyFilePath, CSVOption::toCypher(optionsMap)); |
| 132 | } else { |
| 133 | query = |
| 134 | std::format("COPY `{}` {} FROM \"{}\" {};", copyFromStatement.getTableName(), |
| 135 | columnNames, copyFilePath, CSVOption::toCypher(copyFromOptions)); |
| 136 | } |
| 137 | finalQueryStatements += query; |
| 138 | } |
| 139 | } |
| 140 | return std::make_unique<BoundImportDatabase>(boundFilePath, finalQueryStatements, |
| 141 | getQueryFromFile(fs, boundFilePath, PortDBConstants::INDEX_FILE_NAME, clientContext)); |
| 142 | } |
nothing calls this directly
no test coverage detected