aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2012-01-14 12:52:04 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2012-01-14 12:52:04 +0200
commitc5d8c8293ce3e35d0606d3054cb74baf9ac02bd2 (patch)
treea3a1828c0510b158b828ad15eb28a49a6b7be782
parent5074a7ffdcae708ebd534fa7eaeb228813694a7c (diff)
Basic Qt profile implementation for SQL Server
-rw-r--r--odb/qt/basic-mssql.options14
-rw-r--r--odb/qt/basic/mssql/default-mapping.hxx24
-rw-r--r--odb/qt/basic/mssql/qbyte-array-traits.hxx177
-rw-r--r--odb/qt/basic/mssql/qstring-traits.hxx374
4 files changed, 589 insertions, 0 deletions
diff --git a/odb/qt/basic-mssql.options b/odb/qt/basic-mssql.options
new file mode 100644
index 0000000..31536bb
--- /dev/null
+++ b/odb/qt/basic-mssql.options
@@ -0,0 +1,14 @@
+# file : odb/qt/basic-mssql.options
+# author : Constantin Michael <constantin@codesynthesis.com>
+# copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC
+# license : GNU GPL v2; see accompanying LICENSE file
+
+--profile qt/version
+
+# Include the default mapping in prologue instead of epilogue to
+# allow the user to override the default mapping.
+#
+--odb-prologue '#include <odb/qt/basic/mssql/default-mapping.hxx>'
+
+--hxx-prologue '#include <odb/qt/basic/mssql/qstring-traits.hxx>'
+--hxx-prologue '#include <odb/qt/basic/mssql/qbyte-array-traits.hxx>'
diff --git a/odb/qt/basic/mssql/default-mapping.hxx b/odb/qt/basic/mssql/default-mapping.hxx
new file mode 100644
index 0000000..7e50a8e
--- /dev/null
+++ b/odb/qt/basic/mssql/default-mapping.hxx
@@ -0,0 +1,24 @@
+// file : odb/qt/basic/mssql/default-mapping.hxx
+// author : Constantin Michael <constantin@codesynthesis.com>
+// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef ODB_QT_BASIC_MSSQL_DEFAULT_MAPPING_HXX
+#define ODB_QT_BASIC_MSSQL_DEFAULT_MAPPING_HXX
+
+#include <QtCore/QString>
+#include <QtCore/QByteArray>
+
+// By default map QString to SQL Server VARCHAR(512) for non-id members
+// and to VARCHAR(256) for id members (the same as the default mapping
+// for std::string). Allow NULL values by default as QString provides
+// a null representation.
+//
+#pragma db value(QString) type("VARCHAR(512)") id_type("VARCHAR(256)") null
+
+// By default map QByteArray to SQL Server VARBINARY(max). Allow NULL
+// values by default as QByteArray provides a null representation.
+//
+#pragma db value(QByteArray) type("VARBINARY(max)") null
+
+#endif // ODB_QT_BASIC_MSSQL_DEFAULT_MAPPING_HXX
diff --git a/odb/qt/basic/mssql/qbyte-array-traits.hxx b/odb/qt/basic/mssql/qbyte-array-traits.hxx
new file mode 100644
index 0000000..70b7019
--- /dev/null
+++ b/odb/qt/basic/mssql/qbyte-array-traits.hxx
@@ -0,0 +1,177 @@
+// file : odb/qt/basic/mssql/qbyte-array-traits.hxx
+// author : Constantin Michael <constantin@codesynthesis.com>
+// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef ODB_QT_BASIC_MSSQL_QBYTE_ARRAY_TRAITS_HXX
+#define ODB_QT_BASIC_MSSQL_QBYTE_ARRAY_TRAITS_HXX
+
+#include <odb/pre.hxx>
+
+#include <cstring> // std::memcpy
+#include <cstddef> // std::size_t
+#include <cassert>
+
+#include <QtCore/QByteArray>
+
+#include <odb/mssql/traits.hxx>
+
+namespace odb
+{
+ namespace mssql
+ {
+ template <>
+ struct default_value_traits<QByteArray, id_binary>
+ {
+ typedef QByteArray value_type;
+ typedef QByteArray query_type;
+ typedef char* image_type;
+
+ static void
+ set_value (QByteArray& v, const char* b, std::size_t n, bool is_null)
+ {
+ if (is_null)
+ v = QByteArray ();
+ else
+ {
+ // Note that we cannot use replace() here since a suitable
+ // overload was only added in Qt 4.7.
+ //
+ v.resize (static_cast<int> (n));
+ std::memcpy (v.data (), b, n);
+ }
+ }
+
+ static void
+ set_image (char* b,
+ std::size_t c,
+ std::size_t& n,
+ bool& is_null,
+ const QByteArray& v)
+ {
+ if (v.isNull ())
+ is_null = true;
+ else
+ {
+ is_null = false;
+ n = static_cast<std::size_t> (v.size ());
+
+ if (n > c)
+ n = c;
+
+ std::memcpy (b, v.constData (), n);
+ }
+ }
+ };
+
+ template <>
+ struct default_value_traits<QByteArray, id_long_binary>
+ {
+ typedef QByteArray value_type;
+ typedef QByteArray query_type;
+ typedef long_callback image_type;
+
+ static void
+ set_value (QByteArray& v,
+ result_callback_type& cb,
+ void*& context)
+ {
+ cb = &result_callback;
+ context = &v;
+ }
+
+ static void
+ set_image (param_callback_type& cb,
+ const void*& context,
+ bool& is_null,
+ const QByteArray& v)
+ {
+ if (v.isNull ())
+ is_null = true;
+ else
+ {
+ is_null = false;
+ cb = &param_callback;
+ context = &v;
+ }
+ }
+
+ static void
+ param_callback (const void* context,
+ std::size_t*,
+ const void** buffer,
+ std::size_t* size,
+ chunk_type* chunk,
+ void*,
+ std::size_t)
+ {
+ const QByteArray& v (*static_cast<const QByteArray*> (context));
+
+ *buffer = v.constData ();
+ *size = static_cast<std::size_t> (v.size ());
+ *chunk = chunk_one;
+ }
+
+ static void
+ result_callback (void* context,
+ std::size_t*,
+ void** buffer,
+ std::size_t* size,
+ chunk_type chunk,
+ std::size_t size_left,
+ void*,
+ std::size_t)
+ {
+ QByteArray& v (*static_cast<QByteArray*> (context));
+
+ switch (chunk)
+ {
+ case chunk_null:
+ {
+ v = QByteArray ();
+ break;
+ }
+ case chunk_one:
+ {
+ v.clear ();
+ break;
+ }
+ case chunk_first:
+ {
+ // The Native Client ODBC driver seems to always be able to
+ // return the total size. This makes things simple and
+ // efficient.
+ //
+ assert (size_left != 0);
+
+ v.resize (static_cast<int> (size_left));
+ *buffer = v.data ();
+ *size = size_left;
+ break;
+ }
+ case chunk_next:
+ {
+ // We should never get here.
+ //
+ assert (false);
+ break;
+ }
+ case chunk_last:
+ {
+ // Nothing to do here. The array is already of the correct size
+ // and should contain the data.
+ break;
+ }
+ }
+ }
+ };
+
+ template <>
+ struct default_type_traits<QByteArray>
+ {
+ static const database_type_id db_type_id = id_long_binary;
+ };
+ }
+}
+
+#endif // ODB_QT_BASIC_MSSQL_QBYTE_ARRAY_TRAITS_HXX
diff --git a/odb/qt/basic/mssql/qstring-traits.hxx b/odb/qt/basic/mssql/qstring-traits.hxx
new file mode 100644
index 0000000..9db8fd5
--- /dev/null
+++ b/odb/qt/basic/mssql/qstring-traits.hxx
@@ -0,0 +1,374 @@
+// file : odb/qt/basic/mssql/qstring-traits.hxx
+// author : Constantin Michael <constantin@codesynthesis.com>
+// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef ODB_QT_BASIC_MSSQL_QSTRING_TRAITS_HXX
+#define ODB_QT_BASIC_MSSQL_QSTRING_TRAITS_HXX
+
+#include <odb/pre.hxx>
+
+#include <cstring> // std::memcpy
+#include <cstddef> // std::size_t
+#include <cassert>
+
+#include <QtCore/QString>
+
+#include <odb/mssql/traits.hxx>
+
+namespace odb
+{
+ namespace mssql
+ {
+ template <>
+ struct default_value_traits<QString, id_string>
+ {
+ typedef QString value_type;
+ typedef QString query_type;
+ typedef char* image_type;
+
+ static void
+ set_value (QString& v,
+ const char* b,
+ std::size_t n,
+ bool is_null)
+ {
+ if (is_null)
+ v = QString ();
+ else
+ // On Windows the string data is in Windows code page. On Linux
+ // it is always UTF-8.
+ //
+#ifdef _WIN32
+ v = QString::fromLocal8Bit (b, static_cast<int> (n));
+#else
+ v = QString::fromUtf8 (b, static_cast<int> (n));
+#endif
+ }
+
+ static void
+ set_image (char* b,
+ std::size_t c,
+ std::size_t& n,
+ bool& is_null,
+ const QString& v)
+ {
+ if (v.isNull ())
+ is_null = true;
+ else
+ {
+ is_null = false;
+
+#ifdef _WIN32
+ const QByteArray& a (v.toLocal8Bit ());
+#else
+ const QByteArray& a (v.toUtf8 ());
+#endif
+ n = static_cast<std::size_t> (a.size ());
+
+ if (n > c)
+ n = c;
+
+ std::memcpy (b, a.constData (), n);
+ }
+ }
+ };
+
+ template <>
+ struct default_value_traits<QString, id_nstring>
+ {
+ typedef QString value_type;
+ typedef QString query_type;
+ typedef ucs2_char* image_type;
+
+ static void
+ set_value (QString& v,
+ const ucs2_char* b,
+ std::size_t n,
+ bool is_null)
+ {
+ if (is_null)
+ v = QString ();
+ else
+ {
+ // Note that we cannot use replace() here since a suitable
+ // overload was only added in Qt 4.7.
+ //
+ v.resize (static_cast<int> (n));
+ std::memcpy (v.data (), b, n * 2);
+ }
+ }
+
+ static void
+ set_image (ucs2_char* b,
+ std::size_t c,
+ std::size_t& n,
+ bool& is_null,
+ const QString& v)
+ {
+ if (v.isNull ())
+ is_null = true;
+ else
+ {
+ is_null = false;
+ n = static_cast<std::size_t> (v.size ());
+
+ if (n > c)
+ n = c;
+
+ std::memcpy (b, v.constData (), n * 2);
+ }
+ }
+ };
+
+ template <>
+ struct default_value_traits<QString, id_long_string>
+ {
+ typedef QString value_type;
+ typedef QString query_type;
+ typedef long_callback image_type;
+
+ static void
+ set_value (QString& v,
+ result_callback_type& cb,
+ void*& context)
+ {
+ cb = &result_callback;
+ context = &v;
+ }
+
+ static void
+ set_image (param_callback_type& cb,
+ const void*& context,
+ bool& is_null,
+ const QString& v)
+ {
+ if (v.isNull ())
+ is_null = true;
+ else
+ {
+ is_null = false;
+ cb = &param_callback;
+ context = &v;
+ }
+ }
+
+ static void
+ param_callback (const void* context,
+ std::size_t* position,
+ const void** buffer,
+ std::size_t* size,
+ chunk_type* chunk,
+ void* tmp_buf,
+ std::size_t tmp_capacity)
+ {
+ const QString& s (*static_cast<const QString*> (context));
+
+#ifdef _WIN32
+ const QByteArray& v (s.toLocal8Bit ());
+#else
+ const QByteArray& v (s.toUtf8 ());
+#endif
+
+ *size = static_cast<std::size_t> (v.size ());
+
+ if (*position == 0)
+ {
+ if (*size <= tmp_capacity)
+ *chunk = chunk_one;
+ else
+ {
+ *size = tmp_capacity;
+ *chunk = chunk_first;
+ }
+ }
+ else
+ {
+ *size -= *position;
+
+ if (*size <= tmp_capacity)
+ *chunk = chunk_last;
+ else
+ {
+ *size = tmp_capacity;
+ *chunk = chunk_next;
+ }
+ }
+
+ //@@ We might split a multi-byte sequence. Microsoft ODBC driver
+ // doesn't support this.
+ //
+ std::memcpy (tmp_buf, v.constData () + *position, *size);
+ *buffer = tmp_buf;
+ *position += *size;
+ }
+
+ static void
+ result_callback (void* context,
+ std::size_t*,
+ void** buffer,
+ std::size_t* size,
+ chunk_type chunk,
+ std::size_t,
+ void* tmp_buf,
+ std::size_t tmp_capacity)
+ {
+ QString& v (*static_cast<QString*> (context));
+
+ switch (chunk)
+ {
+ case chunk_null:
+ {
+ v = QString ();
+ break;
+ }
+ case chunk_one:
+ {
+ v.clear ();
+ break;
+ }
+ case chunk_first:
+ {
+ break;
+ }
+ case chunk_next:
+ case chunk_last:
+ {
+ // Append the data from the temporary buffer.
+ //
+#ifdef _WIN32
+ v += QString::fromLocal8Bit (static_cast<char*> (tmp_buf),
+ static_cast<int> (*size));
+#else
+ v += QString::fromUtf8 (static_cast<char*> (tmp_buf),
+ static_cast<int> (*size));
+#endif
+ break;
+ }
+ }
+
+ if (chunk == chunk_first || chunk == chunk_next)
+ {
+ *buffer = tmp_buf;
+ *size = tmp_capacity;
+ }
+ }
+ };
+
+ template <>
+ struct default_value_traits<QString, id_long_nstring>
+ {
+ typedef QString value_type;
+ typedef QString query_type;
+ typedef long_callback image_type;
+
+ static void
+ set_value (QString& v,
+ result_callback_type& cb,
+ void*& context)
+ {
+ cb = &result_callback;
+ context = &v;
+ }
+
+ static void
+ set_image (param_callback_type& cb,
+ const void*& context,
+ bool& is_null,
+ const QString& v)
+ {
+ if (v.isNull ())
+ is_null = true;
+ else
+ {
+ is_null = false;
+ cb = &param_callback;
+ context = &v;
+ }
+ }
+
+ static void
+ param_callback (const void* context,
+ std::size_t*,
+ const void** buffer,
+ std::size_t* size,
+ chunk_type* chunk,
+ void*,
+ std::size_t)
+ {
+ const QString& v (*static_cast<const QString*> (context));
+
+ *buffer = v.constData ();
+ *size = static_cast<std::size_t> (v.size ()) * 2;
+ *chunk = chunk_one;
+ }
+
+ static void
+ result_callback (void* context,
+ std::size_t*,
+ void** buffer,
+ std::size_t* size,
+ chunk_type chunk,
+ std::size_t size_left,
+ void*,
+ std::size_t)
+ {
+ QString& v (*static_cast<QString*> (context));
+
+ switch (chunk)
+ {
+ case chunk_null:
+ {
+ v = QString ();
+ break;
+ }
+ case chunk_one:
+ {
+ v.clear ();
+ break;
+ }
+ case chunk_first:
+ {
+ // The Native Client ODBC driver seems to always be able to
+ // return the total size. This makes things simple and
+ // efficient.
+ //
+ assert (size_left != 0);
+
+ size_left /= 2; // Convert to characters.
+ size_left++; // One extra for the null terminator.
+
+ v.resize (static_cast<int> (size_left));
+ *buffer = v.data ();
+ *size = size_left * 2; // In bytes.
+ break;
+ }
+ case chunk_next:
+ {
+ // We should never get here.
+ //
+ assert (false);
+ break;
+ }
+ case chunk_last:
+ {
+ // Get rid of the null terminator.
+ //
+ v.resize (static_cast<int> (*size / 2));
+ break;
+ }
+ }
+ }
+ };
+
+ template <>
+ struct default_type_traits<QString>
+ {
+ static const database_type_id db_type_id = id_long_string;
+ };
+ }
+}
+
+#include <odb/post.hxx>
+
+#endif // ODB_QT_BASIC_MSSQL_QSTRING_TRAITS_HXX