Преглед на файлове

DB implementation working

logicp преди 5 години
родител
ревизия
4ded55efd3
променени са 4 файла, в които са добавени 236 реда и са изтрити 59 реда
  1. 22 0
      src/CMakeLists.txt
  2. 122 22
      src/interfaces/DatabaseConnection.cpp
  3. 6 5
      src/interfaces/DatabaseConnection.h
  4. 86 32
      src/main.cpp

+ 22 - 0
src/CMakeLists.txt

@@ -0,0 +1,22 @@
+cmake_minimum_required(VERSION 2.8)
+# g++ main.cpp -std=c++17 -lpqxx -lpq -B /interfaces -o kiq
+project(untitled)
+
+#SET(INCLUDE_HEADERS "/usr/local/include/pqxx ./interfaces")
+#SET(COMPILER_FLAGS "-std=c++17 -lpqxx -lpq")
+#SET(LINKER_FLAGS "-L/usr/local/include/pqxx")
+
+#SET(CMAKE_EXE_LINKER_FLAGS  "${LINKER_FLAGS}")
+#SET(CMAKE_CXX_FLAGS "${COMPILER_FLAGS} -I${INCLUDE_HEADERS}")
+
+set(CMAKE_CXX_STANDARD 17)
+
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -lpqxx -lpq")
+set(PQXX /usr/local/include/pqxx)
+find_library(PQXX_LIB pqxx)
+find_library(PQ_LIB pq)
+
+add_executable(${PROJECT_NAME} "main.cpp" "interfaces/DatabaseConnection.cpp")
+
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${PQXX_LIB} ${PQ_LIB})
+

+ 122 - 22
src/interfaces/DatabaseConnection.cpp

@@ -1,44 +1,144 @@
 #include "DatabaseConnection.h"
-#include "structs.h"
+#include <iostream>
+#include <pqxx/pqxx>
 #include <sstream>
+#include <utility>
+#include "structs.h"
 
