Last active
January 29, 2025 19:30
-
-
Save aneury1/4fb5210b16301f4b55ef54138282be07 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <wx/wx.h> | |
#include <wx/menu.h> | |
#include <stdio.h> | |
#include <vector> | |
#include <string> | |
#include <sstream> | |
#include <functional> | |
#include <sqlite3.h> | |
struct InternalSqliteResponse | |
{ | |
int columnCount; | |
std::vector<std::vector<std::string>> rows; | |
std::vector<std::string> columnNames; | |
}; | |
enum DataType | |
{ | |
Text, | |
Number, | |
Boolean | |
}; | |
enum class Constraint | |
{ | |
PrimaryKey, | |
AutoIncrement, | |
NotNull | |
}; | |
struct Column | |
{ | |
std::string name; | |
int type; | |
std::string value; | |
std::vector<Constraint> constraints; | |
// Constructor | |
Column() : name(""), type(Text), value("") {} | |
Column(const std::string &colName, int colType, const std::string &colValue, std::vector<Constraint> colConstraints) | |
: name(colName), type(colType), value(colValue), constraints(colConstraints) {} | |
// Generate Table Schema string | |
std::string toString() | |
{ | |
std::ostringstream ss; | |
ss << name << " "; | |
switch (type) | |
{ | |
case Text: | |
ss << "TEXT"; | |
break; | |
case Number: | |
ss << "INTEGER"; | |
break; | |
case Boolean: | |
ss << "BOOLEAN"; | |
break; | |
} | |
for (const auto &constraint : constraints) | |
{ | |
switch (constraint) | |
{ | |
case Constraint::PrimaryKey: | |
ss << " PRIMARY KEY"; | |
break; | |
case Constraint::AutoIncrement: | |
ss << " AUTOINCREMENT"; | |
break; | |
case Constraint::NotNull: | |
ss << " NOT NULL"; | |
break; | |
} | |
} | |
return ss.str(); | |
} | |
}; | |
struct SqlTable | |
{ | |
std::vector<Column> columns; | |
std::string tableName; | |
// Constructor: Always contains first ID column as PRIMARY KEY (not AUTOINCREMENT) | |
SqlTable(const std::string table) | |
{ | |
columns.push_back(Column("id", Number, "", {Constraint::PrimaryKey})); | |
tableName = table; | |
} | |
void setColumnValue(const std::string& columnName, const std::string& newValue) { | |
for (auto& col : columns) { | |
if (col.name == columnName) { | |
col.value = newValue; | |
return; | |
} | |
} | |
} | |
// Generate Table Schema string | |
std::string toString() | |
{ | |
std::ostringstream ss; | |
ss << "CREATE TABLE " << tableName << " ("; | |
for (size_t i = 0; i < columns.size(); ++i) | |
{ | |
ss << columns[i].toString(); | |
if (i < columns.size() - 1) | |
ss << ", "; | |
} | |
ss << ");"; | |
return ss.str(); | |
} | |
// Generate SQL INSERT statement | |
std::string generateInsert() | |
{ | |
std::ostringstream ss; | |
ss << "INSERT INTO " << tableName << " ("; | |
for (size_t i = 1; i < columns.size(); ++i) | |
{ | |
ss << columns[i].name; | |
if (i < columns.size() - 1) | |
ss << ", "; | |
} | |
ss << ") VALUES ("; | |
for (size_t i = 1; i < columns.size(); ++i) | |
{ | |
ss << "?"; | |
if (i < columns.size() - 1) | |
ss << ", "; | |
} | |
ss << ");"; | |
return ss.str(); | |
} | |
// Generate SQL SELECT statement | |
std::string generateSelect() | |
{ | |
return "SELECT * FROM " + tableName + ";"; | |
} | |
// Generate SQL UPDATE statement | |
std::string generateUpdate() | |
{ | |
std::ostringstream ss; | |
ss << "UPDATE " << tableName << " SET "; | |
for (size_t i = 1; i < columns.size(); ++i) | |
{ | |
ss << columns[i].name << " = ?"; | |
if (i < columns.size() - 1) | |
ss << ", "; | |
} | |
ss << " WHERE id = ?;"; | |
return ss.str(); | |
} | |
// Generate SQL DELETE statement | |
std::string generateDelete() | |
{ | |
return "DELETE FROM " + tableName + " WHERE id = ?;"; | |
} | |
}; | |
// SQLite Execution Function with Callback | |
bool executeSqliteQuery(sqlite3 *db, const std::string &query, std::function<void(int, InternalSqliteResponse)> callback) | |
{ | |
char *errMsg = nullptr; | |
InternalSqliteResponse response; | |
auto internalCallback = [](void *resp, int argc, char **argv, char **colNames) -> int | |
{ | |
auto &responseRef = *static_cast<InternalSqliteResponse *>(resp); | |
std::vector<std::string> row; | |
for (int i = 0; i < argc; ++i) | |
{ | |
row.push_back(argv[i] ? argv[i] : "NULL"); | |
} | |
responseRef.rows.push_back(row); | |
if (responseRef.columnNames.empty()) | |
{ | |
for (int i = 0; i < argc; ++i) | |
{ | |
responseRef.columnNames.push_back(colNames[i] ? colNames[i] : ""); | |
} | |
} | |
return 0; | |
}; | |
int rc = sqlite3_exec(db, query.c_str(), internalCallback, &response, &errMsg); | |
if (rc != SQLITE_OK) | |
{ | |
std::cerr << "SQL Error: " << errMsg << std::endl; | |
sqlite3_free(errMsg); | |
} | |
response.columnCount = response.columnNames.size(); | |
callback(rc, response); | |
return rc == SQLITE_OK; | |
} | |
SqlTable querySqliteTable(sqlite3* db, const std::string& tableName) { | |
SqlTable table(tableName); | |
std::string query = "PRAGMA table_info(" + tableName + ");"; | |
executeSqliteQuery(db, query, [&](int result, InternalSqliteResponse response) { | |
if (result == SQLITE_OK) { | |
table.columns.clear(); | |
for (const auto& row : response.rows) { | |
if (row.size() >= 2) { | |
std::string colName = row[1]; | |
int colType = (row[2] == "INTEGER") ? Number : (row[2] == "TEXT") ? Text : Boolean; | |
table.columns.push_back(Column(colName, colType, "", {})); | |
} | |
} | |
} | |
}); | |
return table; | |
} | |
std::string generateSelectQuery(const std::string& tableName) { | |
return "SELECT * FROM " + tableName + ";"; | |
} | |
std::string generateInsertQuery(const std::string& tableName, const SqlTable& table) { | |
std::ostringstream ss; | |
ss << "INSERT INTO " << tableName << " ("; | |
for (size_t i = 1; i < table.columns.size(); ++i) { | |
ss << table.columns[i].name; | |
if (i < table.columns.size() - 1) ss << ", "; | |
} | |
ss << ") VALUES ("; | |
for (size_t i = 1; i < table.columns.size(); ++i) { | |
ss << "'" << table.columns[i].value << "'"; | |
if (i < table.columns.size() - 1) ss << ", "; | |
} | |
ss << ");"; | |
return ss.str(); | |
} | |
std::string generateUpdateQuery(const std::string& tableName, const SqlTable& table, const std::string& condition) { | |
std::ostringstream ss; | |
ss << "UPDATE " << tableName << " SET "; | |
for (size_t i = 1; i < table.columns.size(); ++i) { | |
ss << table.columns[i].name << " = '" << table.columns[i].value << "'"; | |
if (i < table.columns.size() - 1) ss << ", "; | |
} | |
ss << " WHERE " << condition << ";"; | |
return ss.str(); | |
} | |
std::string generateDeleteQuery(const std::string& tableName, const std::string& condition) { | |
return "DELETE FROM " + tableName + " WHERE " + condition + ";"; | |
} | |
struct Window : public wxFrame | |
{ | |
wxPanel *sideMenuContainer = new wxPanel(this, wxID_ANY); | |
wxPanel *editorContainer = new wxPanel(this, wxID_ANY); | |
Window() : wxFrame(nullptr, wxID_ANY, wxT("App")) | |
{ | |
Maximize(); | |
auto sizer = new wxBoxSizer(wxHORIZONTAL); | |
sqlite3 *db; | |
if (sqlite3_open("example2.db", &db)) | |
{ | |
std::cerr << "Can't open database: " << sqlite3_errmsg(db) << std::endl; | |
return; | |
} | |
SqlTable table("Usuarios2"); | |
table.columns.push_back(Column("name", Text, "", {})); | |
table.columns.push_back(Column("age", Number, "", {})); | |
wxTextCtrl *text = new wxTextCtrl(editorContainer, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE); | |
text->SetBackgroundColour(wxColour(0x43, 0x43, 0x43, 255)); | |
wxBoxSizer *sizerM = new wxBoxSizer(wxHORIZONTAL); | |
sizerM->Add(text, 1, wxEXPAND | wxALL, 0); | |
editorContainer->SetSizer(sizerM); | |
text->SetValue(wxString(table.toString() + "\r\n")); | |
std::string createTableQuery = table.toString(); | |
executeSqliteQuery(db, createTableQuery, [text](int result, InternalSqliteResponse response) | |
{ | |
if (result == SQLITE_OK) { | |
std::cout << "Table created successfully." << std::endl; | |
text->AppendText("\r\nTable Created Successfully"); | |
} else { | |
text->AppendText("\r\nTable Created with Error"); | |
std::cout << "Failed to create table." << std::endl; | |
} }); | |
auto tableQueried = querySqliteTable(db, table.tableName); | |
text->AppendText("\r\nTable Queried:\n\n"+tableQueried.toString()); | |
for(int i=0;i<65536*2;i++) | |
{ | |
table.setColumnValue("name", std::to_string(i+10)+"Cybord"); | |
table.setColumnValue("age", std::to_string(i+10)); | |
std::string insertQuery = generateInsertQuery(table.tableName, table); | |
text->AppendText(wxT("Insert Query: [")+ wxString(insertQuery.c_str())+"]\r\n"); | |
executeSqliteQuery(db, insertQuery, [](int result, InternalSqliteResponse response) { | |
if (result == SQLITE_OK) { | |
std::cout << "Data inserted successfully." << std::endl; | |
} | |
}); | |
} | |
std::string selectQuery = generateSelectQuery(table.tableName); | |
executeSqliteQuery(db, selectQuery, [text](int result, InternalSqliteResponse response) { | |
for (const auto& row : response.rows) { | |
for (const auto& col : row) { | |
std::cout << col << " "; | |
text->AppendText(col+" "); | |
} | |
std::cout << std::endl; | |
text->AppendText("\r\n"); | |
} | |
}); | |
sqlite3_close(db); | |
editorContainer->SetBackgroundColour(wxColor(0xff, 0x10, 0x63, 255)); | |
sizer->Add(editorContainer, 20, wxEXPAND | wxALL, 2); | |
SetSizer(sizer); | |
} | |
}; | |
class Application : public wxApp | |
{ | |
public: | |
virtual bool OnInit() | |
{ | |
auto app = new Window(); | |
app->Show(true); | |
return true; | |
} | |
}; | |
wxIMPLEMENT_APP(Application); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment