diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/connection.cpp | 10 | ||||
-rw-r--r-- | src/mysql.cpp | 32 | ||||
-rw-r--r-- | src/opcodes.cpp | 99 | ||||
-rw-r--r-- | src/postgresql.cpp | 90 | ||||
-rw-r--r-- | src/sqlite3.cpp | 44 | ||||
-rw-r--r-- | src/tools.cpp | 54 |
6 files changed, 183 insertions, 146 deletions
diff --git a/src/connection.cpp b/src/connection.cpp index 5ac0aa1..43175bd 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -109,7 +109,7 @@ void ConnectionData::Exec(char* sql) { } } -MYFLT ConnectionData::Scalar(char* sql, int row=0, int col=0) { +MYFLT ConnectionData::Scalar(char* sql, int row, int col) { if (!open) { throw std::runtime_error(badConnection); } @@ -136,7 +136,7 @@ MYFLT ConnectionData::Scalar(char* sql, int row=0, int col=0) { } -char* ConnectionData::ScalarString(char* sql, int row=0, int col=0) { +char* ConnectionData::ScalarString(char* sql, csnd::Csound* csound, int row, int col) { if (!open) { throw std::runtime_error(badConnection); } @@ -144,17 +144,17 @@ char* ConnectionData::ScalarString(char* sql, int row=0, int col=0) { switch (type) { #ifdef BUILD_POSTGRES case POSTGRES: - return postgres->ScalarString(sql, row, col); + return postgres->ScalarString(sql, csound, row, col); break; #endif #ifdef BUILD_SQLITE case SQLITE: - return sqlite->ScalarString(sql, row, col); + return sqlite->ScalarString(sql, csound, row, col); break; #endif #ifdef BUILD_MYSQL case MYSQL: - return mysql->ScalarString(sql, row, col); + return mysql->ScalarString(sql, csound, row, col); break; #endif default: diff --git a/src/mysql.cpp b/src/mysql.cpp index 040670e..381898b 100644 --- a/src/mysql.cpp +++ b/src/mysql.cpp @@ -20,6 +20,7 @@ */ #include <plugin.h> +#include "tools.h" #include <iostream> #include <cppconn/driver.h> #include <cppconn/exception.h> @@ -62,11 +63,12 @@ mysql::ResultSet* MySQLConnection::Query(char* sql) { return result; } -MYFLT MySQLConnection::Scalar(char* sql, int row=0, int col=0) { +MYFLT MySQLConnection::Scalar(char* sql, int row, int col) { mysql::ResultSet* res = Query(sql); mysql::ResultSetMetaData* meta = res->getMetaData(); int colCount = meta->getColumnCount(); if (col > colCount - 1) { + delete res; throw std::runtime_error("column number out of range"); } @@ -78,12 +80,13 @@ MYFLT MySQLConnection::Scalar(char* sql, int row=0, int col=0) { return result; } -char* MySQLConnection::ScalarString(char* sql, int row=0, int col=0) { +char* MySQLConnection::ScalarString(char* sql, csnd::Csound* csound, int row, int col) { mysql::ResultSet* res = Query(sql); mysql::ResultSetMetaData* meta = res->getMetaData(); int colCount = meta->getColumnCount(); if (col > colCount - 1) { + delete res; throw std::runtime_error("column number out of range"); } @@ -91,7 +94,7 @@ char* MySQLConnection::ScalarString(char* sql, int row=0, int col=0) { for (int rowIndex = 0; rowIndex <= row; rowIndex++) { res->next(); } - char* result = res->getString(col + 1).c_str(); + char* result = csound->strdup((char*) res->getString(col + 1).c_str()); delete res; @@ -101,31 +104,18 @@ char* MySQLConnection::ScalarString(char* sql, int row=0, int col=0) { void MySQLConnection::ToArray(mysql::ResultSet* result, csnd::Csound* csound, ARRAYDAT* array, bool asString) { mysql::ResultSetMetaData* meta = result->getMetaData(); - int colNum = meta->getColumnCount(); - int rowNum = result->rowsCount(); - int totalResults = colNum * rowNum; - array->sizes = csound->calloc(sizeof(int32_t) * 2); - array->sizes[0] = rowNum; - array->sizes[1] = colNum; - array->dimensions = 2; - CS_VARIABLE *var = array->arrayType->createVariable(csound, NULL); - array->arrayMemberSize = var->memBlockSize; - array->data = csound->calloc(var->memBlockSize * totalResults); - STRINGDAT* strings; - if (asString) { - strings = (STRINGDAT*) array->data; - } + int cols = meta->getColumnCount(); + int rows = result->rowsCount(); + STRINGDAT* strings = arrayInit(csound, array, rows, cols); int colIndex; int index = 0; while (result->next()) { colIndex = 0; - while (colIndex < colNum) { + while (colIndex < cols) { if (asString) { - char* item = result->getString(colIndex + 1).c_str(); - strings[index].size = strlen(item) + 1; - strings[index].data = csound->strdup(item); + insertArrayStringItem(csound, strings, index, (char*) result->getString(colIndex + 1).c_str()); } else { array->data[index] = (MYFLT) result->getDouble(colIndex + 1); } diff --git a/src/opcodes.cpp b/src/opcodes.cpp index 3527f83..e82ce33 100644 --- a/src/opcodes.cpp +++ b/src/opcodes.cpp @@ -95,11 +95,11 @@ public: try { switch (queryData->queryType) { case SCALARSTRING: { - std::string resultString = connection->ScalarString(queryData->sql, queryData->row, queryData->col); + std::string resultString = connection->ScalarString(queryData->sql, csound, queryData->row, queryData->col); if (charData != NULL) { csound->free(charData); } - charData = csound->strdup(resultString.c_str()); + charData = csound->strdup((char*) resultString.c_str()); charSize = resultString.length() + 1; } break; @@ -128,7 +128,7 @@ public: status = 1; done = true; pending = false; - error = csound->strdup(e.what()); + error = csound->strdup((char*) e.what()); } UNLOCK(connection); } @@ -440,12 +440,12 @@ struct dbexec : csnd::InPlug<2> { LOCK(connection); try { connection->Exec(sql.data); - return OK; } catch (const std::exception &e) { + UNLOCK(connection); return csound->init_error(e.what()); } UNLOCK(connection); - + return OK; } }; @@ -461,14 +461,15 @@ struct dbscalar : csnd::Plugin<1, 4> { return csound->init_error(badHandle); } STRINGDAT &sql = inargs.str_data(1); + LOCK(connection); try { - LOCK(connection); outargs[0] = connection->Scalar(sql.data, inargs[2], inargs[3]); - UNLOCK(connection); - return OK; } catch (const std::exception &e) { + UNLOCK(connection); return csound->init_error(e.what()); - } + } + UNLOCK(connection) + return OK; } }; @@ -479,6 +480,7 @@ struct dbscalarstr : csnd::Plugin<1, 4> { static constexpr char const *otypes = "S"; static constexpr char const *itypes = "iSoo"; ConnectionData* connection; + char* resultString; int init() { if (!(connection = getConnection(csound, inargs[0]))) { @@ -486,16 +488,20 @@ struct dbscalarstr : csnd::Plugin<1, 4> { } STRINGDAT &sql = inargs.str_data(1); STRINGDAT &result = outargs.str_data(0); + LOCK(connection); try { - LOCK(connection); - std::string resultString = connection->ScalarString(sql.data, inargs[2], inargs[3]); - UNLOCK(connection); - result.size = resultString.length() + 1; - result.data = csound->strdup(resultString.c_str()); - return OK; + if (resultString != NULL) { + csound->free(resultString); + } + resultString = connection->ScalarString(sql.data, csound, inargs[2], inargs[3]); + result.size = strlen(resultString) + 1; + result.data = resultString; } catch (const std::exception &e) { + UNLOCK(connection); return csound->init_error(e.what()); - } + } + UNLOCK(connection); + return OK; } }; @@ -516,15 +522,15 @@ struct dbarray : csnd::Plugin<1, 2> { STRINGDAT &sql = inargs.str_data(1); ARRAYDAT* array = (ARRAYDAT*) outargs(0); - + LOCK(connection); try { - LOCK(connection); connection->ArrayQuery(sql.data, csound, array); - UNLOCK(connection); - return OK; } catch (const std::exception &e) { + UNLOCK(connection); return csound->init_error(e.what()); } + UNLOCK(connection); + return OK; } }; @@ -544,15 +550,15 @@ struct dbarraystr : csnd::Plugin<1, 2> { STRINGDAT &sql = inargs.str_data(1); ARRAYDAT* array = (ARRAYDAT*) outargs(0); - + LOCK(connection); try { - LOCK(connection); connection->ArrayQueryString(sql.data, csound, array); - UNLOCK(connection); - return OK; } catch (const std::exception &e) { + UNLOCK(connection); return csound->init_error(e.what()); } + UNLOCK(connection); + return OK; } }; @@ -579,14 +585,15 @@ struct dbexec_kb : csnd::InPlug<2> { int kperf() { STRINGDAT &sql = args.str_data(1); + LOCK(connection); try { - LOCK(connection); connection->Exec(sql.data); - UNLOCK(connection); - return OK; } catch (const std::exception &e) { + UNLOCK(connection); return csound->perf_error(e.what(), this); } + UNLOCK(connection); + return OK; } }; @@ -606,14 +613,15 @@ struct dbscalar_kb : csnd::Plugin<1, 4> { int kperf() { STRINGDAT &sql = inargs.str_data(1); + LOCK(connection); try { - LOCK(connection); outargs[0] = connection->Scalar(sql.data, inargs[2], inargs[3]); - UNLOCK(connection); - return OK; } catch (const std::exception &e) { + UNLOCK(connection); return csound->perf_error(e.what(), this); } + UNLOCK(connection); + return OK; } }; @@ -636,16 +644,17 @@ struct dbscalarstr_kb : csnd::Plugin<1, 4> { STRINGDAT &sql = inargs.str_data(1); STRINGDAT &result = outargs.str_data(0); + LOCK(connection); try { - LOCK(connection); - std::string resultString = connection->ScalarString(sql.data, inargs[2], inargs[3]); - UNLOCK(connection); - result.size = resultString.length() + 1; - result.data = csound->strdup(resultString.c_str()); - return OK; + char* resultString = connection->ScalarString(sql.data, csound, inargs[2], inargs[3]); + result.size = strlen(resultString) + 1; + result.data = resultString; } catch (const std::exception &e) { + UNLOCK(connection); return csound->perf_error(e.what(), this); } + UNLOCK(connection); + return OK; } }; @@ -670,15 +679,15 @@ struct dbarray_kb : csnd::Plugin<1, 2> { STRINGDAT &sql = inargs.str_data(1); ARRAYDAT* array = (ARRAYDAT*) outargs(0); - + LOCK(connection); try { - LOCK(connection); connection->ArrayQuery(sql.data, csound, array); - UNLOCK(connection); - return OK; } catch (const std::exception &e) { + UNLOCK(connection); return csound->perf_error(e.what(), this); } + UNLOCK(connection); + return OK; } }; @@ -702,15 +711,15 @@ struct dbarraystr_kb : csnd::Plugin<1, 2> { STRINGDAT &sql = inargs.str_data(1); ARRAYDAT* array = (ARRAYDAT*) outargs(0); - + LOCK(connection); try { - LOCK(connection); connection->ArrayQueryString(sql.data, csound, array); - UNLOCK(connection); - return OK; } catch (const std::exception &e) { + UNLOCK(connection); return csound->perf_error(e.what(), this); } + UNLOCK(connection); + return OK; } }; @@ -746,4 +755,4 @@ void csnd::on_load(csnd::Csound *csound) { csnd::plugin<dbarray_kb>(csound, "dbarray_kb", csnd::thread::ik); csnd::plugin<dbarraystr_kb>(csound, "dbarray_kb.S", csnd::thread::ik); -}
\ No newline at end of file +} diff --git a/src/postgresql.cpp b/src/postgresql.cpp index 681c133..7e194c6 100644 --- a/src/postgresql.cpp +++ b/src/postgresql.cpp @@ -20,15 +20,14 @@ */ #include <plugin.h> +#include "tools.h" #include <iostream> -#include <pqxx/pqxx> +#include "libpq-fe.h" #include "connection.h" #include "postgresql.h" - void PostgresConnection::Init(csnd::Csound* csound, LoginData* login) { - //conn = (pqxx::connection*) csound->malloc(sizeof(pqxx::connection)); char connectionString[256]; snprintf(connectionString, 256, @@ -36,90 +35,85 @@ void PostgresConnection::Init(csnd::Csound* csound, LoginData* login) { login->dbName, login->dbUser, login->dbPass, login->dbHost ); - conn = new pqxx::connection(connectionString); + conn = PQconnectdb(connectionString); - if (!conn->is_open()) { + if (PQstatus(conn) == CONNECTION_BAD) { throw std::runtime_error("Connection not open"); } } void PostgresConnection::Close(csnd::Csound* csound) { - if (conn->is_open()) { - conn->disconnect(); - } - delete conn; + PQfinish(conn); } void PostgresConnection::Exec(char* sql) { - pqxx::nontransaction nt(*conn); - nt.exec(sql); + PGresult* result = PQexec(conn, sql); + PQclear(result); } -pqxx::result PostgresConnection::Query(char* sql) { - pqxx::nontransaction nt(*conn); - pqxx::result result(nt.exec(sql)); - return result; +PGresult* PostgresConnection::Query(char* sql) { + return PQexec(conn, sql); } -MYFLT PostgresConnection::Scalar(char* sql, int row=0, int col=0) { - pqxx::result result = Query(sql); +MYFLT PostgresConnection::Scalar(char* sql, int row, int col) { + PGresult* result = Query(sql); - // checks as libpqxx not throwing if this happens - if (row > result.size() - 1) { + int rows = PQntuples(result); + int cols = PQnfields(result); + + if (row > rows - 1) { + PQclear(result); throw std::runtime_error("row number out of range"); } - if (col > result[row].size() -1) { + if (col > cols - 1) { + PQclear(result); throw std::runtime_error("column number out of range"); } - return result[row][col].as<MYFLT>(); + MYFLT value = (MYFLT) atof(PQgetvalue(result, row, col)); + PQclear(result); + return value; } -char* PostgresConnection::ScalarString(char* sql, int row=0, int col=0) { - pqxx::result result = Query(sql); +char* PostgresConnection::ScalarString(char* sql, csnd::Csound* csound, int row, int col) { + PGresult* result = Query(sql); - // checks as libpqxx not throwing if this happens - if (row > result.size() - 1) { + int rows = PQntuples(result); + int cols = PQnfields(result); + + if (row > rows - 1) { + PQclear(result); throw std::runtime_error("row number out of range"); } - if (col > result[row].size() -1) { + if (col > cols -1) { + PQclear(result); throw std::runtime_error("column number out of range"); } - return result[row][col].c_str(); + char* value = csound->strdup(PQgetvalue(result, row, col)); + PQclear(result); + return value; } -void PostgresConnection::ToArray(pqxx::result result, csnd::Csound* csound, ARRAYDAT* array, bool asString) { - int totalResults = result.size() * result[0].size(); - array->sizes = csound->calloc(sizeof(int32_t) * 2); - array->sizes[0] = result.size(); - array->sizes[1] = result[0].size(); - array->dimensions = 2; - CS_VARIABLE *var = array->arrayType->createVariable(csound, NULL); - array->arrayMemberSize = var->memBlockSize; - array->data = csound->calloc(var->memBlockSize * totalResults); - STRINGDAT* strings; - if (asString) { - strings = (STRINGDAT*) array->data; - } +void PostgresConnection::ToArray(PGresult* result, csnd::Csound* csound, ARRAYDAT* array, bool asString) { + int rows = PQntuples(result); + int cols = PQnfields(result); + STRINGDAT* strings = arrayInit(csound, array, rows, cols); int index = 0; - for (int rowNum = 0; rowNum < result.size(); ++rowNum) { - const pqxx::row row = result[rowNum]; - for (int colNum = 0; colNum < row.size(); ++colNum) { - const pqxx::field field = row[colNum]; + for (int rowIndex = 0; rowIndex < rows; ++rowIndex) { + for (int colIndex = 0; colIndex < cols; ++colIndex) { if (asString) { - char* item = field.c_str(); - strings[index].size = strlen(item) + 1; - strings[index].data = csound->strdup(item); + insertArrayStringItem(csound, strings, index, (char*) PQgetvalue(result, rowIndex, colIndex)); } else { - array->data[index] = field.as<MYFLT>(); + array->data[index] = (MYFLT) atof(PQgetvalue(result, rowIndex, colIndex)); } index++; } } + PQclear(result); } void PostgresConnection::ArrayQueryString(char* sql, csnd::Csound* csound, ARRAYDAT* array) { diff --git a/src/sqlite3.cpp b/src/sqlite3.cpp index 824e165..cbd4af1 100644 --- a/src/sqlite3.cpp +++ b/src/sqlite3.cpp @@ -20,6 +20,7 @@ */ #include <plugin.h> +#include "tools.h" #include <iostream> #include <sqlite3.h> #include "connection.h" @@ -28,7 +29,6 @@ void SqliteConnection::Init(csnd::Csound* csound, LoginData* login) { int result = sqlite3_open(login->dbName, &conn); - std::cout << "Y"; if (result) { throw std::runtime_error("connection not established"); } @@ -53,18 +53,20 @@ sqlite3_stmt* SqliteConnection::Query(char* sql) { return stmt; } -MYFLT SqliteConnection::Scalar(char* sql, int row=0, int col=0) { +MYFLT SqliteConnection::Scalar(char* sql, int row, int col) { sqlite3_stmt *stmt = Query(sql); int colCount = sqlite3_column_count(stmt); int rc = sqlite3_step(stmt); + + if (col > colCount -1) { + rc = sqlite3_finalize(stmt); + throw std::runtime_error("column number out of range"); + } + + rc = sqlite3_step(stmt); int rowIndex = 0; while (rc != SQLITE_DONE && rc != SQLITE_OK) { if (rowIndex == row) { - - if (col > colCount -1) { - rc = sqlite3_finalize(stmt); - throw std::runtime_error("column number out of range"); - } MYFLT result = (MYFLT) sqlite3_column_double(stmt, col); rc = sqlite3_finalize(stmt); return result; @@ -76,7 +78,7 @@ MYFLT SqliteConnection::Scalar(char* sql, int row=0, int col=0) { throw std::runtime_error("no result"); } -char* SqliteConnection::ScalarString(char* sql, int row=0, int col=0) { +char* SqliteConnection::ScalarString(char* sql, csnd::Csound* csound, int row, int col) { sqlite3_stmt *stmt = Query(sql); int colCount = sqlite3_column_count(stmt); int rc = sqlite3_step(stmt); @@ -88,7 +90,7 @@ char* SqliteConnection::ScalarString(char* sql, int row=0, int col=0) { rc = sqlite3_finalize(stmt); throw std::runtime_error("column number out of range"); } - char* result = sqlite3_column_text(stmt, col); + char* result = csound->strdup((char*) sqlite3_column_text(stmt, col)); rc = sqlite3_finalize(stmt); return result; } @@ -111,21 +113,11 @@ int SqliteConnection::RowCount(sqlite3_stmt* stmt) { return rowCount; } + void SqliteConnection::ToArray(sqlite3_stmt* stmt, csnd::Csound* csound, ARRAYDAT* array, bool asString) { - int colNum = sqlite3_column_count(stmt); - int rowNum = RowCount(stmt); - int totalResults = colNum * rowNum; - array->sizes = csound->calloc(sizeof(int32_t) * 2); - array->sizes[0] = rowNum; - array->sizes[1] = colNum; - array->dimensions = 2; - CS_VARIABLE *var = array->arrayType->createVariable(csound, NULL); - array->arrayMemberSize = var->memBlockSize; - array->data = csound->calloc(var->memBlockSize * totalResults); - STRINGDAT* strings; - if (asString) { - strings = (STRINGDAT*) array->data; - } + int cols = sqlite3_column_count(stmt); + int rows = RowCount(stmt); + STRINGDAT* strings = arrayInit(csound, array, rows, cols); int colIndex; int rowIndex; @@ -133,11 +125,9 @@ void SqliteConnection::ToArray(sqlite3_stmt* stmt, csnd::Csound* csound, ARRAYDA int rc = sqlite3_step(stmt); while (rc != SQLITE_DONE && rc != SQLITE_OK) { colIndex = 0; - while (colIndex < colNum) { + while (colIndex < cols) { if (asString) { - char* item = sqlite3_column_text(stmt, colIndex); - strings[index].size = strlen(item) + 1; - strings[index].data = csound->strdup(item); + insertArrayStringItem(csound, strings, index, (char*) sqlite3_column_text(stmt, colIndex)); } else { array->data[index] = (MYFLT) sqlite3_column_double(stmt, colIndex); } diff --git a/src/tools.cpp b/src/tools.cpp new file mode 100644 index 0000000..ec8863b --- /dev/null +++ b/src/tools.cpp @@ -0,0 +1,54 @@ +/* + tools.cpp + Copyright (C) 2022 Richard Knight + + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + */ + +#include <plugin.h> + +STRINGDAT* arrayInit(csnd::Csound* csound, ARRAYDAT* array, int rows, int cols) { + int totalResults = rows * cols; + size_t totalAllocated; + + if (array->data == NULL) { + array->sizes = (int32_t*) csound->calloc(sizeof(int32_t) * 2); + array->sizes[0] = rows; + array->sizes[1] = cols; + array->dimensions = 2; + CS_VARIABLE *var = array->arrayType->createVariable(csound->get_csound(), NULL); + array->arrayMemberSize = var->memBlockSize; + totalAllocated = array->arrayMemberSize * totalResults; + array->data = (MYFLT*) csound->calloc(totalAllocated); + } else if ((totalAllocated = array->arrayMemberSize * totalResults) > array->allocated) { + array->data = (MYFLT*) csound->realloc(array->data, totalAllocated); + memset((char*)(array->data)+array->allocated, '\0', totalAllocated - array->allocated); + array->allocated = totalAllocated; + } + + // convenience return to be used if it is a string array + return (STRINGDAT*) array->data; +} + + +void insertArrayStringItem(csnd::Csound* csound, STRINGDAT* strings, int index, char* item) { + strings[index].size = strlen(item) + 1; + if (strings[index].data != NULL) { + csound->free(strings[index].data); + } + strings[index].data = csound->strdup(item); +}
\ No newline at end of file |