-DatabaseConnection::DatabaseConnection() {}
+std::string fieldsAsString(std::vector<std::string> fields) {
+  std::string field_string{"("};
+  std::string delim = "";
 
-bool DatabaseConnection::isConnected() {
-  return this->connected ? true : false;
+  for (const auto &field : fields) {
+    std::cout << field << std::endl;
+    field_string += delim + field;
+    delim += ",";
+  }
+  std::cout << field_string << std::endl;
+  field_string += ")";
+  return std::move(field_string);
 }
 
+// https://en.wikipedia.org/wiki/Row-_and_column-major_order
+std::string valuesAsString(std::vector<std::string> values, size_t number_of_fields) {
+  std::string value_string{"VALUES ("};
+  int index = 1;
+  for (const auto &value : values) {
+    if (index % number_of_fields == 0) {
+      value_string += value + "), (";
+    } else {
+      value_string += value + ",";
+    }
+    index++;
+  }
+  value_string.erase(value_string.size() - 3);
+
+  return std::move(value_string);
+}
+
+std::string insertStatement(DatabaseQuery query) {
+  return std::string{"INSERT INTO " + query.table + fieldsAsString(query.fields) + valuesAsString(query.values, query.fields.size())};
+}
+
+std::string selectStatement(DatabaseQuery query) {
+  return std::string{"SELECT " + fieldsAsString(query.fields) + " FROM " + query.table};
+}
+
+// TODO: Update query
+// TODO: Filtering
+
+DatabaseConnection::DatabaseConnection() {}
+
 bool DatabaseConnection::setConfig(DatabaseConfiguration config) {
   m_config = config;
+  m_db_name = config.credentials.name;
   return true;
 }
 
+pqxx::result DatabaseConnection::performInsert (DatabaseQuery query) {
+  pqxx::connection connection(getConnectionString().c_str());
+  pqxx::work worker(connection);
+  pqxx::result pqxx_result = worker.exec(insertStatement(query));
+  worker.commit();
+
+  return pqxx_result;
+}
+
 // std::string DatabaseConnection::getDbName(){return }
 
+std::string DatabaseConnection::getConnectionString() {
+  std::string connectionString{};
+      connectionString += "dbname = ";
+      connectionString += m_config.credentials.name;
+      connectionString += " user = ";
+      connectionString += m_config.credentials.user;
+      connectionString += " password = ";
+      connectionString += m_config.credentials.password;
+      connectionString += " hostaddr = ";
+      connectionString += m_config.address;
+      connectionString += " port = ";
+      connectionString += m_config.port;
+      std::cout << connectionString << std::endl;
+    return connectionString;
+}
+
 QueryResult DatabaseConnection::query(DatabaseQuery query) {
   switch (query.type) {
-  case QueryType::INSERT: {
-    std::stringstream query_stream{};
+    case QueryType::SELECT: {
+      std::stringstream query_stream{};
+      query_stream << "SELECT * FROM " << query.table;
+      pqxx::connection connection(getConnectionString().c_str());
+      pqxx::work worker(connection);
+      pqxx::result pqxx_result = worker.exec(query_stream.str());
 
-    query_stream << "INSERT INTO" << query.table << " VALUES (\"test\")";
-    QueryResult result{};
-    break;
-  }
-  case QueryType::DELETE:
-    std::stringstream query_stream{};
+      QueryResult result{};
+      result.table = query.table;
+
+      for (auto row : pqxx_result) {
+        auto row_c_str = row[0].c_str();
+        if (row_c_str != nullptr) {
+          std::string row_string(row_c_str);
+          auto pair = std::make_pair("table", row_string);
+          result.values.push_back(pair);
+        }
+      }
+      return result;
+    }
+
+    case QueryType::INSERT: {
+      auto pqxx_result = performInsert(query);
+      QueryResult result{};
+
+      for (auto row : pqxx_result) {
+        auto row_c_str = row[0].c_str();
+        std::cout << "Insert row result" << row_c_str << std::endl;
+        if (row_c_str != nullptr) {
+          std::string row_string(row_c_str);
+          auto pair = std::make_pair("table", row_string);
+          result.values.push_back(pair);
+        }
+      }
+      return result;
+    }
+
+    case QueryType::DELETE: {
+      std::stringstream query_stream{};
 
-    query_stream << "INSERT INTO" << query.table << " VALUES (\"test\")";
-    QueryResult result{};
-    return result;
+      query_stream << " " << query.table << " VALUES (\"test\")";
+      QueryResult result{};
+      return result;
+    }
   }
+  return QueryResult{};
 }
 
-bool DatabaseConnection::connectToDatabase() {
-  pqxx::connection C("dbname = kiq user = kiqadmin password = kiqadmin \
-      hostaddr = 127.0.0.1 port = 5432");
-  m_connection = std::move(&C);
+pqxx::connection DatabaseConnection::getConnection() {
+  std::string connectionString{("dbname = " + m_config.credentials.name +
+                                " user = " + m_config.credentials.user +
+                                " password = " + m_config.credentials.password +
+                                " hostaddr = " + m_config.address + " port " +
+                                m_config.port)};
+  return pqxx::connection(connectionString);
 }
 
-std::string DatabaseConnection::getDbName() {
-  return std::to_string(*m_connection->dbname());
-}
+std::string DatabaseConnection::getDbName() { return m_db_name; }

+ 6 - 5
src/interfaces/DatabaseConnection.h

@@ -10,17 +10,18 @@ public:
   DatabaseConnection();
   // init db
   bool setConfig(DatabaseConfiguration config);
-  bool connectToDatabase();
   // work
   QueryResult query(DatabaseQuery query);
   // state
-  bool isConnected();
   std::string getDbName();
 
 private:
   DatabaseConfiguration m_config;
-  pqxx::connection *m_connection;
-  bool connected;
+  std::string m_db_name;
+  pqxx::connection getConnection();
+  std::string getConnectionString();
+  pqxx::result performInsert(DatabaseQuery query);
+//  bool connected;
 };
 
-#endif // DATABASECONNECTION_H
+#endif // DATABASECONNECTION_H

+ 86 - 32
src/main.cpp

@@ -1,5 +1,3 @@
-#include "interfaces/DatabaseConnection.h"
-#include "interfaces/structs.h"
 #include <array>
 #include <iostream>
 #include <pqxx/pqxx>
@@ -7,38 +5,94 @@
 #include <string>
 #include <vector>
 
-int main() {
-  try {
-    DatabaseCredentials credentials{};
-    credentials.user = "kiqadmin";
-    credentials.password = "kiqadmin";
-    credentials.name = "kiq";
-
-    DatabaseConfiguration configuration{};
-    configuration.credentials = credentials;
-    configuration.address = "127.0.0.1";
-    configuration.port = "5432";
-
-    DatabaseConnection connection{};
-    connection.setConfig(configuration);
-
-    if (connection.connectToDatabase()) {
-      std::cout << "Opened database successfully: " << connection.getDbName()
-                << std::endl;
-      // pqxx::work W(C);
-      // pqxx::result R = W.exec("SELECT value from test");
-
-      // for (auto row : R) {
-      //   std::cout << row[0].c_str() << std::endl;
-      // }
-    } else {
-      std::cout << "Can't open database" << std::endl;
-      return 1;
+#include "interfaces/DatabaseConnection.h"
+#include "interfaces/structs.h"
+
+typedef std::vector<std::string> stringvec;
+
+DatabaseConfiguration getConfiguration() {
+  DatabaseCredentials credentials{};
+  credentials.user = "kiqadmin";
+  credentials.password = "kiqadmin";
+  credentials.name = "kiq";
+
+  DatabaseConfiguration configuration{};
+  configuration.credentials = credentials;
+  configuration.address = "127.0.0.1";
+  configuration.port = "5432";
+
+  return configuration;
+}
+
+
+stringvec ask_for_fields() {
+  bool stop_asking = false;
+  stringvec fields{};
+  do {
+    std::cout << "Field? Y/N" << std::endl;
+    std::string response{};
+    std::cin >> response;
+
+    if (response == "N" || response == "n") {
+      stop_asking = true;
     }
-  } catch (const std::exception &e) {
-    std::cerr << e.what() << std::endl;
-    return 1;
+
+    std::cout << "Field:" << std::endl;
+    std::string field{};
+    std::cin >> field;
+    fields.push_back(field);
+  } while (!stop_asking);
+  return fields;
+}
+
+stringvec ask_for_values() {
+  bool stop_asking = false;
+  stringvec values{};
+  int index = 1;
+  do {
+    std::cout << "Value? Y/N" << std::endl;
+    std::string response{};
+    std::getline(std::cin, response);
+
+    if (response == "N" || response == "n") {
+      stop_asking = true;
+    }
+
+    std::cout << index << std::endl;
+    std::string value{};
+    values.push_back((std::cin, value));
+    index++;
+  } while (!stop_asking);
+  return values;
+}
+
+void performQuery(DatabaseConnection* connection) {
+  DatabaseQuery query{};
+  query.type = QueryType::SELECT;
+  query.table = "test";
+  QueryResult result = connection->query(query);
+
+  for (auto row : result.values) {
+    std::cout << row.second << std::endl;
   }
 
+  DatabaseQuery insert_query{};
+  insert_query.type = QueryType::INSERT;
+  insert_query.table = "test";
+  insert_query.fields = ask_for_fields();
+  insert_query.values = ask_for_values();
+
+  QueryResult insert_result = connection->query(insert_query);
+
+  for (auto row : insert_result.values) {
+    std::cout << row.second << std::endl;
+  }
+}
+
+int main() {
+  DatabaseConnection connection;
+  connection.setConfig(getConfiguration());
+  performQuery(&connection);
+
   return 0;
 }