diff options
Diffstat (limited to 'doc/manual.xhtml')
-rw-r--r-- | doc/manual.xhtml | 277 |
1 files changed, 252 insertions, 25 deletions
diff --git a/doc/manual.xhtml b/doc/manual.xhtml index 095f540..39ba2b5 100644 --- a/doc/manual.xhtml +++ b/doc/manual.xhtml @@ -541,14 +541,17 @@ for consistency. </td> </tr> <tr> - <th>12.6</th><td><a href="#12.6">C++ Compiler Warnings</a> + <th>12.6</th><td><a href="#12.6">Database Type Mapping Pragmas</a></td> + </tr> + <tr> + <th>12.7</th><td><a href="#12.7">C++ Compiler Warnings</a> <table class="toc"> - <tr><th>12.6.1</th><td><a href="#12.6.1">GNU C++</a></td></tr> - <tr><th>12.6.2</th><td><a href="#12.6.2">Visual C++</a></td></tr> - <tr><th>12.6.3</th><td><a href="#12.6.3">Sun C++</a></td></tr> - <tr><th>12.6.4</th><td><a href="#12.6.4">IBM XL C++</a></td></tr> - <tr><th>12.6.5</th><td><a href="#12.6.5">HP aC++</a></td></tr> - <tr><th>12.6.6</th><td><a href="#12.6.6">Clang</a></td></tr> + <tr><th>12.7.1</th><td><a href="#12.7.1">GNU C++</a></td></tr> + <tr><th>12.7.2</th><td><a href="#12.7.2">Visual C++</a></td></tr> + <tr><th>12.7.3</th><td><a href="#12.7.3">Sun C++</a></td></tr> + <tr><th>12.7.4</th><td><a href="#12.7.4">IBM XL C++</a></td></tr> + <tr><th>12.7.5</th><td><a href="#12.7.5">HP aC++</a></td></tr> + <tr><th>12.7.6</th><td><a href="#12.7.6">Clang</a></td></tr> </table> </td> </tr> @@ -8045,7 +8048,7 @@ result r (db.query<employee_retirement> ()); words, we may need to combine a constant query expression specified in the <code>db query</code> pragma with the varying expression specified at the query execution time. To allow this, the - <code>db query</code> pragma syntax supports the use of a special + <code>db query</code> pragma syntax supports the use of the special <code>(?)</code> placeholder that indicates the position in the constant query expression where the runtime expression should be inserted. For example:</p> @@ -8869,17 +8872,19 @@ for (bool done (false); !done; ) <p>The <em>qualifier</em> tells the ODB compiler what kind of C++ construct this pragma describes. Valid qualifiers are <code>object</code>, - <code>view</code>, <code>value</code>, <code>member</code>, and - <code>namespace</code>. A pragma with the <code>object</code> - qualifier describes a persistent object type. It tells the ODB - compiler that the C++ class it describes is a persistent class. - Similarly, pragmas with the <code>view</code> qualifier describe + <code>view</code>, <code>value</code>, <code>member</code>, + <code>namespace</code>, and <code>map</code>. A pragma with the + <code>object</code> qualifier describes a persistent object type. It + tells the ODB compiler that the C++ class it describes is a persistent + class. Similarly, pragmas with the <code>view</code> qualifier describe view types, the <code>value</code> qualifier describes value types and the <code>member</code> qualifier is used to describe data members of persistent object, view, and value types. The <code>namespace</code> qualifier is used to describe common properties of objects, views, and value types that belong to - a C++ namespace.</p> + a C++ namespace. The <code>map</code> qualifier describes a + mapping between additional database types and types for + which ODB provides built-in support.</p> <p>The <em>specifier</em> informs the ODB compiler about a particular database-related property of the C++ declaration. For example, the @@ -9010,9 +9015,8 @@ class person --odb-epilogue '#include "person-pragmas.hxx"' </pre> - <p>The following three sections cover the specifiers applicable - to the <code>object</code>, <code>value</code>, and <code>member</code> - qualifiers.</p> + <p>The following sections cover the specifiers applicable to all the + qualifiers mentioned above.</p> <p>The C++ header file that defines our persistent classes and normally contains one or more ODB pragmas is compiled by both @@ -9020,7 +9024,7 @@ class person the C++ compiler to build the application. Some C++ compilers issue warnings about pragmas that they do not recognize. There are several ways to deal with this problem which are covered - at the end of this chapter in <a href="#12.6">Section 12.6, + at the end of this chapter in <a href="#12.7">Section 12.7, "C++ Compiler Warnings"</a>.</p> <h2><a name="12.1">12.1 Object Type Pragmas</a></h2> @@ -11688,7 +11692,202 @@ namespace hr "<code>session</code>"</a>). For more information on sessions, refer to <a href="#10">Chapter 10, "Session"</a>.</p> - <h2><a name="12.6">12.6 C++ Compiler Warnings</a></h2> + <h2><a name="12.6">12.6 Database Type Mapping Pragmas</a></h2> + + <p>A pragma with the <code>map</code> qualifier describes a + mapping between two database types. For each database system + ODB provides built-in support for a core set of database types, + such as integers, strings, binary, etc. However, many database + systems provide additional types such as extensions (geospatial, + key-value stores, etc.), user-defined types, and collections (arrays, + table types, etc). In order to support such additional types, ODB + allows us to map them to one of the built-in types, normally + a string or a binary. Given the text or binary representation + of the data we can then extract it into our chosen C++ data type + and thus establish a mapping between an additional database type and + its C++ equivalent.</p> + + <p>The <code>map</code> pragma has the following format:</p> + +<pre class="cxx"> +#pragma db map type("regex") as("subst") [to("subst")] [from("subst")] +</pre> + + <p>The <code>type</code> clause specifies the name of the database type + that we are mapping. We will refer to it as the <em>mapped type</em> + from now on. The name of the mapped type is a Perl-like regular + expression pattern that is matched in the case-insensitive mode.</p> + + <p>The <code>as</code> clause specifies the name of the database type + that we are mapping the mapped type to. We will refer to it as + the <em>interface type</em> from now on. The name of the interface + type is a regular expression substitution and should expand to a + name of a database type for which ODB provides built-in support.</p> + + <p>The optional <code>to</code> and <code>from</code> clauses specify the + database conversion expressions between the mapped type and the + interface type. The <code>to</code> expression converts from the + interface type to the mapped type and <code>from</code> converts + in the other direction. If no explicit conversion is required for + either direction, then the corresponding clause can be omitted. + The conversion expressions are regular expression substitutions. + They must contain the special <code>(?)</code> placeholder which will + be replaced with the actual value to be converted. Turning on SQL + statement tracing (<a href="#3.12">Section 3.12, "Tracing SQL + Statement Execution"</a>) can be useful for debugging conversion + expressions. This allows you to see the substituted expressions + as used in the actual statements.</p> + + <p>As an example, the following <code>map</code> pragma maps the + PostgreSQL array of <code>INTEGER</code>'s to <code>TEXT</code>:</p> + +<pre class="cxx"> +#pragma db map type("INTEGER *\\[(\\d*)\\]") \ + as("TEXT") \ + to("(?)::INTEGER[$1]") \ + from("(?)::TEXT") +</pre> + + <p>With the above mapping we can now have a persistent class that + has a member of the PostgreSQL array type:</p> + +<pre class="cxx"> +#pragma db object +class object +{ + #pragma db type("INTEGER[]") + std::string array_; +}; +</pre> + + <p>In PostgreSQL the array literal has the <code>{n1,n2,...}</code> form. + As a result, we need to make sure that we pass the correct text + representation in the <code>array_</code> member, for example:</p> + +<pre class="cxx"> +object o; +o.array_ = "{1,2,3}"; +db.persist (o); +</pre> + + <p>Of course, <code>std::string</code> is not the most natural + representation of an array of integers in C++. Instead, + <code>std::vector<int></code> would have been much more + appropriate. To add support for mapping + <code>std::vector<int></code> to PostgreSQL <code>INTEGER[]</code> + we need to provide a <code>value_traits</code> specialization + that implements conversion between the PostgreSQL text representation + of an array and <code>std::vector<int></code>. Below is a sample + implementation:</p> + +<pre class="cxx"> +namespace odb +{ + namespace pgsql + { + template <> + class value_traits<std::vector<int>, id_string> + { + public: + typedef std::vector<int> value_type; + typedef value_type query_type; + typedef details::buffer image_type; + + static void + set_value (value_type& v, + const details::buffer& b, + std::size_t n, + bool is_null) + { + v.clear (); + + if (!is_null) + { + char c; + std::istringstream is (std::string (b.data (), n)); + + is >> c; // '{' + + for (c = static_cast<char> (is.peek ()); c != '}'; is >> c) + { + v.push_back (int ()); + is >> v.back (); + } + } + } + + static void + set_image (details::buffer& b, + std::size_t& n, + bool& is_null, + const value_type& v) + { + is_null = false; + std::ostringstream os; + + os << '{'; + + for (value_type::const_iterator i (v.begin ()), e (v.end ()); + i != e;) + { + os << *i; + + if (++i != e) + os << ','; + } + + os << '}'; + + const std::string& s (os.str ()); + n = s.size (); + + if (n > b.capacity ()) + b.capacity (n); + + std::memcpy (b.data (), s.c_str (), n); + } + }; + } +} +</pre> + + <p>Once this specialization is included in the generated code (see + the <code>mapping</code> example in the <code>odb-examples</code> + package for details), we can use <code>std::vector<int></code> + instead of <code>std::string</code> in our persistent class:</p> + +<pre class="cxx"> +#pragma db object +class object +{ + #pragma db type("INTEGER[]") + std::vector<int> array_; +}; +</pre> + + <p>If we wanted to always map <code>std::vector<int></code> + to PostgreSQL <code>INTEGER[]</code>, then we could instead + write:</p> + +<pre class="cxx"> +typedef std::vector<int> int_vector; +#pragma db value(int_vector) type("INTEGER[]") + +#pragma db object +class object +{ + std::vector<int> array_; // Mapped to INTEGER[]. +}; +</pre> + + <p>While the above example only shows how to handle PostgreSQL arrays, + other types in PostgreSQL and in other databases can be supported + in a similar way. The <code>odb-tests</code> package contains a + set of tests in the <code><database>/custom</code> directories that, + for each database, shows how to provide custom mapping for some of + the additional types.</p> + + <h2><a name="12.7">12.7 C++ Compiler Warnings</a></h2> <p>When a C++ header file defining persistent classes and containing ODB pragmas is used to build the application, the C++ compiler may @@ -11741,7 +11940,7 @@ class person <p>The disadvantage of this approach is that it can quickly become overly verbose when positioned pragmas are used.</p> - <h3><a name="12.6.1">12.6.1 GNU C++</a></h3> + <h3><a name="12.7.1">12.7.1 GNU C++</a></h3> <p>GNU g++ does not issue warnings about unknown pragmas unless requested with the <code>-Wall</code> command line option. @@ -11753,7 +11952,7 @@ class person g++ -Wall -Wno-unknown-pragmas ... </pre> - <h3><a name="12.6.2">12.6.2 Visual C++</a></h3> + <h3><a name="12.7.2">12.7.2 Visual C++</a></h3> <p>Microsoft Visual C++ issues an unknown pragma warning (C4068) at warning level 1 or higher. This means that unless we have disabled @@ -11787,7 +11986,7 @@ class person #pragma warning (pop) </pre> - <h3><a name="12.6.3">12.6.3 Sun C++</a></h3> + <h3><a name="12.7.3">12.7.3 Sun C++</a></h3> <p>The Sun C++ compiler does not issue warnings about unknown pragmas unless the <code>+w</code> or <code>+w2</code> option is specified. @@ -11799,7 +11998,7 @@ class person CC +w -erroff=unknownpragma ... </pre> - <h3><a name="12.6.4">12.6.4 IBM XL C++</a></h3> + <h3><a name="12.7.4">12.7.4 IBM XL C++</a></h3> <p>IBM XL C++ issues an unknown pragma warning (1540-1401) by default. To disable this warning we can add the <code>-qsuppress=1540-1401</code> @@ -11809,7 +12008,7 @@ CC +w -erroff=unknownpragma ... xlC -qsuppress=1540-1401 ... </pre> - <h3><a name="12.6.5">12.6.5 HP aC++</a></h3> + <h3><a name="12.7.5">12.7.5 HP aC++</a></h3> <p>HP aC++ (aCC) issues an unknown pragma warning (2161) by default. To disable this warning we can add the <code>+W2161</code> @@ -11819,7 +12018,7 @@ xlC -qsuppress=1540-1401 ... aCC +W2161 ... </pre> - <h3><a name="12.6.6">12.6.6 Clang</a></h3> + <h3><a name="12.7.6">12.7.6 Clang</a></h3> <p>Clang does not issue warnings about unknown pragmas unless requested with the <code>-Wall</code> command line option. @@ -12076,6 +12275,11 @@ class object }; </pre> + <p>It is also possible to add support for additional MySQL types, + such as geospatial types. For more information, refer to + <a href="#12.6">Section 12.6, "Database Type Mapping + Pragmas"</a>.</p> + <h2><a name="13.2">13.2 MySQL Database Class</a></h2> <p>The MySQL <code>database</code> class has the following @@ -12689,6 +12893,11 @@ class object <code>unsigned long long</code> values will be represented in the database as negative values.</p> + <p>It is also possible to add support for additional SQLite types, + such as <code>NUMERIC</code>. For more information, refer to + <a href="#12.6">Section 12.6, "Database Type Mapping + Pragmas"</a>.</p> + <h2><a name="14.2">14.2 SQLite Database Class</a></h2> <p>The SQLite <code>database</code> class has the following @@ -13442,6 +13651,13 @@ class object the most significant bit of the actual unsigned value being persisted.</p> + <p>It is also possible to add support for additional PostgreSQL types, + such as <code>NUMERIC</code>, geometry types, <code>XML</code>, + <code>JSON</code>, enumeration types, composite types, arrays, + geospatial types, and the key-value store (<code>HSTORE</code>). + For more information, refer to <a href="#12.6">Section 12.6, + "Database Type Mapping Pragmas"</a>.</p> + <h2><a name="15.2">15.2 PostgreSQL Database Class</a></h2> <p>The PostgreSQL <code>database</code> class has the following @@ -14072,6 +14288,12 @@ class object mapped to <code>NUMBER(10)</code> with the default <code>NULL</code> semantics being <code>NOT NULL</code>.</p> + <p>It is also possible to add support for additional Oracle types, + such as <code>XML</code>, geospatial types, user-defined types, + and collections (arrays, table types). For more information, refer to + <a href="#12.6">Section 12.6, "Database Type Mapping + Pragmas"</a>.</p> + <h2><a name="16.2">16.2 Oracle Database Class</a></h2> <p>The Oracle <code>database</code> class encapsulates the OCI environment @@ -14927,6 +15149,11 @@ t.commit (); the value stored by the database for these types will contain the sign bit of the actual signed value being persisted.</p> + <p>It is also possible to add support for additional SQL Server types, + such as geospatial types, <code>XML</code>, and user-defined types. + For more information, refer to <a href="#12.6">Section 12.6, "Database + Type Mapping Pragmas"</a>.</p> + <h2><a name="17.2">17.2 SQL Server Database Class</a></h2> <p>The SQL Server <code>database</code> class encapsulates the ODBC |