--- a/src/SqlHandler.h Mon May 25 21:11:17 2020 +0200
+++ b/src/SqlHandler.h Sun May 31 16:56:07 2020 +0200
@@ -75,6 +75,7 @@
}
}
+ // TODO: support comments at the end of the script (after last ;)
string_t remainingSql = scanner.getAndReset();
for (wchar_t ch : remainingSql) if (ch != L' ' && ch != L'\n' && ch != L'\r' && ch != L'\t') throw SqlException(L"Unexpected EOF, missing „;“ after: „" + remainingSql + L"“");
@@ -85,56 +86,59 @@
if (input == nullptr) return;
*input >> std::ws >> std::noskipws;
for (std::wstringstream sql; readNextSqlStatement(input, &sql);) {
- std::unique_ptr<PreparedStatement> prepared(connection->prepareStatement(convertor.to_bytes(sql.str()).c_str()));
- while (prepared->next());
+ std::unique_ptr<PreparedStatement> prepared(connection->prepareStatement(sql.str()));
+ prepared->executeUpdate();
}
}
- relpipe::writer::TypeId findType(string_t columnName, int columnIndex, const Statement& statement, std::shared_ptr<PreparedStatement> preparedStatement) {
+ relpipe::writer::TypeId findType(string_t columnName, const Statement& statement, relpipe::writer::TypeId typeFromResultSet) {
for (TypeCast typeCast : statement.typeCasts) if (typeCast.name == columnName) return relationalWriter->toTypeId(typeCast.type);
- return preparedStatement->getColumType(columnIndex);
+ return typeFromResultSet;
}
void processStatement(const Statement& statement) {
- std::shared_ptr<PreparedStatement> prepared(connection->prepareStatement(convertor.to_bytes(statement.sql).c_str()));
- int columnCount = prepared->getColumnCount();
+ std::shared_ptr<PreparedStatement> prepared(connection->prepareStatement(statement.sql));
int parameterCount = statement.parameters.size();
for (int i = 0; i < parameterCount; i++) {
- prepared->setString(i + 1, convertor.to_bytes(statement.parameters[i].value));
+ prepared->setString(i + 1, statement.parameters[i].value);
}
+ std::shared_ptr<ResultSet> resultSet(prepared->executeQuery());
+ std::shared_ptr<ResultSet::MetaData> metaData(resultSet->getMetaData());
+
+ auto columnCount = metaData->getColumnCount();
std::vector<relpipe::writer::AttributeMetadata> metadata;
- for (int i = 0; i < columnCount; i++) {
- string_t columnName = convertor.from_bytes(prepared->getColumName(i).c_str());
- metadata.push_back({columnName, findType(columnName, i, statement, prepared)});
+ for (int columnNumber = 1; columnNumber <= columnCount; columnNumber++) {
+ auto columnDescriptor = metaData->describeColumn(columnNumber);
+ metadata.push_back({columnDescriptor.name, findType(columnDescriptor.name, statement, columnDescriptor.type)});
}
relationalWriter->startRelation(statement.relation, metadata, true);
- while (prepared->next()) {
- for (int i = 0; i < columnCount; i++) {
- relationalWriter->writeAttribute(convertor.from_bytes(prepared->getString(i)));
+ while (resultSet->next()) {
+ for (int columnNumber = 1; columnNumber <= columnCount; columnNumber++) {
+ relationalWriter->writeAttribute(resultSet->getString(columnNumber));
}
}
}
- std::vector<string_t> getAllRelations() {
- std::vector<string_t> relations;
- std::unique_ptr<PreparedStatement> prepared(connection->prepareStatement("SELECT name FROM sqlite_master WHERE type IN ('table', 'view')"));
- while (prepared->next()) relations.push_back(convertor.from_bytes(prepared->getString(0)));
- return relations;
- }
-
void copyRelations(const CopyRelations& copy) {
std::wregex pattern(copy.pattern);
- for (string_t relation : getAllRelations()) {
- if (regex_match(relation, pattern)) {
+ relpipe::writer::string_t userName = connection->getUserName();
+ for (Connection::TablePrivilege tableMetaData : connection->getTablePrivileges()) {
+ if (regex_match(tableMetaData.name, pattern) && tableMetaData.privilege == L"SELECT" && tableMetaData.grantee == userName) {
+ // TODO: May we have multiple SELECT permissions for same table? Copy it only once.
std::wstringstream select;
select << L"SELECT * FROM ";
- writeIdentifier(select, relation);
+ if (tableMetaData.schema.size()) {
+ // TODO: use qualified table name also for regex matching and for relation name
+ writeIdentifier(select, tableMetaData.schema);
+ select << L".";
+ }
+ writeIdentifier(select, tableMetaData.name);
Statement statement;
- statement.relation = copy.replace ? regex_replace(relation, pattern, copy.replacement) : relation;
+ statement.relation = copy.replace ? regex_replace(tableMetaData.name, pattern, copy.replacement) : tableMetaData.name;
statement.sql = select.str();
processStatement(statement);
}
@@ -170,8 +174,9 @@
file = ":memory:";
}
- connection.reset(new Connection(file.c_str()));
- connection->setAutoCommit(false);
+ connection.reset(driverManager->getConnectionByDSN(L"sqlite-memory")); // FIXME: custom DSN and files
+ connection.reset(driverManager->getConnectionByDSN(L"relpipe")); // FIXME: custom DSN and files
+ //connection->setAutoCommit(false);
}
virtual ~SqlHandler() {
@@ -194,8 +199,8 @@
}
sql << L"\n)";
- std::unique_ptr<PreparedStatement> createTable(connection->prepareStatement(convertor.to_bytes(sql.str()).c_str()));
- createTable->next();
+ std::unique_ptr<PreparedStatement> createTable(connection->prepareStatement(sql.str()));
+ createTable->executeUpdate();
// prepare INSERT:
sql = wstringstream();
@@ -207,7 +212,7 @@
if (i < attributes.size() - 1) sql << L",";
}
sql << L")";
- currentInsert.reset(connection->prepareStatement(convertor.to_bytes(sql.str()).c_str()));
+ currentInsert.reset(connection->prepareStatement(sql.str()));
}
void attribute(const void* value, const std::type_info& typeInfo) override {
@@ -233,7 +238,7 @@
{
assert(typeInfo == typeid (string_t));
auto* typedValue = static_cast<const string_t*> (value);
- currentInsert->setString(currentAttributeIndex, convertor.to_bytes(*typedValue).c_str());
+ currentInsert->setString(currentAttributeIndex, *typedValue);
break;
}
default:
@@ -241,7 +246,7 @@
}
if (currentAttributeIndex % currentReaderMetadata.size() == 0) {
- currentInsert->next();
+ currentInsert->executeUpdate();
currentInsert->reset();
currentAttributeIndex = 0;
}