aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--CMakeLists.txt322
-rw-r--r--Plugin.cmake45
-rw-r--r--README.md20
-rw-r--r--cmake/CompilerOptimizations.cmake53
-rw-r--r--cmake/Modules/FindCsound.cmake53
-rw-r--r--cmake/Modules/FindPQXX.cmake33
-rw-r--r--cmake/Modules/FindPostgreSQL.cmake173
-rw-r--r--include/connection.h6
-rw-r--r--include/logindata.h4
-rw-r--r--include/mysql.h6
-rw-r--r--include/postgresql.h14
-rw-r--r--include/sqlite.h6
-rw-r--r--include/tools.h30
-rw-r--r--src/connection.cpp10
-rw-r--r--src/mysql.cpp32
-rw-r--r--src/opcodes.cpp99
-rw-r--r--src/postgresql.cpp90
-rw-r--r--src/sqlite3.cpp44
-rw-r--r--src/tools.cpp54
20 files changed, 709 insertions, 386 deletions
diff --git a/.gitignore b/.gitignore
index e7bf528..567609b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1 @@
build/
-examples-test/ \ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 43c251d..8c47998 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,217 +1,201 @@
-project("csound_sqldb")
+# from https://github.com/csound/plugins : common CMake operations
+cmake_minimum_required(VERSION 2.8.12)
+project(Csound-plugins)
-cmake_minimum_required(VERSION 3.8)
-
-set(APIVERSION "6.0")
+if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
+ set(CMAKE_COMPILER_IS_CLANG 1)
+endif()
-# Release or Debug
-set(CMAKE_BUILD_TYPE "Release")
+# C++11 needed
+if(NOT MSVC)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+endif()
-# force make to print the command lines
-set(CMAKE_VERBOSE_MAKEFILE on)
+set(APIVERSION "6.0")
-# path to Csound cmake module
+set(CMAKE_MACOSX_RPATH 1)
+set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
-# set compilation flags
-set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-std=c++11 -fpermissive -fPIC -w -DUSE_DOUBLE -DB64BIT")
-
-# options
-option(USE_LIB64 "Set to on to set installation dir for libs to lib64" OFF)
-option(USE_DOUBLE "Use doubles for audio calculations" ON)
-option(CPP11 "c++11" ON)
-
-set(BUILDING_CSOUND_PLUGINS ON)
-
-# ----------------------------------------------
-
-include(FindCsound)
-include(FindPQXX)
-include(FindSqlite3)
-include(FindMySQL)
-
+include(TestBigEndian)
+include(CheckFunctionExists)
include(CheckCCompilerFlag)
include(CheckCXXCompilerFlag)
-# -----------------------------------------------
-
-function(addflag flag flagname)
- check_c_compiler_flag(${flag} ${flagname})
- if (${flagname})
- # message(STATUS "Setting C flag ${flag}")
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${flag}" PARENT_SCOPE)
- endif()
- check_cxx_compiler_flag(${flag} CXX_${flagname})
- if (CXX_${flagname})
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}" PARENT_SCOPE)
- endif()
-endfunction(addflag)
-
-
-MACRO(SUBDIRLIST result curdir)
- FILE(GLOB children RELATIVE ${curdir} ${curdir}/*)
- SET(dirlist "")
- FOREACH(child ${children})
- message(STATUS "looking at ${child}")
- IF(IS_DIRECTORY ${curdir}/${child})
- LIST(APPEND dirlist ${child})
- ENDIF()
- ENDFOREACH()
- SET(${result} ${dirlist})
-ENDMACRO()
-
-
-MACRO(ADD_ALL_SUBDIRECTORIES directory)
- subdirlist(SUBDIRS ${directory})
- message(STATUS "Found subdirs: ${SUBDIRS}")
- foreach(SUBDIR ${SUBDIRS})
- set(thissubdir "${directory}/${SUBDIR}")
- if(EXISTS "${directory}/${SUBDIR}/CMakeLists.txt")
- message(STATUS "Adding subdir: ${thissubdir}")
- add_subdirectory(${directory}/${SUBDIR})
- else()
- message(WARNING "Skipping ${directory}/${SUBDIR} because no CMakeLists.txt file was found")
- endif()
- endforeach()
-ENDMACRO()
+### COMPILER OPTIMIZATION FLAGS
+option(USE_COMPILER_OPTIMIZATIONS "Use the default Csound compiler optimization flags" ON)
+if(USE_COMPILER_OPTIMIZATIONS)
+ include(${CMAKE_SOURCE_DIR}/cmake/CompilerOptimizations.cmake)
+endif()
+if(APPLE)
+ set(OSX_VERSION " ")
+endif()
+## USER OPTIONS ##
+# Optional targets, they should all default to ON (check_deps will disable them if not possible to build)
+option(USE_DOUBLE "Set to use double-precision floating point for audio samples." ON)
-# set optimization flags
-if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANG)
- add_definitions(-fvisibility=hidden)
- if(NATIVE)
- add_definitions(-march=native)
- endif()
-
- include(CheckCCompilerFlag)
- include(CheckCXXCompilerFlag)
- addflag(-msse HAS_SSE)
- addflag(-msse2 HAS_SSE2)
- addflag(-mfgpath=sse HAS_FPMATH_SSE)
-
+# in Release configuration, set NDEBUG
+if(${CMAKE_BUILD_TYPE} MATCHES "Release")
+message("-----> Release mode")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNDEBUG")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNDEBUG")
+elseif(${CMAKE_BUILD_TYPE} MATCHES "Debug")
+message("-----> Debug mode")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBETA")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DBETA")
endif()
-if(MINGW)
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mstackrealign")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mstackrealign")
+# set -Werror if in Debug configuration
+if(NOT MSVC AND NOT WASM)
+ set(CMAKE_CXX_FLAGS_RELEASE "-O3 ")
+ set(CMAKE_C_FLAGS_RELEASE "-O3 ")
+ if(${CMAKE_BUILD_TYPE} MATCHES "Debug")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -Wno-missing-field-initializers")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -Wno-missing-field-initializers")
+ endif()
endif()
-addflag(-ftree-vectorize HAS_TREE_VECTORIZE)
-addflag(-ffast-math HAS_FAST_MATH)
-addflag(-fomit-frame-pointer HAS_OMIT_FRAME_POINTER)
+if(CMAKE_SYSTEM_NAME MATCHES "Linux")
+ set(LINUX YES)
+else()
+ set(LINUX NO)
+endif()
+
+set(BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR})
-# -------------------------------------------------------------------
+check_c_compiler_flag(-fvisibility=hidden HAS_VISIBILITY_HIDDEN)
+check_cxx_compiler_flag(-fvisibility=hidden HAS_CXX_VISIBILITY_HIDDEN)
+if (HAS_VISIBILITY_HIDDEN)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")
+endif()
+if (HAS_CXX_VISIBILITY_HIDDEN)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
+endif()
-set(CS_FRAMEWORK_DEST "~/Library/Frameworks")
+check_c_compiler_flag(-std=gnu99 HAS_GNU99)
+if (HAS_GNU99)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99")
+endif()
+if (HAS_CXX_VISIBILITY_HIDDEN)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
+endif()
+find_package(Csound)
+option(USE_LIB64 "Set to on to set installation directory for libraries to lib64" OFF)
if(USE_LIB64)
- set(LIBRARY_INSTALL_DIR "lib64")
- add_definitions("-DLIB64")
+ set(LIBRARY_INSTALL_DIR "lib64")
+ add_definitions("-DLIB64")
else()
- set(LIBRARY_INSTALL_DIR "lib")
+ set(LIBRARY_INSTALL_DIR "lib")
endif()
-
message(STATUS "LIBRARY INSTALL DIR: ${LIBRARY_INSTALL_DIR}")
-# -------------------------------------------------------------------
-
-
if(USE_DOUBLE)
- message(STATUS ">>> using doubles")
-
- if(APPLE)
- set(CSOUNDLIB "CsoundLib64")
- set(PLUGIN_INSTALL_DIR "${CS_FRAMEWORK_DEST}/${CSOUNDLIB}.framework/Versions/${APIVERSION}/Resources/Opcodes64")
- else()
- set(CSOUNDLIB "csound64")
+ message(STATUS "Building with 64-bit floats")
set(PLUGIN_INSTALL_DIR "${LIBRARY_INSTALL_DIR}/csound/plugins64-${APIVERSION}")
- endif()
+ if(APPLE)
+ set(PLUGIN_INSTALL_DIR "${CS_FRAMEWORK_DEST}/${CSOUNDLIB}.framework/Versions/${APIVERSION}/Resources/Opcodes64")
+ endif()
else()
- message(STATUS ">>> not using doubles")
- if(APPLE)
- set(CSOUNDLIB "CsoundLib")
- set(PLUGIN_INSTALL_DIR "${CS_FRAMEWORK_DEST}/${CSOUNDLIB}.framework/Versions/${APIVERSION}/Resources/Opcodes")
- else()
- set(CSOUNDLIB "csound")
+ message(STATUS "Building with 32-bit floats")
set(PLUGIN_INSTALL_DIR "${LIBRARY_INSTALL_DIR}/csound/plugins-${APIVERSION}")
- endif()
+ if(APPLE)
+ set(PLUGIN_INSTALL_DIR "${CS_FRAMEWORK_DEST}/${CSOUNDLIB}.framework/Versions/${APIVERSION}/Resources/Opcodes")
+ endif()
endif()
-# -------------------------------------------------------------------
-
-# Csound opcode build
-find_package(Csound)
-
-
-set(BUILD_PLUGINS_DIR ${CMAKE_CURRENT_BINARY_DIR})
-
-if(NOT CSOUND_FOUND)
- message(FATAL_ERROR "Csound installation not found")
-endif()
-
-if(NOT PQXX_FOUND AND NOT SQLITE3_FOUND AND NOT MYSQLCONNECTORCPP_FOUND)
- message(FATAL_ERROR "No database libraries could be found")
-endif()
+# Checks if dependencies for an enabled target are fulfilled.
+# If FAIL_MISSING is true and the dependencies are not fulfilled,
+# it will abort the cmake run.
+# If FAIL_MISSING is false, it will set the option to OFF.
+# If the target is not enabled, it will do nothing.
+# example: check_deps(BUILD_NEW_PARSER FLEX_EXECUTABLE BISON_EXECUTABLE)
+function(check_deps option)
+ if(${option})
+ set(i 1)
+ while( ${i} LESS ${ARGC} )
+ set(dep ${ARGV${i}})
+ if(NOT ${dep})
+ if(FAIL_MISSING)
+ message(FATAL_ERROR
+ "${option} is enabled, but ${dep}=\"${${dep}}\"")
+ else()
+ message(STATUS "${dep}=\"${${dep}}\", so disabling ${option}")
+ set(${option} OFF PARENT_SCOPE)
+ # Set it in the local scope too
+ set(${option} OFF)
+ endif()
+ endif()
+ math(EXPR i "${i}+1")
+ endwhile()
+ endif()
+ if(${option})
+ message(STATUS "${option} is enabled.")
+ else()
+ message(STATUS "${option} is disabled.")
+ endif()
+endfunction(check_deps)
+# Utility function to make plugins. All plugin targets should use this as it
+# sets up output directory set in top-level CmakeLists.txt
+# and adds the appropriate install target
#
-#if(APPLE)
-# add_library(sqldb SHARED ${srcs})
-#else()
-# add_library(sqldb MODULE ${srcs})
-#endif()
-
-set(CPPFILES src/opcodes.cpp src/connection.cpp)
-
-
-if (PQXX_FOUND)
- message(STATUS "Using PostgreSQL")
- list(APPEND CPPFILES "src/postgresql.cpp")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBUILD_POSTGRES")
-endif()
+# libname - name of library to produce
+# srcs - list of src files (must be quoted if a list)
+# extralibs (OPTIONAL) - extra libraries to link the plugin to
+#
+# NB - this was moved here as it needs some VARS defined above
+# for setting up the framework
+function(make_plugin libname srcs)
+ if(APPLE)
+ add_library(${libname} SHARED ${srcs})
+ else()
+ add_library(${libname} MODULE ${srcs})
+ endif()
-if (SQLITE3_FOUND)
- message(STATUS "Using SQLite3")
- list(APPEND CPPFILES "src/sqlite3.cpp")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBUILD_SQLITE")
-endif()
+ set(i 2)
+ while( ${i} LESS ${ARGC} )
+ target_link_libraries(${libname} ${ARGV${i}})
+ math(EXPR i "${i}+1")
+ endwhile()
-if (MYSQLCONNECTORCPP_FOUND)
- message(STATUS "Using MySQL")
- list(APPEND CPPFILES "src/mysql.cpp")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBUILD_MYSQL")
-endif()
+ set_target_properties(${libname} PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+ install(TARGETS ${libname}
+ LIBRARY DESTINATION "${PLUGIN_INSTALL_DIR}"
+ ARCHIVE DESTINATION "${PLUGIN_INSTALL_DIR}" )
+endfunction(make_plugin)
+# Linux does not have a separate libintl, it is part of libc
+set(LIBINTL_AVAIL (LIBINTL_LIBRARY OR LINUX))
-#include_directories(/usr/include)
-include_directories(${CSOUND_INCLUDE_DIRS})
-include_directories(include)
+if(LINUX)
+ message(STATUS "Building on Linux.")
+ add_definitions(-DLINUX -DPIPES -D_GNU_SOURCE -DHAVE_SOCKETS)
+ list(APPEND libcsound_LIBS ${MATH_LIBRARY} dl)
-if (PQXX_FOUND)
- link_libraries(${PQXX_LIBRARIES})
- include_directories(${PQXX_INCLUDE_DIRECTORIES})
endif()
-if (SQLITE3_FOUND)
- link_libraries(${SQLITE3_LIBRARIES})
- include_directories(${SQLITE3_INCLUDE_DIRS})
+if(APPLE AND NOT IOS)
+ message(STATUS "Building on OSX")
+ add_definitions(-DMACOSX -DPIPES -DNO_FLTK_THREADS -DHAVE_SOCKETS)
+ find_library(ACCELERATE_LIBRARY Accelerate)
+ find_path(VECLIB_PATH "Accelerate/Accelerate.h")
+ include_directories(${VECLIB_PATH})
+ list(APPEND libcsound_LIBS ${MATH_LIBRARY} dl ${ACCELERATE_LIBRARY})
endif()
-if (MYSQLCONNECTORCPP_FOUND)
- link_libraries(${MYSQLCONNECTORCPP_LIBRARIES})
- include_directories(${MYSQLCONNECTORCPP_INCLUDE_DIRS})
+if(WIN32)
+ add_definitions(-DWIN32)
endif()
-add_library(sqldb SHARED ${CPPFILES})
-
-set_target_properties(sqldb PROPERTIES
- RUNTIME_OUTPUT_DIRECTORY ${BUILD_PLUGINS_DIR}
- LIBRARY_OUTPUT_DIRECTORY ${BUILD_PLUGINS_DIR})
-
-install(TARGETS sqldb LIBRARY DESTINATION "${PLUGIN_INSTALL_DIR}" )
-
+include(Plugin.cmake)
diff --git a/Plugin.cmake b/Plugin.cmake
new file mode 100644
index 0000000..febebda
--- /dev/null
+++ b/Plugin.cmake
@@ -0,0 +1,45 @@
+set(PLUGIN_NAME sqldb)
+
+# Dependencies
+find_package(PostgreSQL)
+find_package(Sqlite3)
+find_package(MySQL)
+
+# Check databases available
+if(NOT PostgreSQL_FOUND AND NOT SQLITE3_FOUND AND NOT MYSQLCONNECTORCPP_FOUND)
+ message(FATAL_ERROR "No database libraries could be found")
+endif()
+
+# Source files
+set(CPPFILES src/opcodes.cpp src/connection.cpp src/tools.cpp)
+set(INCLUDES ${CSOUND_INCLUDE_DIRS} "include")
+set(LIBS "")
+
+if(PostgreSQL_FOUND)
+ message(STATUS "Using PostgreSQL")
+ list(APPEND CPPFILES "src/postgresql.cpp")
+ list(APPEND INCLUDES ${PostgreSQL_INCLUDE_DIRS})
+ list(APPEND LIBS ${PostgreSQL_LIBRARIES})
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBUILD_POSTGRES")
+endif()
+
+if(SQLITE3_FOUND)
+ message(STATUS "Using SQLite3")
+ list(APPEND CPPFILES "src/sqlite3.cpp")
+ list(APPEND INCLUDES ${SQLITE3_INCLUDE_DIRS})
+ list(APPEND LIBS ${SQLITE3_LIBRARIES})
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBUILD_SQLITE")
+endif()
+
+if(MYSQLCONNECTORCPP_FOUND)
+ message(STATUS "Using MySQL")
+ list(APPEND CPPFILES "src/mysql.cpp")
+ list(APPEND INCLUDES ${MYSQLCONNECTORCPP_INCLUDE_DIRS})
+ list(APPEND LIBS ${MYSQLCONNECTORCPP_LIBRARIES})
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBUILD_MYSQL")
+endif()
+
+
+make_plugin(${PLUGIN_NAME} "${CPPFILES}" ${LIBS})
+target_include_directories(${PLUGIN_NAME} PRIVATE ${INCLUDES})
+
diff --git a/README.md b/README.md
index a73a9f8..bdbfff6 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,12 @@
## Introduction
csound-sqldb provides database access opcodes which allow for the querying of data in SQL databases at i- and k-rate.
-MySQL, PostgreSQL and SQLite3 are supported and are used with the same opcodes after the initial connection. The opcodes have currently been tested on Linux only.
+MySQL, PostgreSQL and SQLite3 are supported and are used with the same opcodes after the initial connection. The opcodes have been tested on Linux and Windows.
The opcodes rely on changes made after the official 6.13.0 release of Csound so while awaiting the next release the Csound source will need to be obtained from the develop branch of https://github.com/csound/csound/ otherwise they will not build.
## Opcode overview
The opcodes are detailed in full in OpcodeDocumentation.md
+
Aside from the connection opcode, there are three groups available for each to allow for design options particularly when considering database latency/performance:
- i-rate : to be used when db latency is particularly low, in global orchestra space or not running in realtime etc.
@@ -15,30 +16,30 @@ Aside from the connection opcode, there are three groups available for each to a
## Requirements
- Csound libraries
- - Cmake
+ - Cmake >= 2.8.12
- At least one database development library from the three below. Opcodes will support whichever of these databases can be found, which will be indicated when running the initial cmake command.
### MySQL
Connector/C++ (https://dev.mysql.com/downloads/connector/cpp/)
- # apt get install libmysqlcppconn-dev
+ # apt-get install libmysqlcppconn-dev
### PostgreSQL
-libpqxx (http://pqxx.org/development/libpqxx/wiki/DownloadPage)
+libpq (https://www.postgresql.org/download/)
- # apt get install libpqxx-dev
+ # apt-get install libpq-dev
### SQLite
libsqlite (https://www.sqlite.org/download.html)
- # apt get install libsqlite3-dev
+ # apt-get install libsqlite3-dev
## Building
Create a build directory at the top of the source tree, execute *cmake ..*, *make* and optionally *make install* as root. If the latter is not used/possible then the resulting libsqldb.so can be used with the *--opcode-lib* flag in Csound.
eg:
- git clone https://github.com/1bpm/csound-sqldb.git
+ git clone https://git.1bpm.net/csound-sqldb
cd csound-sqldb
mkdir build && cd build
cmake ..
@@ -47,6 +48,7 @@ eg:
## Examples
A number of examples are included in the examples directory. Generally the syntax of each opcode is agnostic to the database type used, so the different techniques in each can be used for any database type.
+## Reference
+OpcodeDocumentation.md contains an explanation of all provided opcodes.
-
-By Richard Knight 2019 \ No newline at end of file
+By Richard Knight 2019
diff --git a/cmake/CompilerOptimizations.cmake b/cmake/CompilerOptimizations.cmake
new file mode 100644
index 0000000..543daf8
--- /dev/null
+++ b/cmake/CompilerOptimizations.cmake
@@ -0,0 +1,53 @@
+
+check_c_compiler_flag(-ftree-vectorize HAS_TREE_VECTORIZE)
+check_cxx_compiler_flag(-ftree-vectorize HAS_CXX_TREE_VECTORIZE)
+if (HAS_TREE_VECTORISE)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ftree-vectorize")
+endif()
+if (HAS_CXX_TREE_VECTORISE)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftree-vectorize")
+endif()
+
+
+check_c_compiler_flag(-ffast-math HAS_FAST_MATH)
+check_cxx_compiler_flag(-ffast-math HAS_CXX_FAST_MATH)
+if (HAS_FAST_MATH AND NOT MINGW)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffast-math")
+endif()
+if (HAS_CXX_FAST_MATH AND NOT MINGW)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffast-math")
+endif()
+
+
+
+if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+check_c_compiler_flag(-mfpmath=sse HAS_FPMATH_SSE)
+check_cxx_compiler_flag(-mfpmath=sse HAS_CXX_FPMATH_SSE)
+ if (HAS_FPMATH_SSE)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpmath=sse")
+endif()
+if (HAS_CXX_FPMATH_SSE)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpmath=sse")
+endif()
+
+endif()
+
+
+check_c_compiler_flag(-msse2 HAS_SSE2)
+check_cxx_compiler_flag(-msse2 HAS_CXX_SSE2)
+ if (HAS_SSE2 AND NOT IOS AND NOT WASM)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse2")
+endif()
+if (HAS_CXX_SSE2 AND NOT IOS AND NOT WASM)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse2")
+endif()
+
+
+check_c_compiler_flag(-fomit-frame-pointer HAS_OMIT_FRAME_POINTER)
+check_cxx_compiler_flag(-fomit-frame-pointer HAS_CXX_OMIT_FRAME_POINTER)
+if (HAS_OMIT_FRAME_POINTER)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fomit-frame-pointer")
+endif()
+if (HAS_CXX_OMIT_FRAME_POINTER)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fomit-frame-pointer")
+endif()
diff --git a/cmake/Modules/FindCsound.cmake b/cmake/Modules/FindCsound.cmake
index e55b269..24c90d9 100644
--- a/cmake/Modules/FindCsound.cmake
+++ b/cmake/Modules/FindCsound.cmake
@@ -4,20 +4,53 @@
# CSOUND_INCLUDE_DIRS - The Csound include directories.
# CSOUND_LIBRARIES - The libraries needed to use the Csound library.
-if(APPLE)
-find_path(CSOUND_INCLUDE_DIR csound.h HINTS /Library/Frameworks/CsoundLib64.framework/Headers
-"$ENV{HOME}/Library/Frameworks/CsoundLib64.framework/Headers")
-else()
-find_path(CSOUND_INCLUDE_DIR csound.h PATH_SUFFIXES csound)
-endif()
+# RKnight 2021-07-21 : quick copy paste hack to deal with 32 bit if not using double
+
+if(USE_DOUBLE)
+ # 64 bit
+ if(APPLE)
+ find_path(CSOUND_INCLUDE_DIR csound.h HINTS /Library/Frameworks/CsoundLib64.framework/Headers
+ "$ENV{HOME}/Library/Frameworks/CsoundLib64.framework/Headers")
+ elseif(WIN32)
+ find_path(CSOUND_INCLUDE_DIR csound.h PATH_SUFFIXES csound
+ HINTS "c:\\Program Files\\Csound6_x64\\include")
+ else()
+ find_path(CSOUND_INCLUDE_DIR csound.h PATH_SUFFIXES csound)
+ endif()
+
+ if(APPLE)
+ find_library(CSOUND_LIBRARY NAMES CsoundLib64 HINTS /Library/Frameworks/CsoundLib64.framework/
+ "$ENV{HOME}/Library/Frameworks/CsoundLib64.framework")
+ elseif(WIN32)
+ find_library(CSOUND_LIBRARY NAMES csound64 HINTS "c:\\Program Files\\Csound6_x64\\lib")
+ else()
+ find_library(CSOUND_LIBRARY NAMES csound64 csound)
+ endif()
-if(APPLE)
-find_library(CSOUND_LIBRARY NAMES CsoundLib64 HINTS /Library/Frameworks/CsoundLib64.framework/
-"$ENV{HOME}/Library/Frameworks/CsoundLib64.framework")
else()
-find_library(CSOUND_LIBRARY NAMES csound64 csound)
+ # 32 bit
+ if(APPLE)
+ find_path(CSOUND_INCLUDE_DIR csound.h HINTS /Library/Frameworks/CsoundLib.framework/Headers
+ "$ENV{HOME}/Library/Frameworks/CsoundLib.framework/Headers")
+ elseif(WIN32)
+ find_path(CSOUND_INCLUDE_DIR csound.h PATH_SUFFIXES csound
+ HINTS "c:\\Program Files (x86)\\Csound6\\include")
+ else()
+ find_path(CSOUND_INCLUDE_DIR csound.h PATH_SUFFIXES csound)
+ endif()
+
+ if(APPLE)
+ find_library(CSOUND_LIBRARY NAMES CsoundLib HINTS /Library/Frameworks/CsoundLib.framework/
+ "$ENV{HOME}/Library/Frameworks/CsoundLib.framework")
+ elseif(WIN32)
+ find_library(CSOUND_LIBRARY NAMES csound HINTS "c:\\Program Files (x86)\\Csound6\\lib")
+ else()
+ find_library(CSOUND_LIBRARY NAMES csound csound)
+ endif()
+
endif()
+
include(FindPackageHandleStandardArgs)
# handle the QUIETLY and REQUIRED arguments and set CSOUND_FOUND to TRUE
# if all listed variables are TRUE
diff --git a/cmake/Modules/FindPQXX.cmake b/cmake/Modules/FindPQXX.cmake
deleted file mode 100644
index 724079b..0000000
--- a/cmake/Modules/FindPQXX.cmake
+++ /dev/null
@@ -1,33 +0,0 @@
-# - Find libpqxx
-# Find the libpqxx includes and client library
-# This module defines
-# PQXX_INCLUDE_DIRS
-# PQXX_LIBRARIES
-# PQXX_FOUND
-
-include (FindPackageHandleStandardArgs)
-
-find_path (PQXX_INCLUDE_DIRS
- NAME
- pqxx
- PATHS
- /usr/include
- /usr/local/include
- PATH_SUFFIXES
- pqxx
- DOC
- "Directory for pqxx headers"
-)
-
-find_library (PQXX_LIBRARIES
- NAMES
- pqxx
-)
-
-FIND_PACKAGE_HANDLE_STANDARD_ARGS("PQXX"
- "libpqxx couldn't be found"
- PQXX_LIBRARIES
- PQXX_INCLUDE_DIRS
-)
-
-mark_as_advanced (PQXX_INCLUDE_DIR PQXX_LIBRARY) \ No newline at end of file
diff --git a/cmake/Modules/FindPostgreSQL.cmake b/cmake/Modules/FindPostgreSQL.cmake
new file mode 100644
index 0000000..4b17df1
--- /dev/null
+++ b/cmake/Modules/FindPostgreSQL.cmake
@@ -0,0 +1,173 @@
+# - Find the PostgreSQL installation.
+# In Windows, we make the assumption that, if the PostgreSQL files are installed, the default directory
+# will be C:\Program Files\PostgreSQL.
+#
+# This module defines
+# PostgreSQL_LIBRARIES - the PostgreSQL libraries needed for linking
+# PostgreSQL_INCLUDE_DIRS - the directories of the PostgreSQL headers
+# PostgreSQL_VERSION_STRING - the version of PostgreSQL found (since CMake 2.8.8)
+
+#=============================================================================
+# Copyright 2004-2009 Kitware, Inc.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+# License text for the above reference.)
+
+# ----------------------------------------------------------------------------
+# History:
+# This module is derived from the module originally found in the VTK source tree.
+#
+# ----------------------------------------------------------------------------
+# Note:
+# PostgreSQL_ADDITIONAL_VERSIONS is a variable that can be used to set the
+# version mumber of the implementation of PostgreSQL.
+# In Windows the default installation of PostgreSQL uses that as part of the path.
+# E.g C:\Program Files\PostgreSQL\8.4.
+# Currently, the following version numbers are known to this module:
+# "9.1" "9.0" "8.4" "8.3" "8.2" "8.1" "8.0"
+#
+# To use this variable just do something like this:
+# set(PostgreSQL_ADDITIONAL_VERSIONS "9.2" "8.4.4")
+# before calling FIND_PACKAGE(PostgreSQL) in your CMakeLists.txt file.
+# This will mean that the versions you set here will be found first in the order
+# specified before the default ones are searched.
+#
+# ----------------------------------------------------------------------------
+# You may need to manually set:
+# PostgreSQL_INCLUDE_DIR - the path to where the PostgreSQL include files are.
+# PostgreSQL_LIBRARY_DIR - The path to where the PostgreSQL library files are.
+# If FindPostgreSQL.cmake cannot find the include files or the library files.
+#
+# ----------------------------------------------------------------------------
+# The following variables are set if PostgreSQL is found:
+# PostgreSQL_FOUND - Set to true when PostgreSQL is found.
+# PostgreSQL_INCLUDE_DIRS - Include directories for PostgreSQL
+# PostgreSQL_LIBRARY_DIRS - Link directories for PostgreSQL libraries
+# PostgreSQL_LIBRARIES - The PostgreSQL libraries.
+#
+# ----------------------------------------------------------------------------
+# If you have installed PostgreSQL in a non-standard location.
+# (Please note that in the following comments, it is assumed that <Your Path>
+# points to the root directory of the include directory of PostgreSQL.)
+# Then you have three options.
+# 1) After CMake runs, set PostgreSQL_INCLUDE_DIR to <Your Path>/include and
+# PostgreSQL_LIBRARY_DIR to wherever the library pq (or libpq in windows) is
+# 2) Use CMAKE_INCLUDE_PATH to set a path to <Your Path>/PostgreSQL<-version>. This will allow find_path()
+# to locate PostgreSQL_INCLUDE_DIR by utilizing the PATH_SUFFIXES option. e.g. In your CMakeLists.txt file
+# SET(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "<Your Path>/include")
+# 3) Set an environment variable called ${PostgreSQL_ROOT} that points to the root of where you have
+# installed PostgreSQL, e.g. <Your Path>.
+#
+# ----------------------------------------------------------------------------
+
+set(PostgreSQL_INCLUDE_PATH_DESCRIPTION "top-level directory containing the PostgreSQL include directories. E.g /usr/local/include/PostgreSQL/8.4 or C:/Program Files/PostgreSQL/8.4/include")
+set(PostgreSQL_INCLUDE_DIR_MESSAGE "Set the PostgreSQL_INCLUDE_DIR cmake cache entry to the ${PostgreSQL_INCLUDE_PATH_DESCRIPTION}")
+set(PostgreSQL_LIBRARY_PATH_DESCRIPTION "top-level directory containing the PostgreSQL libraries.")
+set(PostgreSQL_LIBRARY_DIR_MESSAGE "Set the PostgreSQL_LIBRARY_DIR cmake cache entry to the ${PostgreSQL_LIBRARY_PATH_DESCRIPTION}")
+set(PostgreSQL_ROOT_DIR_MESSAGE "Set the PostgreSQL_ROOT system variable to where PostgreSQL is found on the machine E.g C:/Program Files/PostgreSQL/8.4")
+
+
+set(PostgreSQL_ROOT_DIRECTORIES $ENV{PostgreSQL_ROOT})
+if(PostgreSQL_ROOT_DIRECTORIES)
+ file(TO_CMAKE_PATH ${PostgreSQL_ROOT_DIRECTORIES} PostgreSQL_ROOT_DIRECTORIES)
+endif(PostgreSQL_ROOT_DIRECTORIES)
+
+set(PostgreSQL_KNOWN_VERSIONS ${PostgreSQL_ADDITIONAL_VERSIONS}
+ "9.1" "9.0" "8.4" "8.3" "8.2" "8.1" "8.0")
+
+# Define additional search paths for root directories.
+if ( WIN32 )
+ foreach (suffix ${PostgreSQL_KNOWN_VERSIONS} )
+ set(PostgreSQL_ADDITIONAL_SEARCH_PATHS ${PostgreSQL_ADDITIONAL_SEARCH_PATHS} "C:/Program Files/PostgreSQL/${suffix}" )
+ endforeach(suffix)
+endif( WIN32 )
+set( PostgreSQL_ROOT_DIRECTORIES
+ ${PostgreSQL_ROOT_DIRECTORIES}
+ ${PostgreSQL_ROOT}
+ ${PostgreSQL_ADDITIONAL_SEARCH_PATHS}
+)
+
+#
+# Look for an installation.
+#
+find_path(PostgreSQL_INCLUDE_DIR
+ NAMES libpq-fe.h
+ PATHS
+ # Look in other places.
+ ${PostgreSQL_ROOT_DIRECTORIES}
+ PATH_SUFFIXES
+ pgsql
+ postgresql
+ include
+ # Help the user find it if we cannot.
+ DOC "The ${PostgreSQL_INCLUDE_DIR_MESSAGE}"
+)
+
+find_path(PostgreSQL_TYPE_INCLUDE_DIR
+ NAMES catalog/pg_type.h
+ PATHS
+ # Look in other places.
+ ${PostgreSQL_ROOT_DIRECTORIES}
+ PATH_SUFFIXES
+ postgresql
+ pgsql/server
+ postgresql/server
+ include/server
+ # Help the user find it if we cannot.
+ DOC "The ${PostgreSQL_INCLUDE_DIR_MESSAGE}"
+)
+
+# The PostgreSQL library.
+set (PostgreSQL_LIBRARY_TO_FIND pq)
+# Setting some more prefixes for the library
+set (PostgreSQL_LIB_PREFIX "")
+if ( WIN32 )
+ set (PostgreSQL_LIB_PREFIX ${PostgreSQL_LIB_PREFIX} "lib")
+ set ( PostgreSQL_LIBRARY_TO_FIND ${PostgreSQL_LIB_PREFIX}${PostgreSQL_LIBRARY_TO_FIND})
+endif()
+
+find_library( PostgreSQL_LIBRARY
+ NAMES ${PostgreSQL_LIBRARY_TO_FIND}
+ PATHS
+ ${PostgreSQL_ROOT_DIRECTORIES}
+ PATH_SUFFIXES
+ lib
+)
+get_filename_component(PostgreSQL_LIBRARY_DIR ${PostgreSQL_LIBRARY} PATH)
+
+if (PostgreSQL_INCLUDE_DIR AND EXISTS "${PostgreSQL_INCLUDE_DIR}/pg_config.h")
+ file(STRINGS "${PostgreSQL_INCLUDE_DIR}/pg_config.h" pgsql_version_str
+ REGEX "^#define[\t ]+PG_VERSION[\t ]+\".*\"")
+
+ string(REGEX REPLACE "^#define[\t ]+PG_VERSION[\t ]+\"([^\"]*)\".*" "\\1"
+ PostgreSQL_VERSION_STRING "${pgsql_version_str}")
+ unset(pgsql_version_str)
+endif()
+
+# Did we find anything?
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(PostgreSQL
+ REQUIRED_VARS PostgreSQL_LIBRARY PostgreSQL_INCLUDE_DIR PostgreSQL_TYPE_INCLUDE_DIR
+ VERSION_VAR PostgreSQL_VERSION_STRING)
+set( PostgreSQL_FOUND ${POSTGRESQL_FOUND})
+
+# Now try to get the include and library path.
+if(PostgreSQL_FOUND)
+
+ set(PostgreSQL_INCLUDE_DIRS ${PostgreSQL_INCLUDE_DIR} ${PostgreSQL_TYPE_INCLUDE_DIR} )
+ set(PostgreSQL_LIBRARY_DIRS ${PostgreSQL_LIBRARY_DIR} )
+ set(PostgreSQL_LIBRARIES ${PostgreSQL_LIBRARY_TO_FIND})
+
+ #message("Final PostgreSQL include dir: ${PostgreSQL_INCLUDE_DIRS}")
+ #message("Final PostgreSQL library dir: ${PostgreSQL_LIBRARY_DIRS}")
+ #message("Final PostgreSQL libraries: ${PostgreSQL_LIBRARIES}")
+endif(PostgreSQL_FOUND)
+
+mark_as_advanced(PostgreSQL_INCLUDE_DIR PostgreSQL_TYPE_INCLUDE_DIR PostgreSQL_LIBRARY )
diff --git a/include/connection.h b/include/connection.h
index e67ea27..cf3fb2e 100644
--- a/include/connection.h
+++ b/include/connection.h
@@ -19,8 +19,8 @@
*/
-#ifndef CONNECTION_H
-#define CONNECTION_H
+#ifndef CSSQLDB_CONNECTION_H
+#define CSSQLDB_CONNECTION_H
#include <plugin.h>
#include "logindata.h"
@@ -68,7 +68,7 @@ struct ConnectionData {
void Close(csnd::Csound* csound);
void Exec(char* sql);
MYFLT Scalar(char* sql, int row, int col);
- char* ScalarString(char* sql, int row=0, int col=0);
+ char* ScalarString(char* sql, csnd::Csound* csound, int row=0, int col=0);
void ArrayQuery(char* sql, csnd::Csound* csound, ARRAYDAT* array);
void ArrayQueryString(char* sql, csnd::Csound* csound, ARRAYDAT* array);
};
diff --git a/include/logindata.h b/include/logindata.h
index 8a62e6b..be8e79a 100644
--- a/include/logindata.h
+++ b/include/logindata.h
@@ -19,8 +19,8 @@
*/
-#ifndef LOGINDATA_H
-#define LOGINDATA_H
+#ifndef CSSQLDB_LOGINDATA_H
+#define CSSQLDB_LOGINDATA_H
struct LoginData {
int dbType;
diff --git a/include/mysql.h b/include/mysql.h
index 1abc6e3..950e9d3 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -19,8 +19,8 @@
*/
-#ifndef MYSQL_H
-#define MYSQL_H
+#ifndef CSSQLDB_MYSQL_H
+#define CSSQLDB_MYSQL_H
#include <plugin.h>
#include <cppconn/driver.h>
@@ -37,7 +37,7 @@ struct MySQLConnection {
void Exec(char* sql);
mysql::ResultSet* Query(char *sql);
MYFLT Scalar(char* sql, int row, int col);
- char* ScalarString(char* sql, int row, int col);
+ char* ScalarString(char* sql, csnd::Csound* csound, int row, int col);
void ToArray(mysql::ResultSet* result, csnd::Csound* csound, ARRAYDAT* array, bool asString);
void ArrayQuery(char* sql, csnd::Csound* csound, ARRAYDAT* array);
void ArrayQueryString(char* sql, csnd::Csound* csound, ARRAYDAT* array);
diff --git a/include/postgresql.h b/include/postgresql.h
index d7db5d9..eaf01c8 100644
--- a/include/postgresql.h
+++ b/include/postgresql.h
@@ -19,22 +19,22 @@
*/
-#ifndef POSTGRESQL_H
-#define POSTGRESQL_H
+#ifndef CSSQLDB_POSTGRESQL_H
+#define CSSQLDB_POSTGRESQL_H
#include <plugin.h>
-#include <pqxx/pqxx>
+#include "libpq-fe.h"
#include "connection.h"
struct PostgresConnection {
- pqxx::connection* conn;
+ PGconn* conn;
void Init(csnd::Csound* csound, LoginData* login);
void Close(csnd::Csound* csound);
void Exec(char* sql);
- pqxx::result Query(char *sql);
+ PGresult* Query(char *sql);
MYFLT Scalar(char* sql, int row, int col);
- char* ScalarString(char* sql, int row, int col);
- void ToArray(pqxx::result result, csnd::Csound* csound, ARRAYDAT* array, bool asString);
+ char* ScalarString(char* sql, csnd::Csound* csound, int row, int col);
+ void ToArray(PGresult* result, csnd::Csound* csound, ARRAYDAT* array, bool asString);
void ArrayQuery(char* sql, csnd::Csound* csound, ARRAYDAT* array);
void ArrayQueryString(char* sql, csnd::Csound* csound, ARRAYDAT* array);
};
diff --git a/include/sqlite.h b/include/sqlite.h
index 4e2b0c3..c42eb57 100644
--- a/include/sqlite.h
+++ b/include/sqlite.h
@@ -19,8 +19,8 @@
*/
-#ifndef XSQLITE3_H
-#define XSQLITE3_H
+#ifndef CSSQLDB_SQLITE3_H
+#define CSSQLDB_SQLITE3_H
#include <plugin.h>
#include <sqlite3.h>
@@ -33,7 +33,7 @@ struct SqliteConnection {
void Exec(char* sql);
sqlite3_stmt* Query(char *sql);
MYFLT Scalar(char* sql, int row, int col);
- char* ScalarString(char* sql, int row, int col);
+ char* ScalarString(char* sql, csnd::Csound* csound, int row, int col);
int RowCount(sqlite3_stmt* stmt);
void ToArray(sqlite3_stmt* result, csnd::Csound* csound, ARRAYDAT* array, bool asString);
void ArrayQuery(char* sql, csnd::Csound* csound, ARRAYDAT* array);
diff --git a/include/tools.h b/include/tools.h
new file mode 100644
index 0000000..54a0363
--- /dev/null
+++ b/include/tools.h
@@ -0,0 +1,30 @@
+/*
+ tools.h
+ 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.
+
+ */
+
+#ifndef CSSQLDB_TOOLS_H
+#define CSSQLDB_TOOLS_H
+
+#include <plugin.h>
+
+STRINGDAT* arrayInit(csnd::Csound* csound, ARRAYDAT* array, int rows, int cols);
+void insertArrayStringItem(csnd::Csound* csound, STRINGDAT* strings, int index, char* item);
+
+#endif /* TOOLS_H */
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