diff options
Diffstat (limited to 'odb-tests/libcommon')
-rw-r--r-- | odb-tests/libcommon/.gitignore | 3 | ||||
-rw-r--r-- | odb-tests/libcommon/buffer.hxx | 104 | ||||
-rw-r--r-- | odb-tests/libcommon/buildfile | 50 | ||||
-rw-r--r-- | odb-tests/libcommon/common.cxx | 384 | ||||
-rw-r--r-- | odb-tests/libcommon/common.hxx | 50 | ||||
-rw-r--r-- | odb-tests/libcommon/common.txx | 24 | ||||
-rw-r--r-- | odb-tests/libcommon/concrete.hxx | 57 | ||||
-rw-r--r-- | odb-tests/libcommon/config.hxx.in | 14 | ||||
-rw-r--r-- | odb-tests/libcommon/export.hxx | 39 |
9 files changed, 725 insertions, 0 deletions
diff --git a/odb-tests/libcommon/.gitignore b/odb-tests/libcommon/.gitignore new file mode 100644 index 0000000..a994ddc --- /dev/null +++ b/odb-tests/libcommon/.gitignore @@ -0,0 +1,3 @@ +# Generated config header. +# +config.hxx diff --git a/odb-tests/libcommon/buffer.hxx b/odb-tests/libcommon/buffer.hxx new file mode 100644 index 0000000..41b7e46 --- /dev/null +++ b/odb-tests/libcommon/buffer.hxx @@ -0,0 +1,104 @@ +// file : libcommon/buffer.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef LIBCOMMON_BUFFER_HXX +#define LIBCOMMON_BUFFER_HXX + +#include <new> +#include <cstddef> // std::size_t +#include <cstring> // std::{memcmp,memcpy} + +struct basic_buffer_base +{ + ~basic_buffer_base () + { + operator delete (data_); + } + + basic_buffer_base () + : data_ (0), size_ (0) + { + } + + basic_buffer_base (const void* data, std::size_t size) + : data_ (0), size_ (size) + { + data_ = operator new (size_); + std::memcpy (data_, data, size_); + } + + basic_buffer_base (const basic_buffer_base& y) + : data_ (0), size_ (0) + { + assign (y.data_, y.size_); + } + + basic_buffer_base& + operator= (const basic_buffer_base& y) + { + if (this != &y) + assign (y.data_, y.size_); + + return *this; + } + + void + assign (const void* data, std::size_t size) + { + if (size_ < size) + { + void *p (operator new (size)); + operator delete (data_); + data_ = p; + } + + std::memcpy (data_, data, size); + size_ = size; + } + + std::size_t + size () const + { + return size_; + } + + bool + operator== (const basic_buffer_base& y) const + { + return size_ == y.size_ && std::memcmp (data_, y.data_, size_) == 0; + } + +protected: + void* data_; + std::size_t size_; +}; + +template <typename T> +struct basic_buffer: basic_buffer_base +{ + basic_buffer () + { + } + + basic_buffer (const T* data, std::size_t size) + : basic_buffer_base (data, size) + { + } + + T* + data () + { + return static_cast<T*> (data_); + } + + const T* + data () const + { + return static_cast<const T*> (data_); + } +}; + +typedef basic_buffer<char> buffer; +typedef basic_buffer<unsigned char> ubuffer; + +#endif // LIBCOMMON_BUFFER_HXX diff --git a/odb-tests/libcommon/buildfile b/odb-tests/libcommon/buildfile new file mode 100644 index 0000000..eb61455 --- /dev/null +++ b/odb-tests/libcommon/buildfile @@ -0,0 +1,50 @@ +# file : libcommon/buildfile +# license : GNU GPL v2; see accompanying LICENSE file + +import intf_libs = libodb%lib{odb} + +for db: $databases + import intf_libs += libodb-$db%lib{odb-$db} + +lib{common}: {hxx ixx txx cxx}{** -config} hxx{config} $intf_libs + +# Generated config file. +# +using autoconf + +hxx{config}: in{config} +{ + DATABASE_MYSQL = $mysql + DATABASE_SQLITE = $sqlite + DATABASE_PGSQL = $pgsql + DATABASE_ORACLE = $oracle + DATABASE_MSSQL = $mssql + MULTI_DATABASE = $multi +} + +# Build options. +# +cxx.poptions =+ "-I$out_root" "-I$src_root" + +{hbmia obja}{*}: cxx.poptions += -DLIBCOMMON_STATIC_BUILD +{hbmis objs}{*}: cxx.poptions += -DLIBCOMMON_SHARED_BUILD + +# Export options. +# +lib{common}: +{ + cxx.export.poptions = "-I$out_root" "-I$src_root" + cxx.export.libs = $intf_libs +} + +liba{common}: cxx.export.poptions += -DLIBCOMMON_STATIC +libs{common}: cxx.export.poptions += -DLIBCOMMON_SHARED + +# For pre-releases use the complete version to make sure they cannot +# be used in place of another pre-release or the final version. See +# the version module for details on the version.* variable values. +# +if $version.pre_release + lib{common}: bin.lib.version = "-$version.project_id" +else + lib{common}: bin.lib.version = "-$version.major.$version.minor" diff --git a/odb-tests/libcommon/common.cxx b/odb-tests/libcommon/common.cxx new file mode 100644 index 0000000..0e6fe55 --- /dev/null +++ b/odb-tests/libcommon/common.cxx @@ -0,0 +1,384 @@ +// file : libcommon/common.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include <cstdlib> // std::exit +#include <utility> // std::move +#include <iostream> + +#include <odb/database.hxx> + +#include <libcommon/config.hxx> +#include <libcommon/common.hxx> + +// MySQL. +// +#if defined(DATABASE_MYSQL) + +#include <odb/mysql/database.hxx> +#include <odb/mysql/connection-factory.hxx> + +static std::unique_ptr<odb::database> +create_mysql_database (int& argc, char* argv[], bool, size_t max_connections) +{ + using namespace std; + using namespace odb::core; + namespace mysql = odb::mysql; + + unique_ptr<mysql::connection_factory> f; + + if (max_connections != 0) + f.reset (new mysql::connection_pool_factory (max_connections)); + + return unique_ptr<database> ( + new mysql::database (argc, argv, false, "", 0, move (f))); +} +#endif // MySQL + + +// SQLite. +// +#if defined(DATABASE_SQLITE) + +#include <odb/connection.hxx> +#include <odb/transaction.hxx> +#include <odb/schema-catalog.hxx> +#include <odb/sqlite/database.hxx> +#include <odb/sqlite/connection-factory.hxx> + +static std::unique_ptr<odb::database> +create_sqlite_database (int& argc, + char* argv[], + bool schema, + size_t max_connections) +{ + using namespace std; + using namespace odb::core; + namespace sqlite = odb::sqlite; + + unique_ptr<sqlite::connection_factory> f; + + if (max_connections != 0) + f.reset (new sqlite::connection_pool_factory (max_connections)); + + unique_ptr<database> db ( + new sqlite::database ( + argc, argv, false, + SQLITE_OPEN_READWRITE + | SQLITE_OPEN_CREATE +#ifdef SQLITE_OPEN_URI + | SQLITE_OPEN_URI +#endif + , + true, + "", + move (f))); + + // Create the database schema. Due to bugs in SQLite foreign key + // support for DDL statements, we need to temporarily disable + // foreign keys. + // + if (schema) + { + connection_ptr c (db->connection ()); + + c->execute ("PRAGMA foreign_keys=OFF"); + + transaction t (c->begin ()); + schema_catalog::create_schema (*db); + t.commit (); + + c->execute ("PRAGMA foreign_keys=ON"); + } + + return db; +} +#endif // SQLite + + +// PostgreSQL. +// +#if defined(DATABASE_PGSQL) + +#include <odb/pgsql/database.hxx> +#include <odb/pgsql/connection-factory.hxx> + +static std::unique_ptr<odb::database> +create_pgsql_database (int& argc, char* argv[], bool, size_t max_connections) +{ + using namespace std; + using namespace odb::core; + namespace pgsql = odb::pgsql; + + unique_ptr<pgsql::connection_factory> f; + + if (max_connections != 0) + f.reset (new pgsql::connection_pool_factory (max_connections)); + + return unique_ptr<database> ( + new pgsql::database (argc, argv, false, "", move (f))); +} +#endif // PostgreSQL + + +// Oracle. +// +#if defined(DATABASE_ORACLE) + +#include <odb/oracle/database.hxx> +#include <odb/oracle/connection-factory.hxx> + +static std::unique_ptr<odb::database> +create_oracle_database (int& argc, char* argv[], bool, size_t max_connections) +{ + using namespace std; + using namespace odb::core; + namespace oracle = odb::oracle; + + unique_ptr<oracle::connection_factory> f; + + if (max_connections != 0) + f.reset (new oracle::connection_pool_factory (max_connections)); + + // Set client database character set and client national character set + // to UTF-8. + // + return unique_ptr<database> ( + new oracle::database (argc, argv, false, 873, 873, 0, move (f))); +} +#endif // Oracle + +// SQL Server. +// +#if defined(DATABASE_MSSQL) + +#include <odb/mssql/database.hxx> +#include <odb/mssql/connection-factory.hxx> + +static std::unique_ptr<odb::database> +create_mssql_database (int& argc, char* argv[], bool, size_t max_connections) +{ + using namespace std; + using namespace odb::core; + namespace mssql = odb::mssql; + + unique_ptr<mssql::connection_factory> f; + + if (max_connections != 0) + f.reset (new mssql::connection_pool_factory (max_connections)); + + return unique_ptr<database> ( + new mssql::database (argc, argv, false, "TrustServerCertificate=yes", + mssql::isolation_read_committed, 0, move (f))); +} +#endif // SQL Server + +// +// +std::unique_ptr<odb::database> +create_database (int argc, + char* argv[], + bool schema, + size_t max_connections, +#if defined(MULTI_DATABASE) + odb::database_id db +#else + odb::database_id +#endif +) +{ + using namespace std; + using namespace odb::core; + + char** argp = argv + 1; // Position of the next argument. Assignment for VC8. + int argn (argc - 1); // Number of arguments left. + +#if defined(MULTI_DATABASE) + // Figure out which database we are creating. We may be given the + // database name as a program argument or as an id. + // + if (db == odb::id_common && argn != 0) + { + string s (*argp); + + if (s == "mysql") + db = odb::id_mysql; + else if (s == "sqlite") + db = odb::id_sqlite; + else if (s == "pgsql") + db = odb::id_pgsql; + else if (s == "oracle") + db = odb::id_oracle; + else if (s == "mssql") + db = odb::id_mssql; + + if (db != odb::id_common) + { + argp++; + argn--; + } + } + + if (db == odb::id_common) + { + cerr << "Usage: " << argv[0] << " <db> [options]" << endl; + exit (1); + } +#endif + + if (argn != 0 && *argp == string ("--help")) + { +#if defined(MULTI_DATABASE) + cout << "Usage: " << argv[0] << " <db> [options]" << endl; +#else + cout << "Usage: " << argv[0] << " [options]" << endl; +#endif + + cout << "Options:" << endl; + +#if defined(MULTI_DATABASE) + switch (db) + { + case odb::id_mysql: +#if defined(DATABASE_MYSQL) + odb::mysql::database::print_usage (cout); +#else + assert (false); +#endif + break; + case odb::id_sqlite: +#if defined(DATABASE_SQLITE) + odb::sqlite::database::print_usage (cout); +#else + assert (false); +#endif + break; + case odb::id_pgsql: +#if defined(DATABASE_PGSQL) + odb::pgsql::database::print_usage (cout); +#else + assert (false); +#endif + break; + case odb::id_oracle: +#if defined(DATABASE_ORACLE) + odb::oracle::database::print_usage (cout); +#else + assert (false); +#endif + break; + case odb::id_mssql: +#if defined(DATABASE_MSSQL) + odb::mssql::database::print_usage (cout); +#else + assert (false); +#endif + break; + case odb::id_common: + assert (false); + } +#elif defined(DATABASE_MYSQL) + odb::mysql::database::print_usage (cout); +#elif defined(DATABASE_SQLITE) + odb::sqlite::database::print_usage (cout); +#elif defined(DATABASE_PGSQL) + odb::pgsql::database::print_usage (cout); +#elif defined(DATABASE_ORACLE) + odb::oracle::database::print_usage (cout); +#elif defined(DATABASE_MSSQL) + odb::mssql::database::print_usage (cout); +#else +# error unknown database +#endif + + exit (0); + } + +#if defined(MULTI_DATABASE) + switch (db) + { + case odb::id_mysql: +#if defined(DATABASE_MYSQL) + return create_mysql_database (argc, argv, schema, max_connections); +#else + assert (false); + break; +#endif + case odb::id_sqlite: +#if defined(DATABASE_SQLITE) + return create_sqlite_database (argc, argv, schema, max_connections); +#else + assert (false); + break; +#endif + case odb::id_pgsql: +#if defined(DATABASE_PGSQL) + return create_pgsql_database (argc, argv, schema, max_connections); +#else + assert (false); + break; +#endif + case odb::id_oracle: +#if defined(DATABASE_ORACLE) + return create_oracle_database (argc, argv, schema, max_connections); +#else + assert (false); + break; +#endif + case odb::id_mssql: +#if defined(DATABASE_MSSQL) + return create_mssql_database (argc, argv, schema, max_connections); +#else + assert (false); + break; +#endif + case odb::id_common: + assert (false); + } + return unique_ptr<database> (); +#elif defined(DATABASE_MYSQL) + return create_mysql_database (argc, argv, schema, max_connections); +#elif defined(DATABASE_SQLITE) + return create_sqlite_database (argc, argv, schema, max_connections); +#elif defined(DATABASE_PGSQL) + return create_pgsql_database (argc, argv, schema, max_connections); +#elif defined(DATABASE_ORACLE) + return create_oracle_database (argc, argv, schema, max_connections); +#elif defined(DATABASE_MSSQL) + return create_mssql_database (argc, argv, schema, max_connections); +#else +# error unknown database +#endif +} + +#ifndef MULTI_DATABASE +std::string +quote_name (const std::string& name) +{ +#if defined(DATABASE_MYSQL) + return '`' + name + '`'; +#elif defined(DATABASE_SQLITE) + return '"' + name + '"'; +#elif defined(DATABASE_PGSQL) + return '"' + name + '"'; +#elif defined(DATABASE_ORACLE) + return '"' + name + '"'; +#elif defined(DATABASE_MSSQL) + return '[' + name + ']'; +#else +# error unknown database +#endif +} +#endif + +bool +size_available () +{ +#if defined(MULTI_DATABASE) || \ + defined(DATABASE_SQLITE) || \ + defined(DATABASE_ORACLE) || \ + defined(DATABASE_MSSQL) + return false; +#else + return true; +#endif +} diff --git a/odb-tests/libcommon/common.hxx b/odb-tests/libcommon/common.hxx new file mode 100644 index 0000000..904bfc6 --- /dev/null +++ b/odb-tests/libcommon/common.hxx @@ -0,0 +1,50 @@ +// file : libcommon/common.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef LIBCOMMON_COMMON_HXX +#define LIBCOMMON_COMMON_HXX + +#include <memory> // std::unique_ptr +#include <cstddef> // std::size_t + +#include <odb/result.hxx> +#include <odb/database.hxx> + +#include <libcommon/export.hxx> + +LIBCOMMON_SYMEXPORT std::unique_ptr<odb::database> +create_database (int argc, + char* argv[], + bool create_schema = true, + std::size_t max_connections = 0, + odb::database_id db = odb::id_common); + +template <typename T> +std::unique_ptr<T> +create_specific_database (int argc, + char* argv[], + bool create_schema = true, + std::size_t max_connections = 0) +{ + std::unique_ptr<odb::database> r ( + create_database (argc, argv, + create_schema, + max_connections, + T::database_id)); + + return std::unique_ptr<T> (&dynamic_cast<T&> (*r.release ())); +} + +LIBCOMMON_SYMEXPORT std::string +quote_name (const std::string&); + +// This function returns an accurate result only if the result iterator +// hasn't been advanced and after the call the result is no longer valid. +// +template <typename T> +std::size_t +size (odb::result<T>); + +#include <libcommon/common.txx> + +#endif // LIBCOMMON_COMMON_HXX diff --git a/odb-tests/libcommon/common.txx b/odb-tests/libcommon/common.txx new file mode 100644 index 0000000..caa7481 --- /dev/null +++ b/odb-tests/libcommon/common.txx @@ -0,0 +1,24 @@ +// file : libcommon/common.txx +// license : GNU GPL v2; see accompanying LICENSE file + +// We have to use this helper function instead of just checking which +// database is used because the DATABASE_* macro may not be defined +// in a project that includes this header. +// +LIBCOMMON_SYMEXPORT bool +size_available (); + +template <typename T> +std::size_t +size (odb::result<T> r) +{ + if (size_available ()) + return r.size (); + else + { + std::size_t n (0); + for (typename odb::result<T>::iterator i (r.begin ()); i != r.end (); ++i) + n++; + return n; + } +} diff --git a/odb-tests/libcommon/concrete.hxx b/odb-tests/libcommon/concrete.hxx new file mode 100644 index 0000000..e0f64a5 --- /dev/null +++ b/odb-tests/libcommon/concrete.hxx @@ -0,0 +1,57 @@ +// file : libcommon/concrete.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef LIBCOMMON_CONCRETE_HXX +#define LIBCOMMON_CONCRETE_HXX + +#include <libcommon/config.hxx> + +// Namespace alias for the concrete database namespace. +// +#if defined(MULTI_DATABASE) + +// Fallback to common interface. +// +#include <odb/database.hxx> +#include <odb/transaction.hxx> + +namespace odb_db = odb; + +#elif defined(DATABASE_MYSQL) + +#include <odb/mysql/database.hxx> +#include <odb/mysql/transaction.hxx> + +namespace odb_db = odb::mysql; + +#elif defined(DATABASE_SQLITE) + +#include <odb/sqlite/database.hxx> +#include <odb/sqlite/transaction.hxx> + +namespace odb_db = odb::sqlite; + +#elif defined(DATABASE_PGSQL) + +#include <odb/pgsql/database.hxx> +#include <odb/pgsql/transaction.hxx> + +namespace odb_db = odb::pgsql; + +#elif defined(DATABASE_ORACLE) + +#include <odb/oracle/database.hxx> +#include <odb/oracle/transaction.hxx> + +namespace odb_db = odb::oracle; + +#elif defined(DATABASE_MSSQL) + +#include <odb/mssql/database.hxx> +#include <odb/mssql/transaction.hxx> + +namespace odb_db = odb::mssql; + +#endif + +#endif // LIBCOMMON_CONCRETE_HXX diff --git a/odb-tests/libcommon/config.hxx.in b/odb-tests/libcommon/config.hxx.in new file mode 100644 index 0000000..ff90e61 --- /dev/null +++ b/odb-tests/libcommon/config.hxx.in @@ -0,0 +1,14 @@ +// file : libcommon/config.hxx.in +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef LIBCOMMON_CONFIG_HXX +#define LIBCOMMON_CONFIG_HXX + +#undef DATABASE_MYSQL +#undef DATABASE_SQLITE +#undef DATABASE_PGSQL +#undef DATABASE_ORACLE +#undef DATABASE_MSSQL +#undef MULTI_DATABASE + +#endif // LIBCOMMON_CONFIG_HXX diff --git a/odb-tests/libcommon/export.hxx b/odb-tests/libcommon/export.hxx new file mode 100644 index 0000000..0de4565 --- /dev/null +++ b/odb-tests/libcommon/export.hxx @@ -0,0 +1,39 @@ +#pragma once + +// Normally we don't export class templates (but do complete specializations), +// inline functions, and classes with only inline member functions. Exporting +// classes that inherit from non-exported/imported bases (e.g., std::string) +// will end up badly. The only known workarounds are to not inherit or to not +// export. Also, MinGW GCC doesn't like seeing non-exported functions being +// used before their inline definition. The workaround is to reorder code. In +// the end it's all trial and error. + +#if defined(LIBCOMMON_STATIC) // Using static. +# define LIBCOMMON_SYMEXPORT +#elif defined(LIBCOMMON_STATIC_BUILD) // Building static. +# define LIBCOMMON_SYMEXPORT +#elif defined(LIBCOMMON_SHARED) // Using shared. +# ifdef _WIN32 +# define LIBCOMMON_SYMEXPORT __declspec(dllimport) +# else +# define LIBCOMMON_SYMEXPORT +# endif +#elif defined(LIBCOMMON_SHARED_BUILD) // Building shared. +# ifdef _WIN32 +# define LIBCOMMON_SYMEXPORT __declspec(dllexport) +# else +# define LIBCOMMON_SYMEXPORT +# endif +#else +// If none of the above macros are defined, then we assume we are being used +// by some third-party build system that cannot/doesn't signal the library +// type. Note that this fallback works for both static and shared libraries +// provided the library only exports functions (in other words, no global +// exported data) and for the shared case the result will be sub-optimal +// compared to having dllimport. If, however, your library does export data, +// then you will probably want to replace the fallback with the (commented +// out) error since it won't work for the shared case. +// +# define LIBCOMMON_SYMEXPORT // Using static or shared. +//# error define LIBCOMMON_STATIC or LIBCOMMON_SHARED preprocessor macro to signal libcommon library type being linked +#endif |