summaryrefslogtreecommitdiff
path: root/odb-tests/libcommon
diff options
context:
space:
mode:
Diffstat (limited to 'odb-tests/libcommon')
-rw-r--r--odb-tests/libcommon/.gitignore3
-rw-r--r--odb-tests/libcommon/buffer.hxx104
-rw-r--r--odb-tests/libcommon/buildfile50
-rw-r--r--odb-tests/libcommon/common.cxx384
-rw-r--r--odb-tests/libcommon/common.hxx50
-rw-r--r--odb-tests/libcommon/common.txx24
-rw-r--r--odb-tests/libcommon/concrete.hxx57
-rw-r--r--odb-tests/libcommon/config.hxx.in14
-rw-r--r--odb-tests/libcommon/export.hxx39
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