pax_global_header00006660000000000000000000000064135470306150014516gustar00rootroot0000000000000052 comment=b66cd6302fe45389b974a530edbacce8572c4c74 tntdb-1.4/000077500000000000000000000000001354703061500124755ustar00rootroot00000000000000tntdb-1.4/.gitignore000066400000000000000000000012241354703061500144640ustar00rootroot00000000000000# Files generated by autoconf, automake and libtool /INSTALL /aclocal.m4 /autom4te.cache /compile /config.guess /config.sub /configure /depcomp /install-sh /ltmain.sh /missing /src/config.h.in /m4/*.m4 !/m4/ax_check_compile_flag.m4 !/m4/ax_compiler_vendor.m4 !/m4/ax_lib_oracle_oci.m4 !/m4/ax_cxx_compile_stdcxx_11.m4 !/m4/acx_pthread.m4 .deps .libs Makefile.in Makefile config.log config.status libtool stamp-h1 # Files generated or compiled in the build process **/demo/select **/demo/modify **/demo/serial **/demo/sqlcmd **/doc/tntdb.doxygen **/include/tntdb/config.h **/src/config.h **/test/tntdb-test *.l[ao] *.o *.pc *.swp # Other .dirstamp *~ tntdb-1.4/AUTHORS000066400000000000000000000001011354703061500135350ustar00rootroot00000000000000Tommi Mäkitalo Mark Write Marc Boris Dürner tntdb-1.4/COPYING000066400000000000000000000575061354703061500135450ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS tntdb-1.4/ChangeLog000066400000000000000000000474221354703061500142600ustar00rootroot000000000000002015-07-20 Tommi Mäkitalo - build library whith multithreading support 2015-07-13 Tommi Mäkitalo - update version number 2015-06-18 Tommi Mäkitalo - reduce log level of some log output - do not install header from demo 2015-06-15 Tommi Mäkitalo - fix leak of statement handles in postgresql driver when using tntdb::Transaction::lockTable - fix crash in postgresql driver when using lastInsertId without sequence name Merge: 7747174 2196fae 2015-06-01 Tommi Mäkitalo - Merge pull request #8 from aggsol/patch-1 Update README - Update README The actual configure option is `--with-replicate` 2015-05-27 Tommi Mäkitalo - fix handling unsigned values in mysql driver 2015-05-20 Tommi Mäkitalo - improve error message in configure when the headers of a database driver could not be found 2015-05-18 Tommi Mäkitalo - add C++11 style begin and end functions to Statement, Result and Row classes 2015-04-23 Tommi Mäkitalo - fix limit and offset handling in oracle driver - add support for limit and offset in sql statements 2015-03-16 Tommi Mäkitalo - minor performance fix: pass std::string by reference (uncovered by cppcheck) 2015-02-01 Tommi Mäkitalo - add include file to dist package Merge: ee56f89 e4c8161 2015-01-23 Tommi Mäkitalo - Merge pull request #7 from ghinadr/master Forward declare class Cursor 2015-01-22 ghinadr - Forward declare class Cursor Class Cursor is referentiated in the Statement class, with the declarator friend. Without the forward declaration of class Cursor, tntdb won't compile on AIX 6.1 2015-01-05 Tommi Mäkitalo - add documentation to tntdb::SqlBuilder 2015-01-04 Tommi Mäkitalo - add support for std::multiset, std::forward_list, std::unordered_set and std::unordered_multimap Merge: 9c0b34f 69bbbb2 2014-12-04 Tommi Mäkitalo - update autoconf macro to check for C++-11 (makes C++-11 flag optional) 2014-11-02 Jonas Platte - Updated .gitignore - Added pkg-config support - Cleaned up configure.ac a bit 2014-10-31 Tommi Mäkitalo - make get methods, which create RowReaders const in Row and Statement::const_iterator 2014-10-28 Tommi Mäkitalo - discard previous http reply on execute if not fully read in http client 2014-10-24 Tommi Mäkitalo - fix typos in tntdb howto 2014-10-14 Tommi Mäkitalo - use c++ 11 mode of compiler if supported for better optimization 2014-09-30 Tommi Mäkitalo - replace some demos with better ones - add helper methods to tntdb::Row and tntdb::Statement::const_iterator to make working with RowReader easier 2014-08-31 Andreas Welchlin - refine documentation 2014-04-15 Jonas Platte - Documentation and style revision for Blob, Connection, Statemnt 2014-04-14 Jonas Platte - Removed all trailing whitespace from source files, documentation + indentation update for the toplevel include directory 2014-03-13 Jonas Platte - Documentation + code style revision: Date, Time, Datetime 2014-08-15 Tommi Mäkitalo - remove cxxtools::NonCopyable class - fix build for oracle driver - pass required oci (oracle) version number correctly 2014-02-22 Tommi Mäkitalo - buildfix: check for postgresql header after setting CPPFLAGS properly 2014-01-22 Tommi Mäkitalo - fix freeing pooled mysql connection when prepareCached is used 2013-11-29 Tommi Mäkitalo - update installation hints 2013-10-03 Tommi Mäkitalo - autoscan.sh is obsolete - use "autoreconf -i" instead 2013-10-01 Tommi Mäkitalo - fix check for unsigned long long 2013-09-21 Tommi Mäkitalo - improve error handling in sqlite driver 2013-07-29 Tommi Mäkitalo - add check for postgresql header availability to configure 2013-07-10 Tommi Mäkitalo - build improvements: * disable static build by default * autodetect oci (oracle call interface) - update build: * autoconf wants configure.ac instead of configure.in * INCLUDE in Makefile.am is obsolete; AM_CPPFLAGS should be used 2013-07-06 Tommi Mäkitalo - add api documentation about the drivers 2013-06-19 Richard Kojedzinszky - Initialize transactionActive in constructor 2013-06-07 Tommi Mäkitalo - add more build instructions into README-SOURCE-REPOS 2013-06-07 Tommi Mäkitalo - set CPPFLAGS instead of CXXFLAGS to set include directory 2013-06-06 Olaf Radicke - Add doku about installation from source repository. 2013-05-10 Tommi Mäkitalo - make oracle connection pool fork safe (don't reuse connections in child process) 2013-05-09 Tommi Mäkitalo - convert documentation to markdown and update it 2013-04-08 tommi@tntnet.org - release candidate 1.3rc3 2013-03-31 tommi@tntnet.org - remove removed m4/acx_pthread.m4 from Makefile.am also - fix compiler warnings - remove pthread checks from tntdb since it is not needed 2013-03-17 tommi@tntnet.org - fix some compiler warnings - set preprocesor flags in CPPFLAGS instead of CXXFLAGS - update version number to 1.3rc2; update ChangeLog 2013-03-16 tommi@tntnet.org - add chapters about business logic, application class and logging to quick start guide - release candidate 1.3rc2 2013-03-11 tommi@tntnet.org - do not use implicit conversion of cxxtools::SmartPtr to raw pointer in oracle driver also 2013-03-03 tommi@tntnet.org - release candidate 1.3rc1 2013-01-18 tommi@tntnet.org - fix table locking in oracle driver 2013-01-17 tommi@tntnet.org - extend locktest program with facility to create read locks - implement lockTable method in tntdb::Transaction - compile with -Wall and -pedantic if compiler supports it 2012-08-15 tommi@tntnet.org - delay deallocation of statements in postgresql during transactions since failed transactions causes deallocation to fail 2012-08-04 tommi@tntnet.org - remove unused variable - pass param format array to PQexecParams correctly when opening cursor in postgresql driver 2012-05-28 tommi@tntnet.org - remove deprecated header cxxtools/loginit.h - add test reading with cursor into unit test 2012-05-26 tommi@tntnet.org - add support for cxxtools::String (unicode string class) 2012-04-16 tommi@tntnet.org - fix fetching blob fields in oracle driver and extend unit test for type for using tntdb::Result - fix fetching datetime and blob fields in oracle driver 2012-04-12 tommi@tntnet.org - use OCI number conversion functions where feasible in oracle driver - optimize oracle driver by fetching multiple values at once (reading larger amounts of data is dramatically faster now) 2012-04-02 tommi@tntnet.org - update version number to 1.2 - remove old debian directory 2012-03-31 tommi@tntnet.org - update ChangeLog and version number - fix tntdb::Decimal for freebsd - fix a special case in conjunction with quotes when parsing sql statements 2012-03-26 tommi@tntnet.org - some fixes concerning new tntdb::Decimal class and optimization in oralce driver (rebind only when needed) 2012-03-25 tommi@tntnet.org - fix mysql driver: mysql_stmt_execute accesses bound data even when it is deleted - add unit tests for basic tntdb functionality - fix setting char, date, time and datetime in mysql 2012-03-15 tommi@tntnet.org - improve support for integer type in Decimal class 2012-03-13 tommi@tntnet.org - new method getInteger in tntdb::Decimal - update oracle driver to new decimal class 2012-03-12 tommi@tntnet.org - fix parsing some decimal numbers and allow leading and trailing white space - avoid possible wrong overflow in decimal class - fixes for decimal parser 2012-03-08 tommi@tntnet.org - remove some constructors from Decimal to reduce abiguity 2012-03-05 tommi@tntnet.org - simplify tntdb::Decimal and make its use more efficient 2012-02-26 tommi@tntnet.org - fix compiler warnings in decimal class and add some unit tests for decimal class 2012-02-25 tommi@tntnet.org - set compile flags for ibm xlc and fix some warnings 2012-02-11 tommi@tntnet.org - set abi version to 3 - add sql scripts for creating test tables into dist package 2012-02-09 tommi@tntnet.org - implement method tntdb::Row::getColumnName(size_type) 2012-02-09 tommi@tntnet.org - fix resetting rowreader - fix some compiler warnings in Decimal class 2012-02-08 tommi@tntnet.org - remove search path from tntdb since people should use LD_LIBRARY_PATH if really needed and prefer that over configured driver directory - better cleanup in tntdb unit test - fix reading floating point number from decimal column in mysql driver 2012-02-05 tommi@tntnet.org - initialize tests correctly - null test did not work as it should have 2012-02-01 tommi@tntnet.org - sort connections in replicate driver to reduce risk of dead locks but still use first connection as primary connection for selects 2011-11-25 tommi@tntnet.org - remove now obsolete method tntdb::Statement::paramlist (replaced by tntdb::SqlBuilder) - add missing return statement into tntdb::SqlBuilder::replaceIf - add else value into tntdb::SqlBuilder::replaceIf - when replication fails in replication driver add the number of the connection, which fails to the exception message - add unit test for tntdb::SqlBuilder - fix replication driver - after last fix statements were executed twice on the first connection 2011-11-24 tommi@tntnet.org - add default constructor and setter for sql builder 2011-11-23 tommi@tntnet.org - add class tntdb::SqlBuilder as a helper for dynamically built sql statements 2011-11-22 tommi@tntnet.org - add support for parameter lists in Statement 2011-11-17 tommi@tntnet.org - Datetime must not have a zero year, month or day in oracle 2011-11-11 tommi@tntnet.org - fix ping in replicate driver - prevent endless retry to create new connections in connectionpool 2011-11-10 tommi@tntnet.org - OCIPing did not work on our oracle server 10.2.0.4.0; replace with OCIServerVersion on oracle before 11 2011-11-04 tommi@tntnet.org - fix out of tree build 2011-09-25 tommi@tntnet.org - fix wrong data type in tntdb::Decimal::getUnsignedShort() - fix build for autoconf 2.68 2011-09-20 tommi@tntnet.org - add missing return statements in replicate driver 2011-09-01 tommi@tntnet.org - add get method for tntdb::Value to RowReader - add rowreader.h to Makefile.am 2011-08-27 tommi@tntnet.org - add documentation for tntdb::RowReader 2011-08-26 tommi@tntnet.org - implement new helper class tntdb::RowReader, which makes it easier to read all values from a row 2011-06-03 tommi@tntnet.org - add support for short and unsigned short 2011-05-06 tommi@tntnet.org - fix reading time with second fractional part >0.9999, which resulted in a invalid time in postgresql driver 2011-04-25 tommi@tntnet.org - add operators for cxxtools::Date, Time and DateTime classes 2011-04-02 tommi@tntnet.org - fix compile problem on BSD (timeval.tv_sec is not of type time_t) 2011-03-24 tommi@tntnet.org - use transacions to make sure replication works also on error on the second db in replication driver 2011-03-22 tommi@tntnet.org - use OCIPing to check if oracle connection is still alive 2011-03-22 tommi@tntnet.org - default to empty string of serial name when retrieving last insert id, which means: get the last inserted id regardless of name 2011-02-27 tommi@tntnet.org - update tntdb to latest cxxtools (svn release 1203 or cxxtools 2.1) 2011-02-21 tommi@tntnet.org - support for nan and inf in postgresql driver 2011-02-21 tommi@tntnet.org - deliver last incremented serial if passed empty string to lastInsertId method in postgresql driver 2011-02-21 tommi@tntnet.org - add replicating driver to tntdb 2011-01-30 tommi@tntnet.org - fix: long was casted to int when set in statement 2011-01-10 tommi@tntnet.org - implement getLong and getUnsignedLong in tntdb::row 2011-01-05 tommi@tntnet.org - add tntdb::BlobIStream: a std::istream interface to tntdb::Blob 2010-11-14 tommi@tntnet.org - do not generate doxygen documentation by default 2010-11-13 tommi@tntnet.org - use async calls when testing connection with ping in postgresql driver to monitor timeout 2010-10-29 tommi@tntnet.org - fix warning in postgresql driver about failed deallocation of statement on close connection when lastInserId was used 2010-10-23 tommi@tntnet.org - statement parser fixes: do not convert type of cast expressions like a::integer into host variable and parse 2 consecutive hostvars correctly 2010-10-06 tommi@tntnet.org - make tntdb::Blob thread safe - the empty instance may be shared between connections in different threads 2010-09-29 tommi@tntnet.org - remove obsolete code for statically bind drivers to tntdb - build driver name from abi_current from configure.in 2010-09-28 tommi@tntnet.org - make tntdb::connect thread safe 2010-09-27 tommi@tntnet.org - bugfix: tntdb::Value::getUnsignedLong should return an unsigned long instead of an unsigned 2010-09-16 tommi@tntnet.org - add logging to transaction class and do not inline it 2010-09-08 tommi@tntnet.org - add convenience method tntdb::Statement::setIf to set to a value or null depending on a bool 2010-08-11 tommi@tntnet.org - unify handling of nested transactions (ignore nested transactions like oracle driver did it already) 2010-08-01 tommi@tntnet.org - release 1.1 2010-03-25 adi - error for decimal number < 1 fixed 2010-02-16 tommi@tntnet.org - tntdb::Statement::setLong and setUnsignedLong - add unittest - add relational operators to tntdb::Decimal 2010-02-13 tommi@tntnet.org - add support for auto-incremented values with new method tntdb::Connection::lastInsertId(std::string) - new methods getLong and getUnsignedLong in tntdb::Value 2010-02-11 tommi@tntnet.org - add template method tntdb::Value::get(T&) 2010-02-09 tommi@tntnet.org - remove automatic conversion operators from tntdb::Value - add an extendable system for retrieving and setting values by overriding 2 operators 2010-02-06 tommi@tntnet.org - let the user specify a short key for statement cache in prepareCached - add getValue-methods to tntdb::Row, which returns the data to variables, passed by reference 2009-12-31 tommi@tntnet.org - replace obsolete cxxtools::Dynbuffer with std::vector 2009-12-14 tommi@tntnet.org - add method tntdb::Value::getValue 2009-12-12 tommi@tntnet.org - check if int and int32_t and others are distinct types 2009-09-09 tommi@tntnet.org - extend syntax of connection string in mysql driver: - allow values to be enclosed in single or double quotes - escape special characters in values with backslash - allow whitespace as delimiter - check for duplicate keys in connection string - add key "app" with a default "tntdb" and use my.cnf with this section 2009-06-29 tommi@tntnet.org - clean up of oracle connection in proper order 2009-06-29 tommi@tntnet.org - close oracle connection correctly 2009-06-16 tommi@tntnet.org - fix sporadic error in string to number conversion in oracle driver 2009-05-15 tommi@tntnet.org - clear statement cache at transaction end with sqlite since statement handles are invalidated 2008-12-18 tommi@tntnet.org - fix error in oracle driver when shutting down the connection after ping 2008-12-05 tommi@tntnet.org - bump so number - simplify cxxtools configuration 2008-12-05 tommi@tntnet.org - fix crash in sqlite driver in Connection::execute 2008-12-05 tommi@tntnet.org - fix driver loading (was broken after cxxtools update) 2008-11-28 tommi@tntnet.org - wrong exception was caught for not found driver libraries 2008-11-28 tommi@tntnet.org - cache ping statement handle in oracle driver 2008-11-21 tommi@tntnet.org - throw NullValue-excpetion, when a null-column is read in a postgresql result set 2008-11-15 tommi@tntnet.org - use fetchsize hint of statement in mysql driver 2008-11-15 tommi@tntnet.org - fix getWDay of date class 2008-07-04 tommi@tntnet.org - remove aix specific handling 2008-07-01 tommi@tntnet.org - fix linkflags for aix 6 2008-07-01 tommi@tntnet.org - support for aix version > 5 2008-07-01 tommi@tntnet.org - don't use ORACLE_HOME to find oracle includes and libraries, since we cannot know, which library the user needs to link (lib or lib32 or whatever) 2008-06-30 tommi@tntnet.org - slightly improved date and time classes 2008-06-07 tommi@tntnet.org - fix Statement::setBool in postgresql driver 2008-06-03 tommi@tntnet.org - release version 1.0.1 2008-06-02 tommi@tntnet.org - fix crash when creating 2 cursors for one statement and destroying in different order 2008-05-30 tommi@tntnet.org - fix string handling in sqlite-driver 2008-02-16 tommi@tntnet.org - version 1.0.0 2008-02-13 tommi@tntnet.org - Blob class (Marc) 2007-11-14 tommi@tntnet.org - get values by column name 2007-10-07 tommi@tntnet.org - replace tntdb::SmartPtr with cxxtools::SmartPtr 2007-09-27 tommi@tntnet.org - build improvements for AIX 2007-09-21 tommi@tntnet.org - support for decimals and 32/64-bit integers (from Mark Wright) 2007-06-08 tommi@tntnet.org - bugfix: tntdb crashed, when iterating over a statement which returns no rows 2007-05-23 tommi@tntnet.org - driver for oracle - support for MEDIUMINT in mysql-driver 2007-05-11 tommi@tntnet.org - fix connectionpool 2007-03-27 tommi@tntnet.org - tntdb::Connection::ping to check, if the connection is alive - use that ping in connectionpool before returning connection - tntdb::setMaxPoolSize(unsingned) and tntdb::getMaxPoolSize() 2007-02-20 tommi@tntnet.org - fix leak: the statement-cursor is not freed, when the first fetch was not successful 2006-10-21 tommi@tntnet.org - add fetchsize-parameter (with default 100) to tntdb::Statement::begin to pass a hint to the implementing cursor 2006-10-12 tommi@tntnet.org - don't inline constructors of error-classes to help compiler matching the right type in catch-block (a problem with gcc 4.1 at least) 2006-10-07 tommi@tntnet.org - add getDate-, getTime- and getDatetime-methods to tntdb::Row 2006-09-20 tommi@tntnet.org - fix cached prepared statements in sqlite: reset before reuse 2006-09-11 tommi@tntnet.org - fix handling of binary data in sqlite3-driver - move drivers to separate directory specified in configure with "--with-driverdir=..." 2006-08-25 tommi@tntnet.org - fix smartpointer to support self-assignment 2006-08-24 tommi@tntnet.org - change license to LGPL 2006-07-21 tommi@tntnet.org - extend license to allow linking with openssl due to postgresql 2006-04-12 tommi@tntnet.org - fix mysql-driver-bug: crashed when fetching some datatypes, because the api seems to return too small length-values (or I misunderstand the api;-) ) 2006-03-27 tommi@tntnet.org - allow date-, datetime- and time-classes to be null, when passed to statements 2006-03-01 tommi@tntnet.org - declare cursor in postgresql with hold to enable cursor outside transactions 2006-02-13 tommi@tntnet.org - new method Statement::clear() 2006-01-21 tommi@tntnet.org - connectionpool 2006-01-13 tommi@tntnet.org - add missing include/tntdb/sqlite/impl/connectionmanager.h 2005-12-26 tommi@tntnet.org - new Sqlite-driver 2005-11-12 tommi@tntnet.org - use PQexec with PREPARE when PQprepare is not found (postgresql prior 8.0) 2005-11-11 tommi@tntnet.org - make drivers for mysql and postgresql optional in configure 2005-10-26 tommi@tntnet.org - fixed handling of MYSQL_TYPE_LONGLONG tntdb-1.4/Makefile.am000066400000000000000000000004341354703061500145320ustar00rootroot00000000000000ACLOCAL_AMFLAGS = -I m4 SUBDIRS = \ src \ src/mysql \ src/postgresql \ src/replicate \ src/sqlite \ src/oracle \ include \ demo \ test \ doc EXTRA_DIST = \ COPYING pkgconfigdir = $(libdir)/pkgconfig/ pkgconfig_DATA = pkgconfig/tntdb.pc tntdb-1.4/NEWS000066400000000000000000000000001354703061500131620ustar00rootroot00000000000000tntdb-1.4/README000066400000000000000000000042761354703061500133660ustar00rootroot00000000000000Tntdb ===== Tntdb is a c++-class-library for easy access to databases. The interface is database-independent. Driverclasses are loaded dynamically. The goal is to have easy access to databases. You don't have to worry about resourceleakage, because all objects you use directly are allocated on the stack and deleted automatically, when going out of scope. The interfaceobjects are wrappers to referencecounted instances, so you can copy them around at your own will. Resources are freed, when the last object goes out of scope. Errorhandling is done exclusively with exceptionhandling. Just wrap your code with a single try-catch and you have full errorhandling. All exceptions are derived from std::exception. STL is used where possible and also STL-like and -compatible interfaces are offered, where suitable. Tntdb is targeted for application programming. It is not suitable for generic databasetools. It does not offer e.g. schemaquery. You have to know, how your tables look like. Thats true for normal applications. You use SQL for databaseaccess. No wrapperclasses like active resultsets or databound controls are offered. Instead you have best control over the database. You can use every SQL-trick you know to get most out of your database. Also this is a thin wrapper, so that you should have no big performancepenalty compared to direct access to the C-API. The project started already some years ago as a postgresql-wrapper. Later I added a sqlite-3-wrapper. The public headers include documentation, which can be generated using Doxygen. Also there are some small examples in the demo-directory. Installation ============ To install tntdb, you need cxxtools (http://www.tntnet.org/). This version needs at least cxxtools version 1.4 You can find generic installation instructions in the file INSTALL. To disable SQLite support (enabled by default) do ./configure --with-sqlite=no To disable MySQL support (enabled by default) do ./configure --with-mysql=no To disable Postgresql support (enabled by default) do ./configure --with-postgresql=no To disable replication driver (enabled by default) do ./configure --with-replicate=no To enable Oracle-support (disabled by default) do ./configure --with-oracle tntdb-1.4/README.git000066400000000000000000000012441354703061500141400ustar00rootroot00000000000000Installation from git ===================== In the git repository there is no configure-script, but configure.ac, which is the source for configure. You need autoconf, automake and libtool to create configure. Run `autoreconf -i` to generate a configure script. To disable SQLite support (enabled by default) do ./configure --with-sqlite=no To disable MySQL support (enabled by default) do ./configure --with-mysql=no To disable Postgresql support (enabled by default) do ./configure --with-postgresql=no To disable replication driver (enabled by default) do ./configure --with-replication=no To enable Oracle-support (disabled by default) do ./configure --with-oracle tntdb-1.4/configure.ac000066400000000000000000000170441354703061500147710ustar00rootroot00000000000000AC_INIT(tntdb, 1.4, [Tommi Maekitalo ]) AM_INIT_AUTOMAKE LT_INIT([disable-static]) abi_current=5 abi_revision=0 abi_age=0 sonumber=${abi_current}:${abi_revision}:${abi_age} AC_SUBST(sonumber) AC_SUBST(abi_current) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_HEADERS([src/config.h]) AC_CONFIG_FILES([include/tntdb/config.h]) AC_CONFIG_SRCDIR([src/connect.cpp]) AC_PROG_CXX AC_LANG(C++) AX_CXX_COMPILE_STDCXX_11(noext, optional) ACX_PTHREAD CC="$PTHREAD_CC" CXX="$PTHREAD_CXX" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" CXXFLAGS="$CXXFLAGS $PTHREAD_CXXFLAGS" LIBS="$LIBS $PTHREAD_LIBS" AX_COMPILER_VENDOR AS_IF([test "$ax_cv_cxx_compiler_vendor" = "ibm"], [CPPFLAGS="$CPPFLAGS -qrtti -qlanglvl=newexcp -D__NOLOCK_ON_INPUT -D__NOLOCK_ON_OUTPUT"], AX_CHECK_COMPILE_FLAG([-Wno-long-long], [CPPFLAGS="$CPPFLAGS -Wno-long-long"]) AX_CHECK_COMPILE_FLAG([-Wall], [CPPFLAGS="$CPPFLAGS -Wall"]) AX_CHECK_COMPILE_FLAG([-pedantic], [CPPFLAGS="$CPPFLAGS -pedantic"])) AC_MSG_CHECKING([for sighandler_t]) AC_COMPILE_IFELSE( [AC_LANG_SOURCE([ #include sighandler_t *f;])], has_sighandler_t=yes,has_sighandler_t=no) AC_MSG_RESULT($has_sighandler_t) AS_IF([test "$has_sighandler_t" = "yes"], [AC_DEFINE( HAVE_SIGHANDLER_T, 1, [Define if sighandler_t available] )]) # # check standard integer types # AC_TYPE_LONG_LONG_INT AS_IF( [test "$ac_cv_type_long_long_int" = yes], [HAVE_LONG_LONG=HAVE_LONG_LONG], [HAVE_LONG_LONG=NO_LONG_LONG]) AC_SUBST(HAVE_LONG_LONG, "$HAVE_LONG_LONG") AC_TYPE_UNSIGNED_LONG_LONG_INT AS_IF( [test "$ac_cv_type_unsigned_long_long_int" = yes], [HAVE_UNSIGNED_LONG_LONG=HAVE_UNSIGNED_LONG_LONG], [HAVE_UNSIGNED_LONG_LONG=NO_UNSIGNED_LONG_LONG]) AC_SUBST(HAVE_UNSIGNED_LONG_LONG, "$HAVE_UNSIGNED_LONG_LONG") AC_COMPILE_IFELSE( [AC_LANG_SOURCE([ #include void foo(int) {} void foo(long) {} void foo(int32_t) {} ])], INT_INT32_T_CONFLICT=0, INT_INT32_T_CONFLICT=1) AC_SUBST(INT_INT32_T_CONFLICT) AC_COMPILE_IFELSE( [AC_LANG_SOURCE([ #include void foo(unsigned) {} void foo(unsigned long) {} void foo(uint32_t) {} ])], UNSIGNED_UINT32_T_CONFLICT=0, UNSIGNED_UINT32_T_CONFLICT=1) AC_SUBST(UNSIGNED_UINT32_T_CONFLICT) AC_COMPILE_IFELSE( [AC_LANG_SOURCE([ #include void foo(int) {} void foo(long) {} void foo(int64_t) {} ])], INT_INT64_T_CONFLICT=0, INT_INT64_T_CONFLICT=1) AC_SUBST(INT_INT64_T_CONFLICT) AC_COMPILE_IFELSE( [AC_LANG_SOURCE([ #include void foo(unsigned) {} void foo(unsigned long) {} void foo(uint64_t) {} ])], UNSIGNED_UINT64_T_CONFLICT=0, UNSIGNED_UINT64_T_CONFLICT=1) AC_SUBST(UNSIGNED_UINT64_T_CONFLICT) # # Cxxtools # AC_CHECK_HEADER([cxxtools/condition.h], , AC_MSG_ERROR([cxxtools headers not found])) LDFLAGS="$LDFLAGS -lcxxtools" # # Postgresql # AC_ARG_WITH( [postgresql], AS_HELP_STRING([--with-postgresql], [build postgresql driver (default: yes)]), [with_postgresql=$withval], [with_postgresql=yes]) AS_IF([test "$with_postgresql" = yes], [ AC_CHECK_PROG(PG_CONFIG, [pg_config], [pg_config]) if test -z "$PG_CONFIG"; then AC_MSG_ERROR([postgresql configuration script pg_config was not found; install postgresql developent package or use --without-postgresql]) fi PG_CPPFLAGS=-I`$PG_CONFIG --includedir` PG_LDFLAGS="-L`$PG_CONFIG --libdir` -lpq" AC_SUBST(PG_CONFIG) AC_SUBST(PG_CPPFLAGS) AC_SUBST(PG_LDFLAGS) save_CPPFLAGS=$CPPFLAGS CPPFLAGS="$CPPFLAGS $PG_CPPFLAGS" AC_CHECK_HEADER([libpq-fe.h], , AC_MSG_ERROR([postgresql headers not found])) AC_MSG_CHECKING([for PQprepare in libpq-fe.h]) AC_COMPILE_IFELSE( [AC_LANG_SOURCE([#include void t() { PQprepare(0, 0, 0, 0, 0); }])], [AC_DEFINE(HAVE_PQPREPARE, 1, [Defined if postgresql supports PQprepare]) AC_MSG_RESULT(yes) ], AC_MSG_RESULT(no)) CPPFLAGS=$save_CPPFLAGS ]) AM_CONDITIONAL(MAKE_POSTGRESQL, test "$with_postgresql" = yes) # # mysql # AC_ARG_WITH( [mysql], AS_HELP_STRING([--with-mysql], [build mysql driver (default: yes)]), [ with_mysql=$withval ], [ with_mysql=yes ]) AS_IF([test "$with_mysql" = yes], [ AC_CHECK_PROG(MYSQL_CONFIG, mysql_config, mysql_config) if test -z "$MYSQL_CONFIG"; then AC_MSG_ERROR([mysql configuration script was not found; install mysql developent package or use --without-mysql]) fi MYSQL_CFLAGS=`$MYSQL_CONFIG --cflags` MYSQL_LDFLAGS=`$MYSQL_CONFIG --libs_r` AC_SUBST(MYSQL_CONFIG) AC_SUBST(MYSQL_CFLAGS) AC_SUBST(MYSQL_LDFLAGS) ]) AM_CONDITIONAL(MAKE_MYSQL, test "$with_mysql" = yes) # # Sqlite # AC_ARG_WITH( [sqlite], AS_HELP_STRING([--with-sqlite], [build sqlite driver (default: yes)]), [with_sqlite=$withval], [with_sqlite=yes]) AS_IF([test "$with_sqlite" = yes], [ AC_CHECK_HEADER([sqlite3.h], , AC_MSG_ERROR([header for sqlite3 not found; install sqlite developent package or use --without-sqlite])) # check for sqlite3_transfer_bindings AC_MSG_CHECKING([for sqlite3_transfer_bindings]) AC_COMPILE_IFELSE( [AC_LANG_SOURCE([#include void t() { sqlite3_transfer_bindings(0, 0); }])], [AC_MSG_RESULT(yes)], [AC_MSG_ERROR([sqlite3_transfer_bindings is missing])]) # check for sqlite3_prepare_v2 AC_MSG_CHECKING([for sqlite3_prepare_v2]) AC_COMPILE_IFELSE( [AC_LANG_SOURCE([#include void t() { sqlite3_prepare_v2(0, 0, 0, 0, 0); }])], [AC_DEFINE(HAVE_SQLITE3_PREPARE_V2, 1, [Defined if sqlite have sqlite3_prepare_v2]) AC_MSG_RESULT(yes) ], AC_MSG_RESULT(no)) ]) AM_CONDITIONAL(MAKE_SQLITE, test "$with_sqlite" = yes) # # Oracle # AC_ARG_WITH( [oracle], AS_HELP_STRING([--with-oracle], [build oracle-driver (default: no)]), [with_oracle=$withval], [with_oracle=no]) if test "$with_oracle" = yes then AC_CHECK_HEADER([oci.h], , AC_MSG_ERROR([header for oracle not found])) ORACLE_OCI_LDFLAGS=-lclntsh AC_SUBST(ORACLE_OCI_LDFLAGS) fi AM_CONDITIONAL(MAKE_ORACLE, test "$with_oracle" = yes) # # Replicate # AC_ARG_WITH( [replicate], AS_HELP_STRING([--with-replicate], [build replicate driver (default: yes)]), [with_replicate=$withval], [with_replicate=yes]) AM_CONDITIONAL(MAKE_REPLICATE, test "$with_replicate" = yes) # # Doxygen-documentation # AC_ARG_VAR(DOXYGEN, [doxygen documentation generator]) AC_ARG_WITH( [doxygen], AS_HELP_STRING([--with-doxygen], [generate doxygen documentation]), [doxygenFlag=$withval], [doxygenFlag=no]) AS_IF([test "$doxygenFlag" != "no"], [ AC_CHECK_PROG(DOXYGEN, doxygen, doxygen) if test "$DOXYGEN" == "" then AC_MSG_ERROR([doxygen not found]) fi AC_DEFINE(WITH_DOXYGEN, 1, [build doxygen documentation]) ]) AM_CONDITIONAL(MAKE_DOXYGEN, test "$doxygenFlag" != "no") AC_SUBST(DOXYGEN) # driverlibdir AC_ARG_WITH( [driverdir], AS_HELP_STRING([--with-driverdir=dir], [specify directory for driver files [[LIBDIR/tntdb]] ]), [driverdir=$withval], [driverdir=$libdir/tntdb]) AC_SUBST(driverdir) AS_IF([test "$driverdir" == "yes"], [driverdir=$libdir/tntdb]) # additional shared library checks case "${host_cpu}-${host_os}" in *-aix*) SHARED_LIB_FLAG=-qmkshrobj ;; *) SHARED_LIB_FLAG= ;; esac AC_SUBST(SHARED_LIB_FLAG) AC_CONFIG_FILES([ Makefile doc/Makefile doc/tntdb.doxygen demo/Makefile include/Makefile pkgconfig/tntdb.pc src/Makefile src/mysql/Makefile src/postgresql/Makefile src/replicate/Makefile src/sqlite/Makefile src/oracle/Makefile test/Makefile ]) AC_OUTPUT tntdb-1.4/demo/000077500000000000000000000000001354703061500134215ustar00rootroot00000000000000tntdb-1.4/demo/Makefile.am000066400000000000000000000006561354703061500154640ustar00rootroot00000000000000noinst_PROGRAMS = select modify serial sqlcmd csvoutput serialize deserialize noinst_HEADERS = \ util.h select_SOURCES = select.cpp modify_SOURCES = modify.cpp serial_SOURCES = serial.cpp sqlcmd_SOURCES = sqlcmd.cpp csvoutput_SOURCES = csvoutput.cpp serialize_SOURCES = serialize.cpp deserialize_SOURCES = deserialize.cpp AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include LDADD = $(top_builddir)/src/libtntdb.la tntdb-1.4/demo/README-serialization000066400000000000000000000036221354703061500171570ustar00rootroot00000000000000Serialization with tntdb ======================== Tntdb supports the serialization framework of cxxtools. This makes it easy to write objects into the database and read them back. Typically applications has business objects, which describes the entities of the application. When writing serialization and deserialization operators in cxxtools the objects can be easily converted to various formats and back to objects, e.g. json or xml. Also they can be easily transfered via rpc to another process wich may be on a different host. With the serialization support of tntdb the very same serialization operators are used to store the objects in the database or read back. See the demos `serialize.cpp`, `deserialize.cpp` and `csvoutput.cpp` to see how. To try the demos, create a database using demodb.sql. The easies way is to use sqlite: sqlite3 test.db are proper operators for converting tntdb::Value, tntdb::Row, tntdb::Result or tntdb::Statement to a cxxtools::SerializationInfo, which is needed to use the serialization of cxxtools. By default the csv serializer is used but also json and xml output are implemented. Note that reading a tntdb::Statements executes the sql when iterating through the result. */ #include #include #include #include #include #include #include #include #include int main(int argc, char* argv[]) { try { log_init(); // Logging should be initialized always; reads log.xml or log.properties to configure logging // parse command line switches -j and -x cxxtools::Arg json(argc, argv, 'j'); cxxtools::Arg xml(argc, argv, 'x'); if (argc <= 2) { std::cerr << "Usage: " << argv[0] << " [options] dburl \"select statement\"\n" "Outputs the results of a select statement as csv or other format\n" "\n" "options:\n" " -j output as json\n" " -x output as xml\n" "\n" "e.g.: " << argv[0] << " sqlite:mydata.db \"select * from foo\"\n"; return -1; } // connect to database std::string database = argv[1]; tntdb::Connection db = tntdb::connect(database); // prepare statement std::string selectStmt = argv[2]; tntdb::Statement stmt = db.prepare(selectStmt); // output in requested format // // The functions cxxtools::Json, cxxtools::xml::Xml and cxxtools::Csv return // a object, which has a output operator, which outputs the data // to the requeste format. To extract the data, the deserialization operator // defined in are used to convert the database output // to a cxxtools::SerializationInfo, which is used to generate the output. // if (json) { std::cout << cxxtools::Json(stmt).beautify(true); } else if (xml) { std::cout << cxxtools::xml::Xml(stmt, "db").beautify(true); } else { std::cout << cxxtools::Csv(stmt); } } catch (const std::exception& e) { std::cerr << e.what() << std::endl; } } tntdb-1.4/demo/demodb.sql000066400000000000000000000001611354703061500153720ustar00rootroot00000000000000create table myobjects ( id serial not null primary key, a int not null, b varchar(64) not null ); tntdb-1.4/demo/deserialize.cpp000066400000000000000000000056621354703061500164360ustar00rootroot00000000000000/* * Copyright (C) 2015 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include struct MyObject { unsigned id; int a; std::string b; }; void operator>>= (const cxxtools::SerializationInfo& si, MyObject& obj) { si.getMember("id") >>= obj.id; si.getMember("a") >>= obj.a; si.getMember("b") >>= obj.b; } int main(int argc, char* argv[]) { try { log_init(); // Logging should be initialized always; reads log.xml or log.properties to configure logging if (argc <= 1) { std::cerr << "Usage: " << argv[0] << " dburl\n"; return -1; } // connect to database std::string database = argv[1]; tntdb::Connection db = tntdb::connect(database); tntdb::Statement sel = db.prepare( "select id, a, b" " from myobjects"); for (tntdb::Statement::const_iterator it = sel.begin(); it != sel.end(); ++it) { // create empty object MyObject obj; // *it returns a tntdb::Row with the result // The operator >>= uses the deserialization operator of MyObject to extract // the data. The names of the columns must match the members defined in the // deserialization operator. *it >>= obj; // output the data std::cout << "id=" << obj.id << " a=" << obj.a << " b=\"" << obj.b << "\"\n"; } } catch (const std::exception& e) { std::cerr << e.what() << std::endl; } } tntdb-1.4/demo/modify.cpp000066400000000000000000000063711354703061500154230ustar00rootroot00000000000000/* * Copyright (C) 2014 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* This demonstrates how to modify data in a database with tntdb. */ #include #include #include #include #include int main(int argc, char* argv[]) { try { log_init(); // logging should be initialized always if (argc < 2) { std::cerr << "Usage: " << argv[0] << " dburl" << std::endl; return -1; } const std::string database = argv[1]; tntdb::Connection db = tntdb::connect(database); // insert tntdb::Statement ins = db.prepare("insert into foo(a, b)" " values (:a, :b)"); ins.set("a", 42) .set("b", "Hi there") .execute(); // update tntdb::Statement upd = db.prepare("update foo" " set b = :b" " where a = :a"); upd.set("a", 42) .set("b", "Hello") .execute(); // delete tntdb::Statement del = db.prepare("delete from foo" " where a = :a"); upd.set("a", 42) .execute(); // using a transaction { // We define the transaction object in a scope. // // The transaction will be rolled back automatically in case the // end of the block is reached and no commit or rollback is called. // This happens typically when a exception is thrown. // // Note that when the rollback fails in the destructor errors are lost. tntdb::Transaction transaction(db); tntdb::Statement ins = db.prepare("insert into foo(a, b)" " values (:a, :b)"); ins.set("a", 42) .set("b", "Hi there") .execute(); ins.set("a", 43) .set("b", "Hello") .execute(); transaction.commit(); } } catch (const std::exception& e) { std::cerr << e.what() << std::endl; } } tntdb-1.4/demo/multiparam.cpp000066400000000000000000000052331354703061500163030ustar00rootroot00000000000000/* * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include int main(int argc, char* argv[]) { try { log_init(); tntdb::Connection conn = tntdb::connectCached("sqlite:mydb.db"); std::vector v; v.push_back(5); v.push_back(2); std::set w; tntdb::Statement stmt = conn.prepare( tntdb::SqlBuilder("select a from %table where a in (%v) or b in (%w) and z = :z %q1 %q2") .extendParam("v", v.size()) .extendParam("w", w.size()) .replace("table", mytable) .replaceIf(condition1, "q1", "and z > :z") .replaceIf(condition2, "q2", "and y > :y") ); stmt.set("v", v); stmt.set("w", w); if (condition1) stmt.set("z", 5); if (condition2) stmt.set("y", 18); for (tntdb::Statement::const_iterator cur = stmt.begin(); cur != stmt.end(); ++cur) { int vv; (*cur)[0].get(vv); std::cout << vv << '\t'; } std::cout << std::endl; } catch (const std::exception& e) { std::cerr << "failed: " << e.what() << std::endl; } } tntdb-1.4/demo/select.cpp000066400000000000000000000124401354703061500154050ustar00rootroot00000000000000/* * Copyright (C) 2014 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* This demonstrates the various ways to read data from a database with tntdb. */ #include #include #include #include #include #include #include int main(int argc, char* argv[]) { try { log_init(); // logging should be initialized always if (argc < 2) { std::cerr << "Usage: " << argv[0] << " dburl" << std::endl; return -1; } const std::string database = argv[1]; tntdb::Connection db = tntdb::connect(database); // selecting a single value unsigned count; db.selectValue("select count(*)" " from foo") // returns a tntdb::Value .get(count); // extracts unsigned value from tntdb::Value // selecting multiple values unsigned max, min; tntdb::Row row = db.selectRow("select max(a) as max, min(a) as min" " from foo"); row["max"].get(max); row["min"].get(min); // reading multiple values from a row with tntdb::RowReader db.selectRow("select max(a), min(a)" " from foo") // returns a tntdb::Row .get(max) // extracts unsigned and returns a tntdb::RowReader .get(min); // reading a result set // Note that a tntdb::Result helds the whole result in memory, which may not be what you want. // Use tntdb::Statement to fetch step by step. tntdb::Result result = db.select("select a, b" " from foo"); for (tntdb::Result::const_iterator it = result.begin(); it != result.end(); ++it) { tntdb::Row r = *it; // dereferencing returns a tntdb::Row unsigned a; std::string b; bool a_isnull = r["a"].get(a); // get returns a boolean wether the value was null bool b_isnull = r["b"].get(b); // as an alternative we can use index r[0].get(a); r[1].get(b); // or again tntdb::RowReader r.get(a) .get(b); // a or b may be null: r.get(a, a_isnull) .get(b, b_isnull); } // using tntdb::Statement // fetching value db.prepare("select count(*)" " from foo" " where a > :a") // returns tntdb::Statement .set("a", 42) // sets :a to a value .selectValue() // returns a tntdb::Value .get(count); // extracts unsigned value from tntdb::Value // fetching multiple values row = db.prepare("select max(a) as max, min(a) as min" " from foo" " where a > :a") .set("a", 42) .selectRow(); row["max"].get(max); row["min"].get(min); // reading multiple values from a row with tntdb::RowReader db.prepare("select max(a), min(a)" " from foo" " where a > :a") .set("a", 42) // sets :a to a value .selectRow() .get(max) // extracts unsigned and returns a tntdb::RowReader .get(min); // reading data step by step tntdb::Statement stmt = db.prepare("select a, b" " from foo" " where a > :a"); stmt.set("a", 42); for (tntdb::Statement::const_iterator it = stmt.begin(); it != stmt.end(); ++it) { tntdb::Row r = *it; // dereferencing returns a tntdb::Row unsigned a; std::string b; // the row can be read just like in tntdb::Result bool a_isnull = r["a"].get(a); // get returns a boolean wether the value was null bool b_isnull = r["b"].get(b); // the iterator can also return a RowReader it.get(a, a_isnull) .get(b, b_isnull); } } catch (const std::exception& e) { std::cerr << e.what() << std::endl; } } tntdb-1.4/demo/serial.cpp000066400000000000000000000041511354703061500154050ustar00rootroot00000000000000/* * Copyright (C) 2009 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include int main(int argc, char* argv[]) { try { cxxtools::Arg dburl(argc, argv, "--dburl", "sqlite:test.db"); tntdb::Connection conn = tntdb::connect(dburl); /** assume: create table foo ( a serial not null primary key, b integer not null ); */ tntdb::Statement ins = conn.prepare("insert into foo (b) values (:b)"); ins.set("b", 7).execute(); std::cout << "serial=" << conn.lastInsertId("foo_seq") << std::endl; ins.set("b", 10).execute(); std::cout << "serial=" << conn.lastInsertId("foo_seq") << std::endl; } catch (const std::exception& e) { std::cerr << e.what() << std::endl; } } tntdb-1.4/demo/serialize.cpp000066400000000000000000000054661354703061500161270ustar00rootroot00000000000000/* * Copyright (C) 2015 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include struct MyObject { unsigned id; int a; std::string b; }; void operator<<= (cxxtools::SerializationInfo& si, const MyObject& obj) { si.addMember("id") <<= obj.id; si.addMember("a") <<= obj.a; si.addMember("b") <<= obj.b; } int main(int argc, char* argv[]) { try { log_init(); // Logging should be initialized always; reads log.xml or log.properties to configure logging if (argc <= 1) { std::cerr << "Usage: " << argv[0] << " dburl\n"; return -1; } // connect to database std::string database = argv[1]; tntdb::Connection db = tntdb::connect(database); tntdb::Statement ins = db.prepare( "insert into myobjects(id, a, b)" " values (:id, :a, :b)"); // create a object and fill with some data MyObject obj; obj.id = 42; obj.a = 1; obj.b = "Hello"; // the operator<<= for tntdb::Statement and MyObject uses the serialization // operator for MyObject to set the variables in statement with the members // of MyObject. The variable names in the statement must match the members // in the serialization operator. ins.set(obj) .execute(); } catch (const std::exception& e) { std::cerr << e.what() << std::endl; } } tntdb-1.4/demo/sqlcmd.cpp000066400000000000000000000075271354703061500154230ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include "util.h" int main(int argc, char* argv[]) { try { cxxtools::Arg value(argc, argv, 'v'); cxxtools::Arg row(argc, argv, 'r'); cxxtools::Arg exec(argc, argv, 'e'); cxxtools::Arg statement(argc, argv, 'p'); cxxtools::Arg cursor(argc, argv, 'c'); log_init(); if (argc < 2) { std::cerr << "This is sqlcmd - a commandline-sql-processor. It demonstrates the use of tntdb.\n\n" "Usage:\n" " sqlcmd [options] db-url [sql-query]\n\n" "Options:\n" " -e execute statement without result\n" " -v select value\n" " -r select row\n" " -p select with prepared statement\n" " -c select with cursor\n" "When no sql-query is passed, sqlcmd reads a sql-query from standard-input.\n" << std::endl; return -1; } const std::string database = argv[1]; std::string cmd; if (argc > 2) cmd = argv[2]; else { // read sql-command from stdin std::ostringstream s; s << std::cin.rdbuf(); // copy stdin to buffer cmd = s.str(); } tntdb::Connection conn = tntdb::connect(database); if (exec) { std::cout << "exec" << std::endl; conn.execute(cmd); } else if (value) { tntdb::Value v = conn.selectValue(cmd); ValuePrinter()(v); std::cout << std::endl; } else if (row) { tntdb::Row t = conn.selectRow(cmd); RowPrinter()(t); } else if (statement) { tntdb::Statement stmt = conn.prepare(cmd); tntdb::Result r = stmt.select(); std::for_each(r.begin(), r.end(), RowPrinter()); } else if (cursor) { // postgresql needs a active transaction for cursors tntdb::Transaction trans(conn); tntdb::Statement stmt = conn.prepare(cmd); std::for_each(stmt.begin(), stmt.end(), RowPrinter()); } else { tntdb::Result r = conn.select(cmd); std::for_each(r.begin(), r.end(), RowPrinter()); } } catch (const std::exception& e) { std::cerr << "ERROR: " << e.what() << std::endl; } } tntdb-1.4/demo/util.h000066400000000000000000000047021354703061500145520ustar00rootroot00000000000000/* * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ //////////////////////////////////////////////////////////////////////// // util.h // #ifndef UTIL_H #define UTIL_H #include #include #include #include class ValuePrinter { std::ostream& out; char delimiter; public: explicit ValuePrinter(std::ostream& out_, char delimiter_ = '\t') : out(out_), delimiter(delimiter_) { } explicit ValuePrinter(char delimiter_ = '\t') : out(std::cout), delimiter(delimiter_) { } void operator() (const tntdb::Value& v) const { if (v.isNull()) out << "null" << delimiter; else out << v.getString() << delimiter; } }; class RowPrinter { std::ostream& out; char delimiter; public: explicit RowPrinter(std::ostream& out_, char delimiter_ = '\n') : out(out_), delimiter(delimiter_) { } explicit RowPrinter(char delimiter_ = '\n') : out(std::cout), delimiter(delimiter_) { } void operator() (const tntdb::Row& t) const { std::for_each(t.begin(), t.end(), ValuePrinter(out, '\t')); out << delimiter; } }; #endif // UTIL_H tntdb-1.4/doc/000077500000000000000000000000001354703061500132425ustar00rootroot00000000000000tntdb-1.4/doc/Doxyfile.in000066400000000000000000000235131354703061500153610ustar00rootroot00000000000000# Doxyfile 1.4.4 #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- PROJECT_NAME = tntdb PROJECT_NUMBER = 0.5 OUTPUT_DIRECTORY = @top_builddir@/doc CREATE_SUBDIRS = NO OUTPUT_LANGUAGE = English USE_WINDOWS_ENCODING = NO BRIEF_MEMBER_DESC = YES REPEAT_BRIEF = YES ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the ALWAYS_DETAILED_SEC = YES INLINE_INHERITED_MEMB = NO FULL_PATH_NAMES = YES STRIP_FROM_PATH = @top_builddir@/include STRIP_FROM_INC_PATH = SHORT_NAMES = NO JAVADOC_AUTOBRIEF = YES MULTILINE_CPP_IS_BRIEF = NO DETAILS_AT_TOP = NO INHERIT_DOCS = YES DISTRIBUTE_GROUP_DOC = YES SEPARATE_MEMBER_PAGES = NO TAB_SIZE = 8 ALIASES = OPTIMIZE_OUTPUT_FOR_C = NO OPTIMIZE_OUTPUT_JAVA = NO SUBGROUPING = YES #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- EXTRACT_ALL = NO EXTRACT_PRIVATE = NO EXTRACT_STATIC = NO EXTRACT_LOCAL_CLASSES = YES EXTRACT_LOCAL_METHODS = NO HIDE_UNDOC_MEMBERS = YES HIDE_UNDOC_CLASSES = YES HIDE_FRIEND_COMPOUNDS = NO HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO CASE_SENSE_NAMES = YES HIDE_SCOPE_NAMES = NO SHOW_INCLUDE_FILES = YES INLINE_INFO = YES SORT_MEMBER_DOCS = YES SORT_BRIEF_DOCS = NO SORT_BY_SCOPE_NAME = NO GENERATE_TODOLIST = YES GENERATE_TESTLIST = YES GENERATE_BUGLIST = YES GENERATE_DEPRECATEDLIST= YES ENABLED_SECTIONS = MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES SHOW_DIRECTORIES = YES FILE_VERSION_FILTER = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- QUIET = NO WARNINGS = YES WARN_IF_UNDOCUMENTED = YES WARN_IF_DOC_ERROR = YES WARN_NO_PARAMDOC = NO WARN_FORMAT = "$file:$line: $text" WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- INPUT = @top_builddir@/include/tntdb \ @top_builddir@/include/tntdb/bits FILE_PATTERNS = *.c \ *.cc \ *.cxx \ *.cpp \ *.c++ \ *.d \ *.java \ *.ii \ *.ixx \ *.ipp \ *.i++ \ *.inl \ *.h \ *.hh \ *.hxx \ *.hpp \ *.h++ \ *.idl \ *.odl \ *.cs \ *.php \ *.php3 \ *.inc \ *.m \ *.mm \ *.dox \ *.C \ *.CC \ *.C++ \ *.II \ *.I++ \ *.H \ *.HH \ *.H++ \ *.CS \ *.PHP \ *.PHP3 \ *.M \ *.MM RECURSIVE = NO EXCLUDE = EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = EXAMPLE_PATH = EXAMPLE_PATTERNS = * EXAMPLE_RECURSIVE = NO IMAGE_PATH = INPUT_FILTER = FILTER_PATTERNS = FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- SOURCE_BROWSER = NO INLINE_SOURCES = NO STRIP_CODE_COMMENTS = YES REFERENCED_BY_RELATION = NO REFERENCES_RELATION = NO USE_HTAGS = NO VERBATIM_HEADERS = NO #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- ALPHABETICAL_INDEX = NO COLS_IN_ALPHA_INDEX = 5 IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- GENERATE_HTML = YES HTML_OUTPUT = html HTML_FILE_EXTENSION = .html HTML_HEADER = HTML_FOOTER = HTML_STYLESHEET = HTML_ALIGN_MEMBERS = YES GENERATE_HTMLHELP = NO CHM_FILE = HHC_LOCATION = GENERATE_CHI = NO BINARY_TOC = NO TOC_EXPAND = NO DISABLE_INDEX = NO ENUM_VALUES_PER_LINE = 4 GENERATE_TREEVIEW = YES TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- GENERATE_LATEX = YES LATEX_OUTPUT = latex LATEX_CMD_NAME = latex MAKEINDEX_CMD_NAME = makeindex COMPACT_LATEX = NO PAPER_TYPE = a4wide EXTRA_PACKAGES = LATEX_HEADER = PDF_HYPERLINKS = NO USE_PDFLATEX = YES LATEX_BATCHMODE = NO LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- GENERATE_RTF = NO RTF_OUTPUT = rtf COMPACT_RTF = NO RTF_HYPERLINKS = NO RTF_STYLESHEET_FILE = RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- GENERATE_MAN = NO MAN_OUTPUT = man MAN_EXTENSION = .3 MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- GENERATE_XML = NO XML_OUTPUT = xml XML_SCHEMA = XML_DTD = XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- GENERATE_PERLMOD = NO PERLMOD_LATEX = NO PERLMOD_PRETTY = YES PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- ENABLE_PREPROCESSING = YES MACRO_EXPANSION = NO EXPAND_ONLY_PREDEF = NO SEARCH_INCLUDES = YES INCLUDE_PATH = INCLUDE_FILE_PATTERNS = PREDEFINED = EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- TAGFILES = GENERATE_TAGFILE = ALLEXTERNALS = NO EXTERNAL_GROUPS = YES PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- CLASS_DIAGRAMS = YES HIDE_UNDOC_RELATIONS = YES HAVE_DOT = NO CLASS_GRAPH = YES COLLABORATION_GRAPH = YES GROUP_GRAPHS = YES UML_LOOK = NO TEMPLATE_RELATIONS = NO INCLUDE_GRAPH = YES INCLUDED_BY_GRAPH = YES CALL_GRAPH = NO GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = YES DOT_IMAGE_FORMAT = png DOT_PATH = DOTFILE_DIRS = MAX_DOT_GRAPH_WIDTH = 1024 MAX_DOT_GRAPH_HEIGHT = 1024 MAX_DOT_GRAPH_DEPTH = 1000 DOT_TRANSPARENT = NO DOT_MULTI_TARGETS = NO GENERATE_LEGEND = YES DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- SEARCHENGINE = NO tntdb-1.4/doc/Makefile.am000066400000000000000000000003351354703061500152770ustar00rootroot00000000000000EXTRA_DIST = @PACKAGE@.doxygen.in \ main.page if MAKE_DOXYGEN html_DATA = html/index.html html/index.html: @PACKAGE@.doxygen @DOXYGEN@ @PACKAGE@.doxygen install-data-hook: cp -pR html/* $(DESTDIR)$(htmldir) endif tntdb-1.4/doc/main.page000066400000000000000000000036231354703061500150300ustar00rootroot00000000000000/** \mainpage Easy to use database abstraction layer \section intro Introduction Tntdb is database abstraction layer for C++. The goals are: - easy and safe to use - automatic resource management - database independent - thin layer for best performance - no SQL-abstraction - use modern C++ with exceptions and STL - support for multithreaded applications A example, which lists the the content of a table: \code #include #include #include #include int main(int argc, char* argv[]) { try { tntdb::Connection conn = tntdb::connect("sqlite:mydatabase.db"); tntdb::Statement stmt = conn.prepare( "select FIRST_NAME, LAST_NAME" " from ADDRESS"); for (tntdb::Statement::const_iterator cur = stmt.begin(); cur != stmt.end(); ++cur) { tntdb::Row row = *cur; std::cout << row[0].getString() << '\t' << row[1].getString() << std::endl; } } catch (const std::exception& e) { std::cerr << e.what() << std::endl; } } \endcode Example: modify data: \code #include #include #include #include int main(int argc, char* argv[]) { try { tntdb::Connection conn = tntdb::connect("sqlite:mydatabase.db"); tntdb::Transaction trans; // start a transaction here tntdb::Statement stmt = conn.prepare( "insert into ADDRESS (ID, FIRST_NAME, LAST_NAME)" " values (:id, :firstName, :lastName)"); stmt.set("id", 34) .set("firstName", "Tommi") .set("lastName", "Makitalo") .execute(); stmt.set("id", 35) .set("firstName", "Linus") .set("lastName", "Torvalds") .execute(); // if no explicit commit is executed, then rollback is done trans.commit(); } catch (const std::exception& e) { std::cerr << e.what() << std::endl; } } \endcode */ tntdb-1.4/doc/tntdb.doxygen.in000066400000000000000000000235741354703061500163740ustar00rootroot00000000000000# Doxyfile 1.4.4 #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- PROJECT_NAME = tntdb PROJECT_NUMBER = @VERSION@ OUTPUT_DIRECTORY = @top_builddir@/doc CREATE_SUBDIRS = NO OUTPUT_LANGUAGE = English USE_WINDOWS_ENCODING = NO BRIEF_MEMBER_DESC = YES REPEAT_BRIEF = YES ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the ALWAYS_DETAILED_SEC = YES INLINE_INHERITED_MEMB = NO FULL_PATH_NAMES = YES STRIP_FROM_PATH = ../include STRIP_FROM_INC_PATH = SHORT_NAMES = NO JAVADOC_AUTOBRIEF = YES MULTILINE_CPP_IS_BRIEF = NO DETAILS_AT_TOP = NO INHERIT_DOCS = YES DISTRIBUTE_GROUP_DOC = YES SEPARATE_MEMBER_PAGES = NO TAB_SIZE = 8 ALIASES = OPTIMIZE_OUTPUT_FOR_C = NO OPTIMIZE_OUTPUT_JAVA = NO SUBGROUPING = YES #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- EXTRACT_ALL = NO EXTRACT_PRIVATE = NO EXTRACT_STATIC = NO EXTRACT_LOCAL_CLASSES = YES EXTRACT_LOCAL_METHODS = NO HIDE_UNDOC_MEMBERS = NO HIDE_UNDOC_CLASSES = NO HIDE_FRIEND_COMPOUNDS = NO HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO CASE_SENSE_NAMES = YES HIDE_SCOPE_NAMES = NO SHOW_INCLUDE_FILES = YES INLINE_INFO = YES SORT_MEMBER_DOCS = YES SORT_BRIEF_DOCS = NO SORT_BY_SCOPE_NAME = NO GENERATE_TODOLIST = YES GENERATE_TESTLIST = YES GENERATE_BUGLIST = YES GENERATE_DEPRECATEDLIST= YES ENABLED_SECTIONS = MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES SHOW_DIRECTORIES = YES FILE_VERSION_FILTER = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- QUIET = NO WARNINGS = YES WARN_IF_UNDOCUMENTED = NO WARN_IF_DOC_ERROR = YES WARN_NO_PARAMDOC = NO WARN_FORMAT = "$file:$line: $text" WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- INPUT = main.page \ ../include/tntdb.h \ ../include/tntdb \ ../include/tntdb/bits FILE_PATTERNS = *.c \ *.cc \ *.cxx \ *.cpp \ *.c++ \ *.d \ *.java \ *.ii \ *.ixx \ *.ipp \ *.i++ \ *.inl \ *.h \ *.hh \ *.hxx \ *.hpp \ *.h++ \ *.idl \ *.odl \ *.cs \ *.php \ *.php3 \ *.inc \ *.m \ *.mm \ *.dox \ *.C \ *.CC \ *.C++ \ *.II \ *.I++ \ *.H \ *.HH \ *.H++ \ *.CS \ *.PHP \ *.PHP3 \ *.M \ *.MM RECURSIVE = NO EXCLUDE = EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = EXAMPLE_PATH = EXAMPLE_PATTERNS = * EXAMPLE_RECURSIVE = NO IMAGE_PATH = INPUT_FILTER = FILTER_PATTERNS = FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- SOURCE_BROWSER = NO INLINE_SOURCES = NO STRIP_CODE_COMMENTS = YES REFERENCED_BY_RELATION = NO REFERENCES_RELATION = NO USE_HTAGS = NO VERBATIM_HEADERS = NO #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- ALPHABETICAL_INDEX = NO COLS_IN_ALPHA_INDEX = 5 IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- GENERATE_HTML = YES HTML_OUTPUT = html HTML_FILE_EXTENSION = .html HTML_HEADER = HTML_FOOTER = HTML_STYLESHEET = HTML_ALIGN_MEMBERS = YES GENERATE_HTMLHELP = NO CHM_FILE = HHC_LOCATION = GENERATE_CHI = NO BINARY_TOC = NO TOC_EXPAND = NO DISABLE_INDEX = NO ENUM_VALUES_PER_LINE = 4 GENERATE_TREEVIEW = YES TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- GENERATE_LATEX = NO LATEX_OUTPUT = latex LATEX_CMD_NAME = latex MAKEINDEX_CMD_NAME = makeindex COMPACT_LATEX = NO PAPER_TYPE = a4wide EXTRA_PACKAGES = LATEX_HEADER = PDF_HYPERLINKS = NO USE_PDFLATEX = YES LATEX_BATCHMODE = NO LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- GENERATE_RTF = NO RTF_OUTPUT = rtf COMPACT_RTF = NO RTF_HYPERLINKS = NO RTF_STYLESHEET_FILE = RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- GENERATE_MAN = NO MAN_OUTPUT = man MAN_EXTENSION = .3 MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- GENERATE_XML = NO XML_OUTPUT = xml XML_SCHEMA = XML_DTD = XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- GENERATE_PERLMOD = NO PERLMOD_LATEX = NO PERLMOD_PRETTY = YES PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- ENABLE_PREPROCESSING = YES MACRO_EXPANSION = NO EXPAND_ONLY_PREDEF = NO SEARCH_INCLUDES = YES INCLUDE_PATH = INCLUDE_FILE_PATTERNS = PREDEFINED = EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- TAGFILES = GENERATE_TAGFILE = ALLEXTERNALS = NO EXTERNAL_GROUPS = YES PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- CLASS_DIAGRAMS = YES HIDE_UNDOC_RELATIONS = YES HAVE_DOT = NO CLASS_GRAPH = YES COLLABORATION_GRAPH = YES GROUP_GRAPHS = YES UML_LOOK = NO TEMPLATE_RELATIONS = NO INCLUDE_GRAPH = YES INCLUDED_BY_GRAPH = YES CALL_GRAPH = NO GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = YES DOT_IMAGE_FORMAT = png DOT_PATH = DOTFILE_DIRS = MAX_DOT_GRAPH_WIDTH = 1024 MAX_DOT_GRAPH_HEIGHT = 1024 MAX_DOT_GRAPH_DEPTH = 1000 DOT_TRANSPARENT = NO DOT_MULTI_TARGETS = NO GENERATE_LEGEND = YES DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- SEARCHENGINE = NO tntdb-1.4/doc/tntdb.markdown000066400000000000000000000665121354703061500161330ustar00rootroot00000000000000Tntdb ===== Author: Tommi Mäkitalo Introduction ------------ Tntdb is a library for simple database access. There are 2 layers for access - a database independent layer and a database driver. The database independent layer offers easy to use methods for working with the database and also greatly simplifies resource-management. The classes hold reference-counted pointers to the actual implementation. They are copyable and assignable. The user can use the classes just like simple values. The resources they reference are freed, when the last reference is deleted. This happens normally just by leaving the scope. There is normally no reason to instantiate them dynamically on the heap. The driver-layer contains the actual implementation, which does the work. These classes are database-dependent. The user normally doesn't need to deal with this. Each class is defined in a header ``. Error handling is always done with exceptions. A class `tntdb::Error` is the base for all exceptions. It is derived from `std::runtime_error`. Connecting ---------- A connection is represented by the class `tntdb::Connection`. Tntdb offers a simple function, which connects to the database: `tntdb::connect`. This expects a parameter of type `std::string`, which is the database url. The database url consists of the driver name and a database dependent part divided by a colon. ### Example: #include #include int main(int argc, char** argv) { tntdb::Connection conn = tntdb::connect("sqlite:mydb.db"); } The example above loads the sqlite-driver-library and opens a connection to the databasefile "mydb.db". At the end of the program the class `tntdb::Connection` goes out of scope, which closes the connection automatically. When the database could not be opened a exception is thrown. In the above example it is unhandled, which makes the program to abort. This is not so nice, so we add exceptionhandling in the second example: #include #include int main(int argc, char** argv) { try { tntdb::Connection conn = tntdb::connect("postgresql:dbname=db"); } catch (const std::exception& e) { std::cerr << e.what() << std::endl; } } This is a complete example, which just checks, if the database is accessible. Let's look a little deeper into the driver dependent part. ### The Postgresql driver The part after the prefix "postgresql:" is passed directly to the C-API function `PQconnectdb`. You can look into the C-API documentation for details. Here is a simple example: tntdb::Connection conn = tntdb::connect("postgresql:dbname=DS2 user=web password=web"); ### The Sqlite driver The sqlite driver supports only sqlite3. No support for sqlite2 is available. The part after the prefix "sqlite:" is used as a file name for the database. No additional parameters are needed. Here is an example: tntdb::Connection conn = tntdb::connect("sqlite:mydatabase.db"); ### The mysql driver The part after the prefix "mysql:" is split into the parameters needed for `mysql_real_connect`. The string is interpreted as a list of parameters separated by semicolon. Each parameter is a name value pair separated by '='. The keys are post, flags, app, host, user, passwd, db and unix socket. For passwd the word password is also accepted. Db may be replaced with dbname or database. All other keys throw an error. The value may be enclosed in ' or ". The backslash character disables any special meaning of the next character. Ok - this is the definition. It is much easier to understand, if you see an example: tntdb::Connection conn = tntdb::connect("mysql:dbname=DS2;user=web;passwd=web"); ### The oracle driver To install the oracle driver on linux download the following libraries from Oracle (you will have to register but they are free of charge): oracle-instantclientVERS-basic-VERS.x86_64.rpm oracle-instantclientVERS-devel-VERS.x86_64.rpm where VERS stand for the version number e.g. 11.2 Install them with your package manager. The Oracle driver is not compiled by default when tntdb is compiled, since the Oracle client libraries are not free. You have to explicitly enable it using the configure switch --with-oracle. Since the includes and libs of oracle are normally not installed to standard paths, you need to tell the compiler where to find the includes and the linker where to find the libraries. This is done by setting the CPPFLAGS and LDFLAGS. The call to configure may look like this: ./configure --with-oracle --without-mysql CPPFLAGS=-I/usr/include/oracle/11.2/client64 LDFLAGS=-L/usr/lib/oracle/11.2/client64/lib The connection string has to start with the prefix "oracle:". The username and password are extracted. They must be passed semicolon separated "user=username" and "passwd=password". The rest of the string is passed to the OCI function `OCIServerAttach`. Here is an example for the Oracle Express Edition: tntdb::Connection conn = tntdb::connect("oracle:XE;user=hr;passwd=hr"); If your Oracle dbms runs on the machine with ip 192.168.0.100 on port 1521 and the service id is MYDB then the connection is created using: tntdb::Connection conn = tntdb::connect("oracle:192.168.0.100:1521/MYDB;user=hr;passwd=hr"); ### The replication driver The replication driver is a special case. It do not handle a specific database but implements a simple replication at the application level. To use it, the connection string must start with "replicate:" followed by a list of connection strings separated by '|'. A connection is established to each database. Statements, which just reads data, use the first connection in the list. Statements, which modify data, executes the statement on each connection. Before the actual statement is executed, a transaction is started on each connection unless there is already a active transaction. If the statement fails on one connection, all transactions are rolled back to ensure consistency. For modification statement the connection urls are ordered alphabetically to prevent deadlocks when different applications use the replication driver with different ordering of database urls. Note that the connections of the replication driver do not need to use the same database drivers but you can mix different drivers. For example you can replicate between a local sqlite and a postgresql database. Of course you are limited to use sql statements, which each database understand. And here is a example connect for the replication driver: tntdb::Connection conn = tntdb::connect("replicate:sqlite:mydatabase.db|postgresql:dbname=DS2 user=web password=web"); This connection reads data from a local sqlite database file and writes to the sqlite and postgresql database. Note that this is not really a full scale replication solution. It tries to do its best to keep the replication up to date as good as possible but not better. Execute query ------------- To execute sql statements which do not return data (normally update, insert or delete statements) `tntdb::Connection` has a method `execute`. It expects a `std::string` with a sql-statement, which does not return data. It returns the number of affected rows. ### Example: #include #include int main(int argc, char** argv) { try { tntdb::Connection conn = tntdb::connect("postgresql:dbname=db"); conn.execute( "create table t1(col1 int not null primary key," " col2 int not null)"); conn.execute("insert into t1 values(1, 5)"); unsigned n = conn.execute("update t1 set col1 = col1 + 1"); std::cout << n << "rows updated" << std::endl; } catch (const std::exception& e) { std::cerr << e.what() << std::endl; } } Selecting data -------------- A database is not just for storing data, but it also need to fetch the data. Tntdb offers several ways to read the data from the database. The most general is the method `tntdb::Connection::select()`, which expects a query and returns a object of class `tntdb::Result`. `tntdb::Result` is a collection of rows. Rows are represented by the class `tntdb::Row` and these rows are also collections of type `tntdb::Value`. Both collections (Result and Row) can be accessed with a iterator or through a index. The class `Value` offers methods for returning the data in different types. Tntdb does not tell, which type the column is. Value just does its best to convert the data to the requested type. The User has to know, which data the column holds. Fields in a row can be read using the number of occurence but also by using their name. Often there are statements, which return exactly one row or only a single value. For convenience `tntdb::Connection` offers the methods `selectRow` and `selectValue`. The former returns the first row of a query and the latter the first value of the first row. Both throw a exception of type `tntdb::NotFound`, if the query returns no rows at all. A `tntdb::Value` has a get-template-method, which receives a reference to a variable, which is filled by the actual value from the database. It returns a boolean value, which indicates, if the value was not null. In case the value was null, the method returns false and do not modify the passed variable. ### Example: #include #include #include void someFunc(tntdb::Connection conn) { tntdb::Result result = conn.select("select col1, col2, col3 from table"); for (tntdb::Result::const_iterator it = result.begin(); it != result.end(); ++it) { tntdb::Row row = *it; int a; std::string b; long c; bool cIsNotNull; row[0].get(a); // read column 0 into variable a b = row.getString("col2"); // read column with name "col2" into variable b cIsNotNull = row[2].get(c); // read column 2 into variable c std::cout << "col1=" << a << "\tcol2=" << b; if (cIsNotNull) std::cout << "\tcol3=" << c; else std::cout << "\tcol3 is null"; std::cout << std::endl; } } void someOtherFunc(tntdb::Connection conn) { tntdb::Value v = conn.selectValue("select count(*) from table"); std::cout << "The table 'table' has " << v.getUnsigned() << " rows" << std::endl; } Prepared statements ------------------- Most of the time the user needs to parameterize the queries. Because the query has the type `std::string` they can just be stringed together e.g. with `std::ostringstream`. But this is not recommended. The disadvantage is, that the user has to deal with special characters to avoid misinterpretation of data and especially avoid sql injection. Prepared statements solve this by parsing the statement and getting the parameters separately. This also offers sometimes significant performance-advantages, because the user can execute the same statement multiple times with different parameters. Parsing can be done either at the client-side or at the serve-side. Tntdb lets the driver decide, if the database can parse the query and which placeholders the database needs. To create a prepared statement `tntdb::Connection` has a method prepare, which takes a query as a `std::string` and returns a object of type `tntdb::Statement`. The query can contain parameters. Parameters are named tokens in the query prefixed with a colon. A token can occur multiple times in a query. The Statement-class has setter-methods to pass parameter-values with different types. `tntdb::Statement` offers the same methods for databaseaccess as `tntdb::Connect`: `execute`, `select`, `selectRow` and `selectValue`. They work exactly like the methods in `tntdb::Connect`. ### Example: #include void insData(tntdb::Connection conn) { tntdb::Statement st = conn.prepare( "insert into table values (:v1, :v2)"); st.setInt("v1", 1) // the setters return *this, so they can be // chained easily .setString("v2", "hi") .execute(); st.setInt("v1", 2) .setString("v2", "world") .execute(); } You may also omit the explicit mention of the data type. There is a template method `tntdb::Statement::set`, which determines the right type of the column from the type of the passed parameter. If you later decide to change the type of a variable, you don't need to replace the method used to pass the value to the database. Here is the same example as above using this template method: #include void insData(tntdb::Connection conn) { tntdb::Statement st = conn.prepare( "insert into table values (:v1, :v2)"); st.set("v1", 1) .set("v2", "hi") .execute(); st.set("v1", 2) .set("v2", "world") .execute(); } Working with cursors -------------------- Connections and prepared statements offer the method `select()`, which fetches the result and offers random-access to the data. Databases has often more data, than would fit into the memory of the program. To deal with this, the innovators of databases have created cursors. They are like pointers to a window in a resultset, but without holding (and transferring) all data in memory. Tntdb offers this functionality with `const_iterators` in prepared statements. The class `std::Statement::const_iterator` represents a database-cursor. It is a forward only iterator, which returns objects of type `tntdb::Row`, when dereferenced. The `begin` method of `tntdb::Statement` starts a new iteration of a cursor. ### Example: #include void printData(tntdb::Connection conn) { tntdb::Statement st = conn.prepare("select col1, col2 from table"); for (tntdb::Statement::const_iterator cur = st.begin(); cur != st.end(); ++cur) { tntdb::Row row = *cur; std::string col1; std::string col2; row[0].get(col1); row[1].get(col2); std::cout << "col1=" << col1 << " col2=" << col2 << std::endl; } } In the above example the memory-consumption is low even when the table has millions of rows. When the data would have been fetched with a `tntdb::Result` all rows has to fit into the main-memory. The begin-method of `tntdb::Statement` has a optional parameter fetchsize of type `unsigned`, which is passed to the driver. It may use it as a hint, how many rows it should fetch at once. The default value is 100. Using RowReader --------------- When selecting data, mostly you read all values from the row. If you have many values, you have to pass the ordinal value of each value separately, which may be tedious and error prone. To help it and make the code more readable, tntdb has a helper class called `tntdb::RowReader`, which reads all columns in turn. It has like `tntdb::Value` a method get, which receives a reference to a variable. But this time it returns a reference to the `tntdb::RowReader`, to make it easy to chain calls. If you need to know, if a value was null, you can pass a reference to a boolean variable, which tells, if the value was not null. Each call to the `get` method, increments the column counter of the `tntdb::RowReader`. The `tntdb::RowReader` is normally not instantiated explicitly, but a method `tntdb::Row::reader()` creates a instance of the class, with the initial column counter, which points to the first column number 0. Optionally you can pass a different start value to the `reader()` method as a parameter, if you want to skip some columns. As an example lets rewrite the `someFunc` function from a previous example: void someFunc(tntdb::Connection conn) { tntdb::Result result = conn.select("select col1, col2, col3 from table"); for (tntdb::Result::const_iterator it = result.begin(); it != result.end(); ++it) { tntdb::Row row = *it; int a; std::string b; long c; bool cIsNotNull; row.reader().get(a) .get(b) .get(c, cIsNotNull); std::cout << "col1=" << a << "\tcol2=" << b; if (cIsNotNull) std::cout << "\tcol3=" << c; else std::cout << "\tcol3 is null"; std::cout << std::endl; } } The same works also with a cursor. Lets look at the cursor example using the `tntdb::RowReader`: void printData(tntdb::Connection conn) { tntdb::Statement st = conn.prepare("select col1, col2 from table"); for (tntdb::Statement::const_iterator cur = st.begin(); cur != st.end(); ++cur) { std::string col1; std::string col2; cur->reader().get(col1) .get(col2); std::cout << "col1=" << col1 << " col2=" << col2 << std::endl; } } It is just a matter of taste, which method you prefer or which method fits best in the current situation. Tntdb tries to make it just as easy as possible. Starting with tntdb 1.3 we can omit the call to `reader()`. The `tntdb::Row` and `tntdb::Statement::const_iterator` has now methods to construct a reader and returning the first value. So we can write: ... row.get(a) .get(b) .get(c, cIsNotNull); ... Or with cursor: ... cur.get(col1) .get(col2); ... Transactions ------------ A database wouldn't be a database, if it does not offer transactions. `tntdb::Connection` has 3 methods to deal with it: `beginTransaction`, `commitTransaction` and `rollbackTransaction`. But this is not the recommended way to deal with it. Tntdb has more to offer: the class `tntdb::Transaction`. This class monitors the state of a transaction and closes the transaction automatically, when needed. This offers exception-safety without the danger of open transactions. `tntdb::Transaction` are instantiated (just like all tntdb-user-classes) as local variables. The constructor starts a transaction and the destructor rolls the transaction back, if the transaction is not explicitely committed. This guarantees, that the transaction is never left open (except when the rollback fails, but this normally happens only, when the connection is broken anyway and there is no way to do any harm to the database any more). ### Example: #include void doSomeModifications(tntdb::Connection conn) { tntdb::Transaction trans(conn); // do some modifications in the database here: conn.execute(...); conn.prepare("...").set("col1", value).execute(); trans.commit(); } // no explicit rollback is needed. In case of an exception, the // transaction is rolled back automatically here Using dates and times --------------------- Dates and times are a little special when it comes to databases. There is no standard syntax for specifying dates and times. Therefore tntdb offers 3 helper classes. `tntdb::Date` can hold a date, `tntdb::Time` a time and `tntdb::Datetime` both. They can be used just like built in types in tntdb. You can set host variables and retrieve the value from results returned from the database. The classes are simple helper classes which do not have any range checks or other knowledge of the nature of the data. The constructor of `tntdb::Date` takes 3 parameters: the year, the month and the day. The constructor takes 3 or 4 parameters: the hour, the minute, the second and a optional millisecond. `tntdb::Datetime` is created using 6 or 7 parameters. First the 3 parameters of the date and then the 3 or 4 for the time. There are also 2 static methods in each of the 3 classes `localtime` and `gmtime`, which create a object with the current date or time. Lets look for some examples: void dateTimeDemos(tntdb::Connection conn) { // insert dates and times into table: tntdb::Statement ins = conn.prepare( "insert into mytable (datecolumn, timecolumn, datetimecolumn)" " values(:date, :time, :datetime)"); ins.set("date", tntdb::Date(2010, 2, 13)) .set("time", tntdb::Time(23, 22, 30)) .set("datetime", tntdb::Datetime(2010, 2, 13, 23, 22, 30)) .execute(); // insert the current dates and times into the table ins.set("date", tntdb::Date::localtime()) .set("time", tntdb::Time::localtime()) .set("datetime", tntdb::Datetime::localtime()) .execute(); // retrieve dates and times from a table: tntdb::Statement sel = conn.prepare( "select datecolumn, timecolumn, datetimecolumn" " from mytable"); for (tntdb::Statement::const_iterator cur = st.begin(); cur != st.end(); ++cur) { tntdb::Row row = *cur; tntdb::Date mydate; tntdb::Time mytime; tntdb::Datetime mydatetime; row[0].get(mydate); row[1].get(mytime); row[2].get(mydatetime); // now we have the data from the table in our variables std::cout << "date=" << mydate.getIso() << "\n" "time=" << mytime.getIso() << "\n" "datetime=" << mydatetime.getIso() << std::endl; } Using own types --------------- Tntdb offers also support for custom types. The setter and getter methods in tntdb are actually templates, which uses 2 operators to actually map types to the methods. Lets design a own type, which we would like to store in a database field. To make the example simple, we use a struct with public member variables. Normally you should always make the member variables private or protected and offer setter and getter methods: struct Myclass { int a; int b; Myclass() { } // default constructor is mostly good to have Myclass(int a_, int b_) // ctor to initialize both members : a(a_), b(b_) { } }; We would like to write the class as a pair of numbers separated with ':' into a database field. So we define a operator, which formats the structure properly: void operator<< (tntdb::Hostvar& hv, const Myclass& myclass) { std::ostringstream s; s << myclass.a << ':' << myclass.b; hv.set(s.str()); } The operator creates a `std::string` with the content of the class and passes it to this special helper class `tntdb::Hostvar`, which is defined in the header `tntdb/statement.h`. This is the only case, where you will explicitly use the class. To retrieve data from the database we need another operator: bool operator>> (const tntdb::Value& value, Myclass& myclass) { if (value.isNull()) return false; std::string str; value.get(str); std::istringstream in(str); char ch; in >> myclass.a >> ch // skip the ':' >> myclass.b; return true; } That's all. Now we can use the class just like built ins: void customTypeDemo(tntdb::Connection conn) { // insert myclass into table: tntdb::Statement ins = conn.prepare( "insert into mytable (mycolumn)" " values(:mycolumn)"); ins.set("mycolumn", Myclass(17, 45)) .execute(); // retrieve myclass from a table: tntdb::Statement sel = conn.prepare( "select mycolumn from mytable"); for (tntdb::Statement::const_iterator cur = st.begin(); cur != st.end(); ++cur) { tntdb::Row row = *cur; Myclass myclass; row[0].get(myclass); // now we have the data from the table in our variables std::cout << "a=" << myclass.a << "\t" "b=" << myclass.b << std::endl; } } Using serial columns -------------------- If tables are designed, you have to create a primary key to identify uniquely a specific row in the table. Sometimes it is enough to use just some arbitrary unique number. Databases has support for a automatically generated primary key. It actually depends on the database, how to create such columns. Since tntdb has no support for ddl statements (create table ...), there is actually no need to abstract the creation of these columns. But in applications it is often needed to know, which number was given to the last inserted row. This is also depends on the actual database software used. Tntdb helps retrieving that last insert id. There is a method `long tntdb::Connection::lastInsertId(const std::string& name)`. There is one problem. Some databases (postgresql, oracle) use named sequences and a single table may have multiple of them. So to fetch the actual id, we need to tell the driver, which sequence we want to know. The sequence is identified by name. Other databases (mysql, sqlite) do not have a identifier. They will simply ignore the passed name. This name is by default an empty string, which requests the last incremented serial number in the current transaction. Here is a example. We assume a table foo with 2 columns: id and name. The id is the primary auto incremented key. In postgresql or oracle the sequence is created with the name `foo_id_seq`: void insertData(tntdb::Connection conn) { tntdb::Statement ins = conn.prepare( "insert into foo (name)" " values(:name)"); ins.set("name", "some name") .execute(); std::cout << "id: " << conn.lastInsertId("foo_id_seq") << std::endl; // or mostly you can just omit the serial name std::cout << "id: " << conn.lastInsertId() << std::endl; } Connectionpool -------------- In a long-running program it is often desirable not to connect and disconnect for every access. One solution is to keep a connection open somewhere and use is as needed. In a multi threaded application the user has to make sure, that there is only one thread at a time accessing the database through a single connection. To solve this, Tntdb offerers a automatic connectionpool. When the call to `tntdb::connect` is replaced with `tntdb::connectCached` a special connection is returned. This connection works just like the normal connection (it is the same class), but when destroyed, it does not close the connection, but puts the connection to a free pool. When `tntdb::connectCached` is called again with the same parameter, the connection is reused. When the old connection is still in use, `connectCached` just creates a new one. ### Example: std::string url = "mysql:db=mydb;host=192.168.0.1"; tntdb::Connection conn; conn = tntdb::connectCached(url); // connects to the db conn = tntdb::Connection(); // puts the connection back to the pool conn = tntdb::connectCached(url); // fetches the same connection // (if not already fetched by another thread) tntdb::dropCached(); // closes all free connections, but not ours, // because it is hold by 'conn' conn = tntdb::Connection(); tntdb::dropCached(); // closes the connection, because we released it Statementcache -------------- As told previously statement-reuse improves performance quite heavily. It is advisable to try to use prepared statements where possible. In the case of a connectionpool it is quite difficult to maintain prepared statements, because they are specific to the connection. Tntdb helps here by putting a statementcache into the connection-class. When calls to `tntdb::Connection::prepare` is replaced with `tntdb::Connection::prepareCached`, tntdb looks into the connection, if the same statement is already prepared earlier and returns this when needed and calls prepare and fills the statement-cache with this new statement otherwise. tntdb-1.4/include/000077500000000000000000000000001354703061500141205ustar00rootroot00000000000000tntdb-1.4/include/Makefile.am000066400000000000000000000051621354703061500161600ustar00rootroot00000000000000nobase_include_HEADERS = \ tntdb/bits/blob.h \ tntdb/bits/blobstream.h \ tntdb/bits/connection.h \ tntdb/bits/result.h \ tntdb/bits/result_iterator.h \ tntdb/bits/row.h \ tntdb/bits/rowreader.h \ tntdb/bits/row_iterator.h \ tntdb/bits/statement.h \ tntdb/bits/statement_iterator.h \ tntdb/bits/value.h \ tntdb/cxxtools/date.h \ tntdb/cxxtools/time.h \ tntdb/cxxtools/datetime.h \ tntdb/cxxtools/timespan.h \ tntdb/blob.h \ tntdb/connect.h \ tntdb/connection.h \ tntdb/connectionpool.h \ tntdb/date.h \ tntdb/datetime.h \ tntdb/decimal.h \ tntdb/error.h \ tntdb/iface/iblob.h \ tntdb/iface/iconnection.h \ tntdb/iface/iconnectionmanager.h \ tntdb/iface/icursor.h \ tntdb/iface/iresult.h \ tntdb/iface/irow.h \ tntdb/iface/istatement.h \ tntdb/iface/ivalue.h \ tntdb/impl/blob.h \ tntdb/librarymanager.h \ tntdb/result.h \ tntdb/row.h \ tntdb/serialization.h \ tntdb/sqlbuilder.h \ tntdb/statement.h \ tntdb/time.h \ tntdb/transaction.h \ tntdb/value.h \ tntdb.h nobase_noinst_HEADERS = \ tntdb/mysql/bindutils.h \ tntdb/mysql/bindvalues.h \ tntdb/mysql/cursor.h \ tntdb/mysql/error.h \ tntdb/mysql/impl/boundrow.h \ tntdb/mysql/impl/boundvalue.h \ tntdb/mysql/impl/connection.h \ tntdb/mysql/impl/connectionmanager.h \ tntdb/mysql/impl/cursor.h \ tntdb/mysql/impl/result.h \ tntdb/mysql/impl/resultrow.h \ tntdb/mysql/impl/rowcontainer.h \ tntdb/mysql/impl/rowvalue.h \ tntdb/mysql/impl/statement.h \ tntdb/postgresql/error.h \ tntdb/postgresql/impl/connection.h \ tntdb/postgresql/impl/connectionmanager.h \ tntdb/postgresql/impl/cursor.h \ tntdb/postgresql/impl/result.h \ tntdb/postgresql/impl/resultrow.h \ tntdb/postgresql/impl/resultvalue.h \ tntdb/postgresql/impl/statement.h \ tntdb/replicate/connection.h \ tntdb/replicate/connectionmanager.h \ tntdb/replicate/statement.h \ tntdb/sqlite/error.h \ tntdb/sqlite/impl/connection.h \ tntdb/sqlite/impl/connectionmanager.h \ tntdb/sqlite/impl/cursor.h \ tntdb/sqlite/impl/statement.h \ tntdb/sqlite/impl/stmtrow.h \ tntdb/sqlite/impl/stmtvalue.h \ tntdb/impl/poolconnection.h \ tntdb/impl/result.h \ tntdb/impl/row.h \ tntdb/impl/value.h \ tntdb/stmtparser.h \ tntdb/oracle/blob.h \ tntdb/oracle/connection.h \ tntdb/oracle/connectionmanager.h \ tntdb/oracle/cursor.h \ tntdb/oracle/datetime.h \ tntdb/oracle/error.h \ tntdb/oracle/multirow.h \ tntdb/oracle/multivalue.h \ tntdb/oracle/number.h \ tntdb/oracle/result.h \ tntdb/oracle/row.h \ tntdb/oracle/singlerow.h \ tntdb/oracle/singlevalue.h \ tntdb/oracle/statement.h \ tntdb/oracle/string.h \ tntdb/oracle/value.h nobase_nodist_include_HEADERS = \ tntdb/config.h tntdb-1.4/include/tntdb.h000066400000000000000000000035741354703061500154150ustar00rootroot00000000000000/* * Copyright (C) 2007 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_H #define TNTDB_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /** Main namespace for Tntdb All Tntdb code is in this namespace. */ namespace tntdb { } #endif // TNTDB_H tntdb-1.4/include/tntdb/000077500000000000000000000000001354703061500152335ustar00rootroot00000000000000tntdb-1.4/include/tntdb/bits/000077500000000000000000000000001354703061500161745ustar00rootroot00000000000000tntdb-1.4/include/tntdb/bits/blob.h000066400000000000000000000071001354703061500172610ustar00rootroot00000000000000/* * Copyright (C) 2007-2008 Tommi Maekitalo * Copyright (C) 2007-2008 Marc Boris Duerner * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_BITS_BLOB_H #define TNTDB_BITS_BLOB_H #include #include #include namespace tntdb { /// @brief Binary large objects class Blob { public: /// @brief Release policy for SmartPtr template struct Release { void destroy(IBlob* blob) { blob->destroy(); } }; private: /// @brief Pointer to shared data cxxtools::SmartPtr _data; public: Blob() : _data(BlobImpl::emptyInstance()) { } /** Construct a Blob with data of a given length Constructs a Blob using a default implementation using new/delete to manage the blob-data and the shared data object. The first \a len bytes of the data pointed to by \a data are copied to this Blob. */ Blob(const char* data, std::size_t len) : _data(new BlobImpl()) { _data->assign(data, len); } /// Construct a Blob to use a customized implementation explicit Blob(IBlob* b) : _data(b) { } /// Assigns the data to this blob object void assign(const char* data, std::size_t len) { // copy-on-write if (_data->refs() > 1) _data = _data->create(); _data->assign(data, len); } /** Make sure the buffer is big enough to hold at least len bytes If shrink is set, the buffer will be exactly len bytes. Data is not preserved when reallocated. */ char* reserve(std::size_t len, bool shrink = false) { if (_data.getPointer() == BlobImpl::emptyInstance()) _data = _data->create(); return _data->reserve(len, shrink); } bool operator==(const Blob& b) const { return *_data == *b._data; } bool operator!=(const Blob& b) const { return !operator==(b); } /// Get a pointer to the data or 0 if no data is set. const char* data() const { return _data->data(); } /// Get the size of the data std::size_t size() const { return _data->size(); } }; } #endif // TNTDB_BITS_BLOB_H tntdb-1.4/include/tntdb/bits/blobstream.h000066400000000000000000000040661354703061500205050ustar00rootroot00000000000000/* * Copyright (C) 2011 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_BITS_BLOBSTREAM_H #define TNTDB_BITS_BLOBSTREAM_H #include namespace tntdb { class Blob; /** @brief streambuf for reading from a tntdb::Blob */ class BlobStreamBuf : public std::streambuf { public: explicit BlobStreamBuf(Blob& blob); /// see std::streambuf int_type overflow(int_type c); /// see std::streambuf int_type underflow(); /// see std::streambuf int sync(); }; /** @brief istream for reading from a tntdb::Blob */ class BlobIStream : public std::istream { BlobStreamBuf streambuf; public: explicit BlobIStream(Blob& blob) : std::istream(0), streambuf(blob) { init(&streambuf); } }; } #endif tntdb-1.4/include/tntdb/bits/connection.h000066400000000000000000000164641354703061500205170ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_BITS_CONNECTION_H #define TNTDB_BITS_CONNECTION_H #include #include #include #include namespace tntdb { class Result; class Row; class Value; class Statement; /** This class holds a connection to a database Normally you would create a connection with tntdb::connect(url). The actual connection is reference counted. You can copy this class as you need. When the last copy of it is destroyed, the connection is closed. Example: @code try { tntdb::Connection conn = tntdb::connect("postgresql:dbname=mydatabase"); tntdb::Statement st = conn.prepare("SELECT col1, col2 FROM mytable"); for (tntdb::Statement::const_iterator it = res.begin(); it != res.end(); ++it) std::cout << "col1 = " << it->getString() << ", col2 = " << it->getInt() << std::endl; } catch (const std::exception& e) { std::cerr << e.what() << std::endl; } @endcode */ class Connection { public: typedef unsigned size_type; private: cxxtools::SmartPtr _conn; public: /// Create an empty %Connection object Connection() { } /// Create a %Connection object from conn Connection(IConnection* conn) : _conn(conn) { } /** Remove the reference to the connected database. If this was the last reference, the connection is actually closed. */ void close() { _conn = 0; } /** Start a transaction Normally this is not needed. It is better to use the class Transaction instead. */ void beginTransaction(); /// Commit the current transaction void commitTransaction(); /// Roll back the current transaction void rollbackTransaction(); /** Execute a static query without returning results The query normally is an INSERT, UPDATE or DELETE statement. As with the other query execution methods this should be used only for static queries. If you need to pass parameters it is always better to use the Statement class. */ size_type execute(const std::string& query); /** Execute a static query which returns a result The query normally is a SELECT statement. */ Result select(const std::string& query); /** Execute a static query which returns a result The first row is returned. If the query returns an empty result, a NotFound exception is thrown. */ Row selectRow(const std::string& query); /** Execute a static query which returns a result The first value of the first row is returned. If the query returns an empty result, a NotFound exception is thrown. */ Value selectValue(const std::string& query); /// Create a new Statement object with the given query Statement prepare(const std::string& query); /** Create a new Statement object with the given query added by a range limitation. The `limit` and `offset` parameters are the names of the host variables, which receive the limits. The offset is optional. When an empty string is passed to offset, just the limit is used. */ Statement prepareWithLimit(const std::string& query, const std::string& limit, const std::string& offset = std::string()); /** Create a new Statement object with the given query and store it in a cache When called again with the same query, the cached object is returned */ Statement prepareCached(const std::string& query) { return prepareCached(query, query); } /** Create a new Statement object with the given query and caching key Per default, prepareCached() uses the query as key which identifies a Statement object in the cache. With this method you can provide your own key (because shorter keys mean faster lookup in the cache). Be aware though that when using this, you have to ensure the same key won't be used twice. */ Statement prepareCached(const std::string& query, const std::string& key); /** Create a new Statement object with the given query added by a range limitation. This is like `prepareWithLimit` but the prepared statement cache is used. */ Statement prepareCachedWithLimit(const std::string& query, const std::string& limit, const std::string& offset = std::string()) { return prepareCachedWithLimit(query, limit, offset, query); } /** Create a new Statement object with the given query added by a range limitation. This is like `prepareWithLimit` but the prepared statement cache is used. Like in `prepareCached` an optional key can be used. */ Statement prepareCachedWithLimit(const std::string& query, const std::string& limit, const std::string& offset, const std::string& key); /// Clear the Statement cache used from prepareCached() void clearStatementCache() { _conn->clearStatementCache(); } /** Remove a query from the statement cache The return value is true if the given key was found in the cache, false otherwise. */ bool clearStatementCache(const std::string& key) { return _conn->clearStatementCache(key); } /// Check whether the connection is alive bool ping() { return _conn->ping(); } /// Get the last inserted insert id long lastInsertId(const std::string& name = std::string()) { return _conn->lastInsertId(name); } /// Check if a connection is established (true if not) bool operator!() const { return !_conn; } /// @{ /// Get the actual implementation object const IConnection* getImpl() const { return &*_conn; } IConnection* getImpl() { return &*_conn; } /// @} }; } #endif // TNTDB_BITS_CONNECTION_H tntdb-1.4/include/tntdb/bits/result.h000066400000000000000000000064201354703061500176650ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_BITS_RESULT_H #define TNTDB_BITS_RESULT_H #include #include namespace tntdb { class Row; class Value; /** * The class holds a resultset of a query. * Querys might return multiple rows, which are accessable here in arbitary * order. */ class Result { public: typedef unsigned size_type; typedef Row value_type; private: cxxtools::SmartPtr result; public: class const_iterator; Result() { } Result(IResult* res) : result(res) { } /** * Returns the row_num'ths row of the resultset. */ Row getRow(size_type row_num) const; /** * Returns the field_num'ths value of the row_num'ths row. */ Value getValue(size_type row_num, size_type field_num) const; /** * Returns the number of rows of this resultset. */ size_type size() const { return result->size(); } /** * Returns true, when there are no rows available. */ bool empty() const { return size() == 0; } /** * Returns the number of columns of the rows. */ size_type getFieldCount() const { return result->getFieldCount(); } /** * Returns the row_num'ths row of the resultset. */ Row operator[] (size_type row_num) const; /** * Returns a const_iterator to the first row of this resultset. */ const_iterator begin() const; /** * Returns a const_iterator past the last row of this resultset. */ const_iterator end() const; /** * Returns true, when this classes does not reference a resultset. */ bool operator!() const { return !result; } /** * Returns the actual implementation-class. */ const IResult* getImpl() const { return &*result; } }; } #endif // TNTDB_BITS_RESULT_H tntdb-1.4/include/tntdb/bits/result_iterator.h000066400000000000000000000116731354703061500216040ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_BITS_RESULT_ITERATOR_H #define TNTDB_BITS_RESULT_ITERATOR_H #include #include #include namespace tntdb { /** * This implements a constant iterator to a result-set. */ class Result::const_iterator : public std::iterator { public: typedef const value_type& const_reference; typedef const value_type* const_pointer; private: Result result; Row current; size_type offset; void setOffset(size_type off) { if (off != offset) { offset = off; if (offset < result.size()) current = result.getRow(offset); } } public: const_iterator(const Result& r, size_type off) : result(r), offset(off) { if (offset < r.size()) current = r.getRow(offset); } /// Returns true, if the passed iterator points to the same row. /// The iterators should point to the same resultset. This is /// not checked. Only the offsets are considered. bool operator== (const const_iterator& it) const { return offset == it.offset; } /// Returns true, if the passed iterator points to different rows. /// The iterators should point to the same resultset. This is /// not checked. Only the offsets are considered. bool operator!= (const const_iterator& it) const { return !operator== (it); } /// Advances the iterator to the next element and returns the iterator to that element. const_iterator& operator++() { setOffset(offset + 1); return *this; } /// Advances the iterator to the next element and returns the previous iterator. const_iterator operator++(int) { const_iterator ret = *this; setOffset(offset + 1); return ret; } /// Moves the iterator to the previous element and returns the iterator to that element. const_iterator operator--() { setOffset(offset - 1); return *this; } /// Moves the iterator to the previous element and returns the previous iterator. const_iterator operator--(int) { const_iterator ret = *this; setOffset(offset - 1); return ret; } /// returns a reference to the current Row-object. const_reference operator*() const { return current; } /// returns a pointer to the current Row-object. const_pointer operator->() const { return ¤t; } /// Advances the iterator n elements and returns the iterator to that element. const_iterator& operator+= (difference_type n) { setOffset(offset + n); return *this; } /// Returns a iterator, which points n elements further. const_iterator operator+ (difference_type n) const { const_iterator it(*this); it += n; return it; } /// Moves the iterator n elements back and returns the iterator to that element. const_iterator& operator-= (difference_type n) { setOffset(offset - n); return *this; } /// Returns a iterator, which points n elements back. const_iterator operator- (difference_type n) const { const_iterator it(*this); it -= n; return it; } /// Returns the distance between 2 iterators. /// The iterators should point to the same resultset. This is /// not checked. Only the offsets are used. difference_type operator- (const const_iterator& it) const { return offset - it.offset; } }; } #endif // TNTDB_BITS_RESULT_ITERATOR_H tntdb-1.4/include/tntdb/bits/row.h000066400000000000000000000217651354703061500171670ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_BITS_ROW_H #define TNTDB_BITS_ROW_H #include #include #include #include #include namespace tntdb { class RowReader; /** * Row represents a row, which is fetched from the database. */ class Row { public: /// Iterator for iterating through the values of this row. class const_iterator; typedef unsigned size_type; typedef Value value_type; private: cxxtools::SmartPtr row; public: Row() { } Row(IRow* row_) : row(row_) { } /// Returns the number of columns of this row. unsigned size() const { return row->size(); } /// Returns true, if this row-object has no columns. bool empty() const { return !row || size() == 0; } /// Returns the field_num's value-object. Value getValue(size_type field_num) const { return row->getValueByNumber(field_num); } /// Returns the value-object by name. Value getValue(const std::string& field_name) const { return row->getValueByName(field_name); } /// Returns the field_num's value-object. Value operator[] (size_type field_num) const { return row->getValueByNumber(field_num); } /// Returns the value-object by name. Value operator[] (const std::string& field_name) const { return row->getValueByName(field_name); } /// Returns the name of the field_num's column std::string getName(size_type field_num) const { return row->getColumnName(field_num); } /// Return true, if the specified value is null. bool isNull(size_type field_num) const { return getValue(field_num).isNull(); } /// Return true, if the specified value is null. bool isNull(const std::string& field_name) const { return getValue(field_name).isNull(); } //@{ /** * The get-methods try to convert the value of the speicfied column to * the requested type. */ bool getBool(size_type field_num) const { return getValue(field_num).getBool(); } short getShort(size_type field_num) const { return getValue(field_num).getShort(); } int getInt(size_type field_num) const { return getValue(field_num).getInt(); } long getLong(size_type field_num) const { return getValue(field_num).getLong(); } unsigned short getUnsignedShort(size_type field_num) const { return getValue(field_num).getUnsignedShort(); } unsigned getUnsigned(size_type field_num) const { return getValue(field_num).getUnsigned(); } unsigned long getUnsignedLong(size_type field_num) const { return getValue(field_num).getUnsignedLong(); } int32_t getInt32(size_type field_num) const { return getValue(field_num).getInt32(); } uint32_t getUnsigned32(size_type field_num) const { return getValue(field_num).getUnsigned32(); } int64_t getInt64(size_type field_num) const { return getValue(field_num).getInt64(); } uint64_t getUnsigned64(size_type field_num) const { return getValue(field_num).getUnsigned64(); } Decimal getDecimal(size_type field_num) const { return getValue(field_num).getDecimal(); } float getFloat(size_type field_num) const { return getValue(field_num).getFloat(); } double getDouble(size_type field_num) const { return getValue(field_num).getDouble(); } char getChar(size_type field_num) const { return getValue(field_num).getChar(); } std::string getString(size_type field_num) const { return getValue(field_num).getString(); } void getString(size_type field_num, std::string& ret) const { return getValue(field_num).getString(ret); } Blob getBlob(size_type field_num) const { return getValue(field_num).getBlob(); } void getBlob(size_type field_num, Blob& ret) const { return getValue(field_num).getBlob(ret); } Date getDate(size_type field_num) const { return getValue(field_num).getDate(); } Time getTime(size_type field_num) const { return getValue(field_num).getTime(); } Datetime getDatetime(size_type field_num) const { return getValue(field_num).getDatetime(); } bool getBool(const std::string& field_name) const { return getValue(field_name).getBool(); } short getShort(const std::string& field_name) const { return getValue(field_name).getShort(); } int getInt(const std::string& field_name) const { return getValue(field_name).getInt(); } long getLong(const std::string& field_name) const { return getValue(field_name).getLong(); } unsigned getUnsigned(const std::string& field_name) const { return getValue(field_name).getUnsigned(); } unsigned long getUnsignedLong(const std::string& field_name) const { return getValue(field_name).getUnsignedLong(); } int32_t getInt32(const std::string& field_name) const { return getValue(field_name).getInt32(); } uint32_t getUnsigned32(const std::string& field_name) const { return getValue(field_name).getUnsigned32(); } int64_t getInt64(const std::string& field_name) const { return getValue(field_name).getInt64(); } uint64_t getUnsigned64(const std::string& field_name) const { return getValue(field_name).getUnsigned64(); } Decimal getDecimal(const std::string& field_name) const { return getValue(field_name).getDecimal(); } float getFloat(const std::string& field_name) const { return getValue(field_name).getFloat(); } double getDouble(const std::string& field_name) const { return getValue(field_name).getDouble(); } char getChar(const std::string& field_name) const { return getValue(field_name).getChar(); } std::string getString(const std::string& field_name) const { return getValue(field_name).getString(); } void getString(const std::string& field_name, std::string& ret) const { return getValue(field_name).getString(ret); } Blob getBlob(const std::string& field_name) const { return getValue(field_name).getBlob(); } void getBlob(const std::string& field_name, Blob& ret) const { return getValue(field_name).getBlob(ret); } Date getDate(const std::string& field_name) const { return getValue(field_name).getDate(); } Time getTime(const std::string& field_name) const { return getValue(field_name).getTime(); } Datetime getDatetime(const std::string& field_name) const { return getValue(field_name).getDatetime(); } //@} template bool getValue(size_type field_num, T& ret) const { return getValue(field_num).getValue(ret); } /// Returns a iterator to the first column const_iterator begin() const; /// Returns a iterator past the last column const_iterator end() const; /// Returns true, if this class is not connected to a actual databaserow. bool operator!() const { return !row; } /// Returns the actual implementation-class. const IRow* getImpl() const { return &*row; } /// Instantiates a tntdb::RowReader with the passed initial column counter. RowReader reader(size_type n = 0) const; /// Instantiates a tntdb::RowReader and fetches the value of the first column. template RowReader get(T& ret) const; /// Instantiates a tntdb::RowReader and fetches the value of the first column and sets the null indicator. template RowReader get(T& ret, bool& nullInd) const; }; } #endif // TNTDB_BITS_ROW_H tntdb-1.4/include/tntdb/bits/row_iterator.h000066400000000000000000000072651354703061500210770ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_BITS_ROW_ITERATOR_H #define TNTDB_BITS_ROW_ITERATOR_H #include #include namespace tntdb { class Row::const_iterator : public std::iterator { public: typedef const value_type& const_reference; typedef const value_type* const_pointer; private: const IRow* row; size_type offset; Value current; void setOffset(size_type off) { if (off != offset) { offset = off; if (offset < row->size()) current = Value(row->getValueByNumber(offset)); } } public: const_iterator(const Row& row_, size_type offset_) : row(row_.getImpl()), offset(offset_) { if (offset < row->size()) current = Value(row->getValueByNumber(offset)); } bool operator== (const const_iterator& it) const { return offset == it.offset; } bool operator!= (const const_iterator& it) const { return !operator== (it); } const_iterator& operator++() { setOffset(offset + 1); return *this; } const_iterator operator++(int) { const_iterator ret = *this; setOffset(offset + 1); return ret; } const_iterator operator--() { setOffset(offset - 1); return *this; } const_iterator operator--(int) { const_iterator ret = *this; setOffset(offset - 1); return ret; } const_reference operator*() const { return current; } const_pointer operator->() const { return ¤t; } const_iterator& operator+= (difference_type n) { setOffset(offset + n); return *this; } const_iterator operator+ (difference_type n) const { const_iterator it(*this); it += n; return it; } const_iterator& operator-= (difference_type n) { setOffset(offset - n); return *this; } const_iterator operator- (difference_type n) const { const_iterator it(*this); it -= n; return it; } difference_type operator- (const const_iterator& it) const { return offset - it.offset; } }; } #endif // TNTDB_BITS_ROW_ITERATOR_H tntdb-1.4/include/tntdb/bits/rowreader.h000066400000000000000000000126701354703061500203450ustar00rootroot00000000000000/* * Copyright (C) 2011 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_ROWREADER_H #define TNTDB_ROWREADER_H #include namespace tntdb { /** * A RowReader is a class which helps reading multiple columns from a row. * * This class helds a field number counter, which is incremented each time * a value is fetched from the underlying row using one of the get methods. * This class is normally instantiated implicitly using the tntdb::Row::reader * method. * * The get methods return a reference to the row reader to make chaining of * calls easy. * * Example: * \code * tntdb::Statement s = conn.prepare("select col1, col2, col3 from table"); * for (tntdb::Statement::const_iterator cur = s.begin(); cur != s.end(); ++cur) * { * int col1; * std::string col2; * long col3; * bool col3IsNotNull; * // note that a dereferenced cursor returns a tntdb::Row: * cur->reader().get(col1) // this fetches the first value and * // increments the field counter * .get(col2) // and the second * .get(col3, col3IsNotNull); // and this reads the 3rd column * // and a flag, if it is not null * // ... * // do whatever you need to do with the values here * // ... * } * \endcode */ class RowReader { const Row& row; Row::size_type field_num; public: /// instatiates a row reader with a row and a initial field counter explicit RowReader(const Row& row_, Row::size_type field_num_ = 0) : row(row_), field_num(field_num_) { } /// Reads the current column value and increments the field counter. /// If the value is null, the passed variable is not changed. /// There is no straight forward way to determine, whether the value was null. /// You should use the get method with the null indicator, if the value /// might be null or just initialize your value with a suitable default. template RowReader& get(T& ret) { row[field_num++].get(ret); return *this; } /// Reads the current column value and a null indicator and increments the /// field counter. If the value is null, the null indicator is set to false /// and the actual value of the passed variable is not changed. template RowReader& get(T& ret, bool& nullInd) { nullInd = row[field_num++].get(ret); return *this; } /// Reads the current value into a tntdb::Value and increments the field /// counter. RowReader& get(tntdb::Value& v) { v = row[field_num++]; return *this; } /// Returns true, if the current value is null. bool isNull() const { return row[field_num].isNull(); } /// Resets the field counter to the passed value. void rewind(Row::size_type n_ = 0) { field_num = n_; } /// returns the underlying row. const Row& currentRow() const { return row; } /// returns the current column number. Row::size_type currentCol() const { return field_num; } /// increments the current column number and returns the incremented value (pre increment). Row::size_type operator++ () { return ++field_num; } /// increments the current column number and returns the previous value (post increment). Row::size_type operator++ (int) { return field_num++; } /// decrements the current column number and returns the decremented value (pre decrement). Row::size_type operator-- () { return --field_num; } /// decrements the current column number and returns the previous value (post decrement). Row::size_type operator-- (int) { return field_num--; } }; inline RowReader Row::reader(Row::size_type n) const { return RowReader(*this, n); } template RowReader Row::get(T& ret) const { return RowReader(*this).get(ret); } template RowReader Row::get(T& ret, bool& nullInd) const { return RowReader(*this).get(ret, nullInd); } } #endif // TNTDB_ROWREADER_H tntdb-1.4/include/tntdb/bits/statement.h000066400000000000000000000441151354703061500203560ustar00rootroot00000000000000/* * Copyright (C) 2005,2010 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_BITS_STATEMENT_H #define TNTDB_BITS_STATEMENT_H #include #include #include #include #include #include #include #include #include #include #include #include #include #if __cplusplus >= 201103L #include #include #include #endif namespace tntdb { class Result; class Row; class Value; class Date; class Time; class Datetime; /** This class represents an SQL statement A statement can have parameters, which are referenced by name, called host variables. They are prefixed with a colon followed by a name. A name starts with a letter followed by alphanumeric characters or underscores. Host variables are not searched in strings (between apostrophes, quotation marks or backticks). A backslash prevents the interpretation of a special meaning of the following character. */ class Statement { public: class const_iterator; typedef IStatement::size_type size_type; private: cxxtools::SmartPtr _stmt; public: Statement(IStatement* stmt = 0) : _stmt(stmt) { } /// Set all host variables to NULL Statement& clear() { _stmt->clear(); return *this; } /// Set the host variable with the given name to NULL Statement& setNull(const std::string& col) { _stmt->setNull(col); return *this; } /// Set the host variable with the given name to a boolean value Statement& setBool(const std::string& col, bool data) { _stmt->setBool(col, data); return *this; } /// Set the host variable with the given name to a short value Statement& setShort(const std::string& col, short data) { _stmt->setShort(col, data); return *this; } /// Set the host variable with the given name to an int value Statement& setInt(const std::string& col, int data) { _stmt->setInt(col, data); return *this; } /// Set the host variable with the given name to a long value Statement& setLong(const std::string& col, long data) { _stmt->setLong(col, data); return *this; } /// Set the host variable with the given name to an unsigned short value Statement& setUnsignedShort(const std::string& col, unsigned short data) { _stmt->setUnsignedShort(col, data); return *this; } /// Set the host variable with the given name to an unsigned value Statement& setUnsigned(const std::string& col, unsigned data) { _stmt->setUnsigned(col, data); return *this; } /// Set the host variable with the given name to an unsigned long value Statement& setUnsignedLong(const std::string& col, unsigned long data) { _stmt->setUnsignedLong(col, data); return *this; } /// Set the host variable with the given name to a int32_t value Statement& setInt32(const std::string& col, int32_t data) { _stmt->setInt32(col, data); return *this; } /// Set the host variable with the given name to a uint32_t value Statement& setUnsigned32(const std::string& col, uint32_t data) { _stmt->setUnsigned32(col, data); return *this; } /// Set the host variable with the given name to a int64_t value Statement& setInt64(const std::string& col, int64_t data) { _stmt->setInt64(col, data); return *this; } /// Set the host variable with the given name to a uint64_t value Statement& setUnsigned64(const std::string& col, uint64_t data) { _stmt->setUnsigned64(col, data); return *this; } /// Set the host variable with the given name to a Decimal Statement& setDecimal(const std::string& col, const Decimal& data) { _stmt->setDecimal(col, data); return *this; } /// Set the host variable with the given name to a float value Statement& setFloat(const std::string& col, float data) { _stmt->setFloat(col, data); return *this; } /// Set the host variable with the given name to a double value Statement& setDouble(const std::string& col, double data) { _stmt->setDouble(col, data); return *this; } /// Set the host variable with the given name to a char value Statement& setChar(const std::string& col, char data) { _stmt->setChar(col, data); return *this; } /// Set the host variable with the given name to a string value Statement& setString(const std::string& col, const std::string& data) { _stmt->setString(col, data); return *this; } /// Set the host variable with the given name to a string value or null Statement& setString(const std::string& col, const char* data) { data == 0 ? _stmt->setNull(col) : _stmt->setString(col, data); return *this; } /// Set the host variable with the given name to a unicode string value Statement& setUString(const std::string& col, const cxxtools::String& data) { _stmt->setUString(col, data); return *this; } /// Set the host variable with the given name to a blob value Statement& setBlob(const std::string& col, const Blob& data) { _stmt->setBlob(col, data); return *this; } /// Set the host variable with the given name to a date value Statement& setDate(const std::string& col, const Date& data) { data.isNull() ? _stmt->setNull(col) : _stmt->setDate(col, data); return *this; } /// Set the host variable with the given name to a time value Statement& setTime(const std::string& col, const Time& data) { data.isNull() ? _stmt->setNull(col) : _stmt->setTime(col, data); return *this; } /// Set the host variable with the given name to a datetime value Statement& setDatetime(const std::string& col, const Datetime& data) { data.isNull() ? _stmt->setNull(col) : _stmt->setDatetime(col, data); return *this; } /** Set the host variable with the given name to the passed value The method uses the operator<< with a l-value of the type Hostvar& and r-value of a const reference to the actual type to read the value. The operator is defined for standard types and may be defined for user defined types. */ template Statement& set(const std::string& col, const T& data); /** Set multiple numbered parameters to the values specified by the iterator range The method expects, that the statement has columns with the specified column name appended by a number range starting from 0. This list can be generated for example with tntdb::SqlBuilder. Example: @code std::vector values; values.push_back(5); values.push_back(12); tntdb::Statement stmt = conn.prepare("select a, b, c from tab1 where v in (" + tntdb::Statement::paramlist("v", values.size()) + ")"); stmt.set("v", values.begin(), values.end()); // or short version: stmt.set("v", values); // now stmt is ready for iteration @endcode */ template Statement& set(const std::string& col, Iterator it1, Iterator it2); template Statement& set(const Object& obj) { cxxtools::SerializationInfo si; si <<= obj; si >>= *this; return *this; } /** Set the host variable with the given name to the passed value or null The method sets the host variable to the given value if the 2nd argument is true. Otherwise the host variable is set to null. */ template Statement& setIf(const std::string& col, bool notNull, const T& data) { if (notNull) set(col, data); else setNull(col); return *this; } /// Statement execution methods /// @{ /** Execute the query without returning the result The query should not return results. This method is normally used with INSERT, UPDATE or DELETE statements. */ size_type execute(); template size_type execute(const Object& obj) { return set(obj).execute(); } /** Execute the query and return the result The query normally is a SELECT statement. */ Result select(); /** Execute the query and return the first row of the result If the result is empty, a NotFound exception is thrown. Additional rows are ignored. */ Row selectRow(); /** Execute the query and return the first value from the first row of the result If the result is empty, a NotFound exception is thrown. Additional values are ignored. */ Value selectValue(); /// @} /// Create a database cursor and fetch the first row of the query result const_iterator begin(unsigned fetchsize = 100) const; /** Get an end iterator This iterator works like the iterator got from the %end() method of STL containers like std::vector and std::list. It doesn't reference the last element in a list but an imaginary element after the last one, and should be used as follows: @code for(tntdb::Statement::const_iterator it = stmtObj.begin(); it != stmtObj.end(); ++it) { // Loop body accessing individual result rows through *it } @endcode */ const_iterator end() const; /// Check whether this object is associated with a real statement (true if not) bool operator!() const { return !_stmt; } /** Sets a buffer for delayed execution of statements. When the number if greater than 0 and the connection is in a transaction, the execute method may delay the actual execution until the buffer is full or flush is called. The default is 0. */ void maxNumDelay(size_type n); /// Returns the number of the currently pending statements. size_type numDelayed() const; /// Executes all currently pending statements. /// Returns number of affected rows. size_type flush(); /// @{ /// Get the actual implementation object const IStatement* getImpl() const { return &*_stmt; } IStatement* getImpl() { return &*_stmt; } /// @} }; /// Helper class to hold a Statement and a column name class Hostvar { private: Statement& _stmt; const std::string& _name; public: Hostvar(Statement& stmt, const std::string& name) : _stmt(stmt), _name(name) { } Statement& getStatement() { return _stmt; } const std::string& getName() { return _name; } void setNull() { _stmt.setNull(_name); } void setBool(bool data) { _stmt.setBool(_name, data); } void setInt(int data) { _stmt.setInt(_name, data); } void setLong(long data) { _stmt.setLong(_name, data); } void setUnsigned(unsigned data) { _stmt.setUnsigned(_name, data); } void setUnsignedLong(unsigned long data) { _stmt.setUnsignedLong(_name, data); } void setInt32(int32_t data) { _stmt.setInt32(_name, data); } void setUnsigned32(uint32_t data) { _stmt.setUnsigned32(_name, data); } void setInt64(int64_t data) { _stmt.setInt64(_name, data); } void setUnsigned64(uint64_t data) { _stmt.setUnsigned64(_name, data); } void setDecimal(const Decimal& data) { _stmt.setDecimal(_name, data); } void setFloat(float data) { _stmt.setFloat(_name, data); } void setDouble(double data) { _stmt.setDouble(_name, data); } void setChar(char data) { _stmt.setChar(_name, data); } void setString(const std::string& data) { _stmt.setString(_name, data); } void setString(const char* data) { data == 0 ? _stmt.setNull(_name) : _stmt.setString(_name, data); } void setUString(const cxxtools::String& data) { _stmt.setUString(_name, data); } void setBlob(const Blob& data) { _stmt.setBlob(_name, data); } void setDate(const Date& data) { data.isNull() ? _stmt.setNull(_name) : _stmt.setDate(_name, data); } void setTime(const Time& data) { data.isNull() ? _stmt.setNull(_name) : _stmt.setTime(_name, data); } void setDatetime(const Datetime& data) { data.isNull() ? _stmt.setNull(_name) : _stmt.setDatetime(_name, data); } template void set(const T& data); }; /// Set operators for host variables /// @{ inline void operator<< (Hostvar& hostvar, bool data) { hostvar.setBool(data); } inline void operator<< (Hostvar& hostvar, int data) { hostvar.setInt(data); } inline void operator<< (Hostvar& hostvar, long data) { hostvar.setLong(data); } inline void operator<< (Hostvar& hostvar, unsigned data) { hostvar.setUnsigned(data); } inline void operator<< (Hostvar& hostvar, unsigned long data) { hostvar.setUnsignedLong(data); } #if INT_INT32_T_CONFLICT != 1 inline void operator<< (Hostvar& hostvar, int32_t data) { hostvar.setInt32(data); } #endif #if UNSIGNED_UINT32_T_CONFLICT != 1 inline void operator<< (Hostvar& hostvar, uint32_t data) { hostvar.setUnsigned32(data); } #endif #if INT_INT64_T_CONFLICT != 1 inline void operator<< (Hostvar& hostvar, int64_t data) { hostvar.setInt64(data); } #endif #if UNSIGNED_UINT64_T_CONFLICT != 1 inline void operator<< (Hostvar& hostvar, uint64_t data) { hostvar.setUnsigned64(data); } #endif inline void operator<< (Hostvar& hostvar, const Decimal& data) { hostvar.setDecimal(data); } inline void operator<< (Hostvar& hostvar, float data) { hostvar.setFloat(data); } inline void operator<< (Hostvar& hostvar, double data) { hostvar.setDouble(data); } inline void operator<< (Hostvar& hostvar, char data) { hostvar.setChar(data); } inline void operator<< (Hostvar& hostvar, const std::string& data) { hostvar.setString(data); } inline void operator<< (Hostvar& hostvar, const char* data) { hostvar.setString(data); } inline void operator<< (Hostvar& hostvar, const cxxtools::String& data) { hostvar.setUString(data); } inline void operator<< (Hostvar& hostvar, const Blob& data) { hostvar.setBlob(data); } inline void operator<< (Hostvar& hostvar, const Date& data) { hostvar.setDate(data); } inline void operator<< (Hostvar& hostvar, const Time& data) { hostvar.setTime(data); } inline void operator<< (Hostvar& hostvar, const Datetime& data) { hostvar.setDatetime(data); } template void operator<< (Hostvar& hostvar, const std::vector& data) { hostvar.getStatement().set(hostvar.getName(), data.begin(), data.end()); } template void operator<< (Hostvar& hostvar, const std::list& data) { hostvar.getStatement().set(hostvar.getName(), data.begin(), data.end()); } template void operator<< (Hostvar& hostvar, const std::deque& data) { hostvar.getStatement().set(hostvar.getName(), data.begin(), data.end()); } template void operator<< (Hostvar& hostvar, const std::set& data) { hostvar.getStatement().set(hostvar.getName(), data.begin(), data.end()); } template void operator<< (Hostvar& hostvar, const std::multiset& data) { hostvar.getStatement().set(hostvar.getName(), data.begin(), data.end()); } #if __cplusplus >= 201103L template void operator<< (Hostvar& hostvar, const std::forward_list& data) { hostvar.getStatement().set(hostvar.getName(), data.begin(), data.end()); } template void operator<< (Hostvar& hostvar, const std::unordered_set& data) { hostvar.getStatement().set(hostvar.getName(), data.begin(), data.end()); } template void operator<< (Hostvar& hostvar, const std::unordered_multiset& data) { hostvar.getStatement().set(hostvar.getName(), data.begin(), data.end()); } #endif /// @} template Statement& Statement::set(const std::string& name, const T& data) { Hostvar h(*this, name); h << data; return *this; } template Statement& Statement::set(const std::string& col, Iterator it1, Iterator it2) { for (unsigned n = 0; it1 != it2; ++n, ++it1) { set(col + cxxtools::convert(n), *it1); } return *this; } template void Hostvar::set(const T& data) { *this << data; } } #endif // TNTDB_BITS_STATEMENT_H tntdb-1.4/include/tntdb/bits/statement_iterator.h000066400000000000000000000066031354703061500222670ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_BITS_STATEMENT_ITERATOR_H #define TNTDB_BITS_STATEMENT_ITERATOR_H #include #include #include #include namespace tntdb { class RowReader; /** * This class represents a database-cursor. */ class Statement::const_iterator : public std::iterator { Row current; cxxtools::SmartPtr cursor; public: explicit const_iterator(ICursor* cursor_ = 0); /** * Returns true, when the cursor points to the same iteration as the * passed iterator. */ bool operator== (const const_iterator& c) const { return cursor == c.cursor; } /** * Returns true, when the cursor does not point to the same iteration as * the passed iterator. */ bool operator!= (const const_iterator& c) const { return cursor != c.cursor; } /** * Fetches the next row. If no rows are available, the cursor is closed * and removed from this class. */ const_iterator& operator++(); const_iterator operator++(int); /** * Returns the current tntdb::Row-object. */ const Row& operator* () const { return current; } /** * This operator makes the const_iterator look like a pointer. */ const Row* operator-> () const { return ¤t; } /// Instantiates a tntdb::RowReader and fetches the value of the first column. template RowReader get(T& ret) const; /// Instantiates a tntdb::RowReader and fetches the value of the first column and sets the null indicator. template RowReader get(T& ret, bool& nullInd) const; /** * Returns the actual implementation-class. */ const ICursor* getImpl() const { return &*cursor; } }; /// Alternative name for the statement iterator. /// It may be easier to write and read. typedef Statement::const_iterator Cursor; } #endif // TNTDB_BITS_STATEMENT_ITERATOR_H tntdb-1.4/include/tntdb/bits/value.h000066400000000000000000000241101354703061500174570ustar00rootroot00000000000000/* * Copyright (C) 2005,2010 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_BITS_VALUE_H #define TNTDB_BITS_VALUE_H #include #include #include #include #include #include #include #include namespace tntdb { /** * The class Value represents a value, which is fetched from the database. */ class Value { cxxtools::SmartPtr value; public: explicit Value(IValue* value = 0) : value(value) { } //@{ /** * Explicit data-access. * The getXXX-methods return the value in the requested type. * If the value can't be converted to the requested type, a exception of * type tntdb::TypeError is thrown. */ /// return true, when value is null bool isNull() const { return !value || value->isNull(); } /// return true, when value represents boolean true. bool getBool() const { return value->getBool(); } /// tries to convert value into an short. short getShort() const { return value->getShort(); } /// tries to convert value into an int. int getInt() const { return value->getInt(); } /// tries to convert value into an long. long getLong() const { return value->getLong(); } /// tries to convert value into an unsigned short. unsigned short getUnsignedShort() const { return value->getUnsignedShort(); } /// tries to convert value into an unsigned. unsigned getUnsigned() const { return value->getUnsigned(); } /// tries to convert value into an unsigned long. unsigned long getUnsignedLong() const { return value->getUnsignedLong(); } /// tries to convert value into an int32_t. int32_t getInt32() const { return value->getInt32(); } /// tries to convert value into an uint32_t. uint32_t getUnsigned32() const { return value->getUnsigned32(); } /// tries to convert value into an int64_t. int64_t getInt64() const { return value->getInt64(); } /// tries to convert value into an uint64_t. uint64_t getUnsigned64() const { return value->getUnsigned64(); } /// tries to convert value into a Decimal. Decimal getDecimal() const { return value->getDecimal(); } /// tries to convert value into an float. float getFloat() const { return value->getFloat(); } /// tries to convert value into an double. double getDouble() const { return value->getDouble(); } /// returns the first character of the text-representation. char getChar() const { return value->getChar(); } /// returns the value as a string. std::string getString() const { std::string ret; value->getString(ret); return ret; } /// fills the passed string with the value. /// this might be slightly more efficient than just returning a new /// string since one copy is saved. void getString(std::string& ret) const { value->getString(ret); } /// returns the value as a unicode string. cxxtools::String getUString() const { cxxtools::String ret; value->getUString(ret); return ret; } void getUString(cxxtools::String& ret) const { value->getUString(ret); } /// Returns the value as a blob. /// This is more or less an alias to getString just to stress, that /// the data is truly binary and not some text value. Blob getBlob() const { Blob ret; value->getBlob(ret); return ret; } /// Returns the value as a blob. void getBlob(Blob& blob) const { value->getBlob(blob); } /// returns the value as a Date. Date getDate() const { return value->getDate(); } /// returns the value as a Time. Time getTime() const { return value->getTime(); } /// returns the value as a Datetime. Datetime getDatetime() const { return value->getDatetime(); } //@} /** * Explicit data-access. * The get-template return false if the value is null. Otherwise the * passed reference is filled with the value. * If the value can't be converted to the requested type, a exception of * type tntdb::TypeError is thrown. * * In contrast to the getXXX-methods the type is not specified explictely * but determined by the passed reference. * * The extraction is actually done using the operator>> with a l-value of * const Value& and a r-value of a reference to the actual type. This * operator is defined for standard types and may be defined for user * defined types. */ template bool getValue(T& ret) const { return *this >> ret; } /// Shorter name for getValue. template bool get(T& ret) const { return *this >> ret; } /// Returns true, if this class is not connected to a actual statement. bool operator!() const { return !value; } /// Returns the actual implementation-class. const IValue* getImpl() const { return &*value; } }; //@{ /** Extraction operators for standard types. */ inline bool operator>> (const Value& value, bool& out) { if (value.isNull()) return false; out = value.getBool(); return true; } inline bool operator>> (const Value& value, short& out) { if (value.isNull()) return false; out = value.getShort(); return true; } inline bool operator>> (const Value& value, int& out) { if (value.isNull()) return false; out = value.getInt(); return true; } inline bool operator>> (const Value& value, long& out) { if (value.isNull()) return false; out = value.getLong(); return true; } inline bool operator>> (const Value& value, unsigned short& out) { if (value.isNull()) return false; out = value.getUnsignedShort(); return true; } inline bool operator>> (const Value& value, unsigned& out) { if (value.isNull()) return false; out = value.getUnsigned(); return true; } inline bool operator>> (const Value& value, unsigned long& out) { if (value.isNull()) return false; out = value.getUnsignedLong(); return true; } #if INT_INT32_T_CONFLICT != 1 inline bool operator>> (const Value& value, int32_t& out) { if (value.isNull()) return false; out = value.getInt32(); return true; } #endif #if UNSIGNED_UINT32_T_CONFLICT != 1 inline bool operator>> (const Value& value, uint32_t& out) { if (value.isNull()) return false; out = value.getUnsigned32(); return true; } #endif #if INT_INT64_T_CONFLICT != 1 inline bool operator>> (const Value& value, int64_t& out) { if (value.isNull()) return false; out = value.getInt64(); return true; } #endif #if UNSIGNED_UINT64_T_CONFLICT != 1 inline bool operator>> (const Value& value, uint64_t& out) { if (value.isNull()) return false; out = value.getUnsigned64(); return true; } #endif inline bool operator>> (const Value& value, Decimal& out) { if (value.isNull()) return false; out = value.getDecimal(); return true; } inline bool operator>> (const Value& value, float& out) { if (value.isNull()) return false; out = value.getFloat(); return true; } inline bool operator>> (const Value& value, double& out) { if (value.isNull()) return false; out = value.getDouble(); return true; } inline bool operator>> (const Value& value, char& out) { if (value.isNull()) return false; out = value.getChar(); return true; } inline bool operator>> (const Value& value, std::string& out) { if (value.isNull()) return false; value.getString(out); return true; } inline bool operator>> (const Value& value, cxxtools::String& out) { if (value.isNull()) return false; value.getUString(out); return true; } inline bool operator>> (const Value& value, Blob& out) { if (value.isNull()) return false; value.getBlob(out); return true; } inline bool operator>> (const Value& value, Date& out) { if (value.isNull()) return false; out = value.getDate(); return true; } inline bool operator>> (const Value& value, Time& out) { if (value.isNull()) return false; out = value.getTime(); return true; } inline bool operator>> (const Value& value, Datetime& out) { if (value.isNull()) return false; out = value.getDatetime(); return true; } //@} } #endif // TNTDB_BITS_VALUE_H tntdb-1.4/include/tntdb/blob.h000066400000000000000000000027771354703061500163370ustar00rootroot00000000000000/* * Copyright (C) 2007 Tommi Maekitalo * Copyright (C) 2007-2008 Marc Boris Duerner * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_BLOB_H #define TNTDB_BLOB_H #include #include #endif // TNTDB_BLOB_H tntdb-1.4/include/tntdb/config.h.in000066400000000000000000000011261354703061500172560ustar00rootroot00000000000000/** defines, whether type long long exists */ #define @HAVE_LONG_LONG@ /** defines, whether type unsigned long long exists */ #define @HAVE_UNSIGNED_LONG_LONG@ /* define if int and int32_t are same types */ #define INT_INT32_T_CONFLICT @INT_INT32_T_CONFLICT@ /* define if int and int64_t are same types */ #define INT_INT64_T_CONFLICT @INT_INT64_T_CONFLICT@ /* define if unsigned and uint32_t are same types */ #define UNSIGNED_UINT32_T_CONFLICT @UNSIGNED_UINT32_T_CONFLICT@ /* define if unsigned and uint64_t are same types */ #define UNSIGNED_UINT64_T_CONFLICT @UNSIGNED_UINT64_T_CONFLICT@ tntdb-1.4/include/tntdb/connect.h000066400000000000000000000116271354703061500170440ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_CONNECT_H #define TNTDB_CONNECT_H #include #include namespace tntdb { /** Establish a connection to a database The url is prefixed with a driver name followed by a colon and a driver-specific part. If the connection can't be established, an exception derived from tntdb::Error is thrown. In the url the string "%u" is replaced with the username and "%p" is replaced with the password. The password parameter and the url with the replaced username and password fields is never logged. To specify the text "%u" or "%p" in the connection string the '%' can be escaped with backslash like this: "\%u". Examples: @code tntdb::Connection sqConn = tntdb::connect("sqlite:mydatabase.db"); tntdb::Connection pgConn = tntdb::connect("postgresql:dbname=DS2 user=%u passwd=%p", "web", "webpw"); tntdb::Connection myConn = tntdb::connect("mysql:db=DS2;user=%u;passwd=%p", "web", "webpw"); tntdb::Connection orConn = tntdb::connect("oracle:XE;user=%u;passwd=%p", "hr", "hr"); @endcode */ Connection connect(const std::string& url, const std::string& username, const std::string& password); Connection connect(const std::string& url); /** Fetch a connection from a pool or create a new one A static pool of connections is kept in memory. This function looks in this pool if there is a connection with the given url. If found, the connection is removed from the pool and returned. When the returned Connection object is destroyed (and all copies are too), the actual connection is put back into the pool. When there is no connection with the given url in the pool, a new connection is established. */ Connection connectCached(const std::string& url, const std::string& username, const std::string& password); Connection connectCached(const std::string& url); /** Returns the number of cached connections. Note that connections, which are in use are not counted. */ unsigned cachedConnections(); /** Returns the number of cached connections for the specified url. Note that connections, which are in use are not counted. */ unsigned cachedConnections(const std::string& url, const std::string& username, const std::string& password); unsigned cachedConnections(const std::string& url); /** Release unused connections; keep the given number of connections. Returns the number of connections freed. Note that connections, which are in use are not freed. */ unsigned dropCached(unsigned keep = 0); /** Release unused connections with the given database url; keep the given number of connections Note that connections, which are in use are not freed. */ unsigned dropCached(const std::string& url, const std::string& username = "", const std::string& password = "", unsigned keep = 0); inline unsigned dropCached(const std::string& url, unsigned keep) { return dropCached(url, "", "", keep); } /** Set the maximum pool size for new connection pools When the maximum number of connections to a specific url is reached, connectCached blocks until a connection is available. This setting do not affect pools with active connections. You have to release all connections and clear the pool of all connections to your database with dropCached(url) for this setting to take effect. */ void setMaxPoolSize(unsigned max); /// Get the current setting for maximum pool size (see setMaxPoolSize()) unsigned getMaxPoolSize(); } #endif // TNTDB_CONNECT_H tntdb-1.4/include/tntdb/connection.h000066400000000000000000000027071354703061500175510ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_CONNECTION_H #define TNTDB_CONNECTION_H #include #endif // TNTDB_CONNECTION_H tntdb-1.4/include/tntdb/connectionpool.h000066400000000000000000000110711354703061500204350ustar00rootroot00000000000000/* * Copyright (C) 2006 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_CONNECTIONPOOL_H #define TNTDB_CONNECTIONPOOL_H #include #include #include namespace tntdb { class Connection; class ConnectionPool { class Connector { std::string url; std::string username; std::string password; public: Connector(const std::string& url_, const std::string& username_, const std::string& password_) : url(url_), username(username_), password(password_) { } Connection* operator() (); }; typedef cxxtools::Pool PoolType; PoolType pool; public: typedef PoolType::Ptr PoolObjectType; public: explicit ConnectionPool(const std::string& url, const std::string& username, const std::string& password, unsigned maxcount = 0) : pool(maxcount, Connector(url, username, password)) { } Connection connect(); /// Release unused connections; keep the given number of connections unsigned drop(unsigned keep = 0); unsigned getMaximumSize() { return pool.getMaximumSize(); } void setMaximumSize(unsigned m) { pool.setMaximumSize(m); } unsigned getCurrentSize() const { return pool.getCurrentSize(); } }; class ConnectionPools { ConnectionPools(const ConnectionPools&) { } ConnectionPools& operator=(const ConnectionPools&) { return *this; } public: struct ConnectionParameter { std::string url; std::string username; std::string password; ConnectionParameter() { } ConnectionParameter(const std::string& url_, const std::string& username_, const std::string& password_) : url(url_), username(username_), password(password_) { } bool operator< (const ConnectionParameter& other) const { int c; c = url.compare(other.url); if (c != 0) return c < 0; c = username.compare(other.username); if (c != 0) return c < 0; return password < other.password; } }; typedef ConnectionPool PoolType; typedef std::map PoolsType; private: PoolsType pools; unsigned maxcount; mutable cxxtools::Mutex mutex; public: explicit ConnectionPools(unsigned maxcount_ = 0) : maxcount(maxcount_) { } ~ConnectionPools(); Connection connect(const std::string& url, const std::string& username, const std::string& password); /// Release unused connections; keep the given number of connections unsigned drop(unsigned keep = 0); /** Release unused connections with the given database url; keep the given number of connections */ unsigned drop(const std::string& url, const std::string& username, const std::string& password, unsigned keep = 0); unsigned getMaximumSize() { return maxcount; } void setMaximumSize(unsigned m); unsigned getCurrentSize(const std::string& url, const std::string& username, const std::string& password) const; unsigned getCurrentSize() const; }; } #endif // TNTDB_CONNECTIONPOOL_H tntdb-1.4/include/tntdb/cxxtools/000077500000000000000000000000001354703061500171165ustar00rootroot00000000000000tntdb-1.4/include/tntdb/cxxtools/date.h000066400000000000000000000050141354703061500202040ustar00rootroot00000000000000/* * Copyright (C) 2011 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_CXXTOOLS_DATE_H #define TNTDB_CXXTOOLS_DATE_H #include #include #include namespace tntdb { /** This operator can be used to pass a cxxtools::Date object to the database. @code tntdb::Statement stmt = conn.prepare("select ... where dt = :dt"); cxxtools::Date dt(2011, 5, 3); stmt.set("dt", dt); @endcode */ inline void operator<< (Hostvar& hostvar, const cxxtools::Date& dt) { hostvar.setDate(Date(dt.year(), dt.month(), dt.day())); } /** This operator can be used to retrieve a cxxtools::Date object from the database. @code tntdb::Statement sel = conn.prepare("select dt from ..."); tntdb::Value v = sel.selectValue(); cxxtools::Date dt; if (v.get(dt)) std::cout << "dt=" << dt.toIsoString() << std::endl; else std::cout << "dt is null" << std::endl; @endcode */ inline bool operator>> (const Value& value, cxxtools::Date& out) { if (value.isNull()) return false; Date dt = value.getDate(); out.set(dt.getYear(), dt.getMonth(), dt.getDay()); return true; } } #endif // TNTDB_CXXTOOLS_DATE_H tntdb-1.4/include/tntdb/cxxtools/datetime.h000066400000000000000000000053341354703061500210700ustar00rootroot00000000000000/* * Copyright (C) 2011 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_CXXTOOLS_DATETIME_H #define TNTDB_CXXTOOLS_DATETIME_H #include #include #include namespace tntdb { /** This operator can be used to pass a cxxtools::DateTime object to the database. @code tntdb::Statement stmt = conn.prepare("select ... where dt = :dt"); cxxtools::DateTime dt(2011, 5, 3, 18, 45, 30); stmt.set("dt", dt); @endcode */ inline void operator<< (Hostvar& hostvar, const cxxtools::DateTime& dt) { hostvar.setDatetime(Datetime(dt.year(), dt.month(), dt.day(), dt.hour(), dt.minute(), dt.second(), dt.msec())); } /** This operator can be used to retrieve a cxxtools::DateTime object from the database. @code tntdb::Statement sel = conn.prepare("select dt from ..."); tntdb::Value v = sel.selectValue(); cxxtools::DateTime dt; if (v.get(dt)) std::cout << "dt=" << dt.toIsoString() << std::endl; else std::cout << "dt is null" << std::endl; @endcode */ inline bool operator>> (const Value& value, cxxtools::DateTime& out) { if (value.isNull()) return false; Datetime dt = value.getDatetime(); out.set(dt.getYear(), dt.getMonth(), dt.getDay(), dt.getHour(), dt.getMinute(), dt.getSecond(), dt.getMillis()); return true; } } #endif // TNTDB_CXXTOOLS_DATETIME_H tntdb-1.4/include/tntdb/cxxtools/time.h000066400000000000000000000051201354703061500202230ustar00rootroot00000000000000/* * Copyright (C) 2011 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_CXXTOOLS_TIME_H #define TNTDB_CXXTOOLS_TIME_H #include #include #include namespace tntdb { /** This operator can be used to pass a cxxtools::Time object to the database. @code tntdb::Statement stmt = conn.prepare("select ... where tim = :tim"); cxxtools::Time tim(18, 45, 30); stmt.set("tim", tim); @endcode */ inline void operator<< (Hostvar& hostvar, const cxxtools::Time& tim) { hostvar.setTime(Time(tim.hour(), tim.minute(), tim.second(), tim.msec())); } /** This operator can be used to retrieve a cxxtools::Time object from the database. @code tntdb::Statement sel = conn.prepare("select tim from ..."); tntdb::Value v = sel.selectValue(); cxxtools::Time tim; if (v.get(tim)) std::cout << "tim=" << tim.toIsoString() << std::endl; else std::cout << "tim is null" << std::endl; @endcode */ inline bool operator>> (const Value& value, cxxtools::Time& out) { if (value.isNull()) return false; Time tim = value.getTime(); out.set(tim.getHour(), tim.getMinute(), tim.getSecond(), tim.getMillis()); return true; } } #endif // TNTDB_CXXTOOLS_TIME_H tntdb-1.4/include/tntdb/cxxtools/timespan.h000066400000000000000000000107721354703061500211160ustar00rootroot00000000000000/* * Copyright (C) 2016 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_CXXTOOLS_TIMESPAN_H #define TNTDB_CXXTOOLS_TIMESPAN_H #include #include #include namespace tntdb { /** This operator can be used to pass a timespan object to the database. The operator expects a numeric column, which is set to the number of specified units. @code tntdb::Statement stmt = conn.prepare("select ... where ts = :ts"); stmt.set("ts", cxxtools::Milliseconds(500)); @endcode */ inline void operator<< (Hostvar& hostvar, const cxxtools::Microseconds& ts) { hostvar.set(ts.totalUSecs()); } inline void operator<< (Hostvar& hostvar, const cxxtools::Milliseconds& ts) { hostvar.set(Decimal(ts.totalUSecs(), -3)); } inline void operator<< (Hostvar& hostvar, const cxxtools::Seconds& ts) { hostvar.set(Decimal(ts.totalUSecs(), -6)); } inline void operator<< (Hostvar& hostvar, const cxxtools::Minutes& ts) { hostvar.set(Decimal(ts.totalUSecs() / 60, -6)); } inline void operator<< (Hostvar& hostvar, const cxxtools::Hours& ts) { hostvar.set(Decimal(ts.totalUSecs() / 60 / 60, -6)); } inline void operator<< (Hostvar& hostvar, const cxxtools::Days& ts) { hostvar.set(Decimal(ts.totalUSecs() / 60 / 60 / 24, -6)); } /** This operator can be used to retrieve a timespan object from the database. A numeric value is read from the database and interpreted as a number of specified units. @code tntdb::Statement sel = conn.prepare("select tim from ..."); tntdb::Value v = sel.selectValue(); cxxtools::Seconds tim; if (v.get(tim)) std::cout << "tim=" << tim << std::endl; else std::cout << "tim is null" << std::endl; @endcode */ inline bool operator>> (const Value& value, cxxtools::Microseconds& out) { int64_t micros; if (!value.get(micros)) return false; out = cxxtools::Timespan(micros); return true; } inline bool operator>> (const Value& value, cxxtools::Milliseconds& out) { Decimal ts; if (!value.get(ts)) return false; int64_t micros = ts.getInteger(3); out = cxxtools::Timespan(micros); return true; } inline bool operator>> (const Value& value, cxxtools::Seconds& out) { Decimal ts; if (!value.get(ts)) return false; int64_t micros = ts.getInteger(6); out = cxxtools::Timespan(micros); return true; } inline bool operator>> (const Value& value, cxxtools::Minutes& out) { Decimal ts; if (!value.get(ts)) return false; int64_t v = ts.getInteger(9); out = cxxtools::Timespan(v*60/1000); return true; } inline bool operator>> (const Value& value, cxxtools::Hours& out) { Decimal ts; if (!value.get(ts)) return false; int64_t v = ts.getInteger(9); out = cxxtools::Timespan(v*60*60/1000); return true; } inline bool operator>> (const Value& value, cxxtools::Days& out) { Decimal ts; if (!value.get(ts)) return false; int64_t v = ts.getInteger(9); out = cxxtools::Timespan(v*60*60*24/1000); return true; } } #endif // TNTDB_CXXTOOLS_TIMESPAN_H tntdb-1.4/include/tntdb/date.h000066400000000000000000000073151354703061500163270ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_DATE_H #define TNTDB_DATE_H #include namespace tntdb { /// This class holds a date. class Date { private: unsigned short _year; unsigned short _month; unsigned short _day; public: /// Create a Date object with empty values Date() : _year(0), _month(0), _day(0) { } /** Create a date object with the given values No range checks are done. */ Date(unsigned short year, unsigned short month, unsigned short day) : _year(year), _month(month), _day(day) { } static Date localtime(); static Date gmtime(); /// Get the year part of the Date unsigned short getYear() const { return _year; } /// Get the month part of the Date unsigned short getMonth() const { return _month; } /// Get the day part of the Date unsigned short getDay() const { return _day; } /// Get the day of week of the Date (from 0 = sunday to 6 = saturday) unsigned short getWDay() const; bool isNull() const { return _month == 0; } /// Set the date void set(unsigned short year, unsigned short month, unsigned short day) { _year = year; _month = month; _day = day; } /// Get the date in ISO format (yyyy-mm-dd) std::string getIso() const; /** Construct a Date object from the given ISO date string If the string is not in ISO format, an exception of type tntdb::TypeError is thrown. */ static Date fromIso(const std::string& s); bool operator== (const Date& dt) const { return _year == dt._year && _month == dt._month && _day == dt._day; } bool operator!= (const Date& dt) const { return !operator==(dt); } bool operator< (const Date& dt) const { return _year < dt._year ? true : _year > dt._year ? false : _month < dt._month ? true : _month > dt._month ? false : _day < dt._day; } bool operator> (const Date& dt) const { return dt < *this; } bool operator<= (const Date& dt) const { return !(*this > dt); } bool operator>= (const Date& dt) const { return !(*this < dt); } }; } #endif // TNTDB_DATE_H tntdb-1.4/include/tntdb/datetime.h000066400000000000000000000137031354703061500172040ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_DATETIME_H #define TNTDB_DATETIME_H #include #include #include namespace tntdb { /// This class holds a date and a time class Datetime { private: unsigned short _year; unsigned short _month; unsigned short _day; unsigned short _hour; unsigned short _minute; unsigned short _second; unsigned short _millis; public: /// Create a Datetime object with empty values Datetime() : _year(0), _month(0), _day(0), _hour(0), _minute(0), _second(0), _millis(0) { } /// Create a Datetime object with the values from the given Date and Time objects Datetime(const Date& date, const Time& time) : _year(date.getYear()), _month(date.getMonth()), _day(date.getDay()), _hour(time.getHour()), _minute(time.getMinute()), _second(time.getSecond()), _millis(time.getMillis()) { } /** Create a Datetime object with the given values No range checks are done. */ Datetime(unsigned short year, unsigned short month, unsigned short day, unsigned short hour, unsigned short minute, unsigned short second, unsigned short millis = 0) : _year(year), _month(month), _day(day), _hour(hour), _minute(minute), _second(second), _millis(millis) { } static Datetime localtime(); static Datetime gmtime(); /// Get the year part of the Datetime unsigned short getYear() const { return _year; } /// Get the month part of the Datetime unsigned short getMonth() const { return _month; } /// Get the day part of the Datetime unsigned short getDay() const { return _day; } /// Get the hour part of the Datetime unsigned short getHour() const { return _hour; } /// Get the minute part of the Datetime unsigned short getMinute() const { return _minute; } /// Get the second part of the Datetime unsigned short getSecond() const { return _second; } /// Get the millisecond part of the Datetime unsigned short getMillis() const { return _millis; } Date getDate() const { return Date(_year, _month, _day); } Time getTime() const { return Time(_hour, _minute, _second, _millis); } bool isNull() const { return _month == 0; } /// Get the date in ISO format (yyyy-mm-dd hh:mm:ss.hhh) std::string getIso() const; /** Construct a Datetime object from the given ISO datetime string If the string is not in ISO format, an exception of type tntdb::TypeError is thrown. */ static Datetime fromIso(const std::string& s); /** Set the date and the time No range checks are done. */ void set(unsigned short year, unsigned short month, unsigned short day, unsigned short hour, unsigned short minute, unsigned short second, unsigned short millis = 0) { _year = year; _month = month; _day = day; _hour = hour; _minute = minute; _second = second; _millis = millis; } bool operator== (const Datetime& dt) const { return _year == dt._year && _month == dt._month && _day == dt._day && _hour == dt._hour && _minute == dt._minute && _second == dt._second && _millis == dt._millis; } bool operator!= (const Datetime& dt) const { return !operator==(dt); } bool operator< (const Datetime& dt) const { return _year < dt._year ? true : _year > dt._year ? false : _month < dt._month ? true : _month > dt._month ? false : _day < dt._day ? true : _day > dt._day ? false : _hour < dt._hour ? true : _hour > dt._hour ? false : _minute < dt._minute ? true : _minute > dt._minute ? false : _second < dt._second ? true : _second > dt._second ? false : _millis < dt._millis; } bool operator> (const Datetime& dt) const { return dt < *this; } bool operator<= (const Datetime& dt) const { return !(*this > dt); } bool operator>= (const Datetime& dt) const { return !(*this < dt); } }; } #endif // TNTDB_DATETIME_H tntdb-1.4/include/tntdb/decimal.h000066400000000000000000000155761354703061500170200ustar00rootroot00000000000000/* * Copyright (C) 2007,2012 Tommi Maekitalo, Mark Wright * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_DECIMAL_H #define TNTDB_DECIMAL_H #include #include #include #include namespace tntdb { class Decimal { public: #ifdef HAVE_LONG_LONG typedef long long LongType; #else typedef long LongType; #endif #ifdef HAVE_UNSIGNED_LONG_LONG typedef unsigned long long UnsignedLongType; #else typedef unsigned long UnsignedLongType; #endif private: // inf: _mantissa is empty, _exponent = numeric_limits::max() // nan: _mantissa is empty, _exponent==0 std::string _mantissa; // just '0'-'9' short _exponent; bool _negative; Decimal(const std::string& mantissa, short exponent, bool negative) : _mantissa(mantissa), _exponent(exponent), _negative(negative) { } friend class Parser; LongType _getInteger(LongType min, LongType max, short exponent) const; UnsignedLongType _getUnsigned(UnsignedLongType max, short exponent) const; template IntType _getInteger(short exponent) const { return _getInteger(std::numeric_limits::min(), std::numeric_limits::max(), exponent); } template UnsignedType _getUnsigned(short exponent) const { return _getUnsigned(std::numeric_limits::max(), exponent); } void _getInteger(short& ret, short exponent) const { ret = _getInteger(exponent); } void _getInteger(int& ret, short exponent) const { ret = _getInteger(exponent); } void _getInteger(long& ret, short exponent) const { ret = _getInteger(exponent); } #ifdef HAVE_LONG_LONG void _getInteger(long long& ret, short exponent) const { ret = _getInteger(exponent); } #endif void _getInteger(unsigned short& ret, short exponent) const { ret = _getUnsigned(exponent); } void _getInteger(unsigned int& ret, short exponent) const { ret = _getUnsigned(exponent); } void _getInteger(unsigned long& ret, short exponent) const { ret = _getUnsigned(exponent); } #ifdef HAVE_UNSIGNED_LONG_LONG void _getInteger(unsigned long long& ret, short exponent) const { ret = _getUnsigned(exponent); } #endif void _setInteger(LongType l, short exponent); void _setUnsigned(UnsignedLongType l, short exponent); public: class Parser; Decimal(); explicit Decimal(long double value) { setDouble(value); } explicit Decimal(const std::string& value); Decimal(long mantissa, short exponent) { setInteger(mantissa, exponent); } static Decimal infinity() { return Decimal(std::string(), std::numeric_limits::max(), false); } static Decimal nan() { return Decimal(std::string(), 0, false); } const std::string& mantissa() const { return _mantissa; } short exponent() const { return _exponent; } bool negative() const { return _negative; } bool isInfinity(bool positiveInfinity = true) const { return _negative != positiveInfinity && _mantissa.empty() && _exponent == std::numeric_limits::max(); } bool isPositiveInfinity() const { return isInfinity(true); } bool isNegativeInfinity() const { return isInfinity(false); } bool isNaN() const { return _mantissa.empty() && _exponent == 0; } bool isZero() const { return _mantissa == "0"; } void setDouble(long double value); long double getDouble() const; void setInteger(short l, short exponent = 0) { _setInteger(l, exponent); } void setInteger(int l, short exponent = 0) { _setInteger(l, exponent); } void setInteger(long l, short exponent = 0) { _setInteger(l, exponent); } void setInteger(long long l, short exponent = 0) { _setInteger(l, exponent); } void setInteger(unsigned short l, short exponent = 0) { _setUnsigned(l, exponent); } void setInteger(unsigned int l, short exponent = 0) { _setUnsigned(l, exponent); } void setInteger(unsigned long l, short exponent = 0) { _setUnsigned(l, exponent); } void setInteger(unsigned long long l, short exponent = 0) { _setUnsigned(l, exponent); } template IntType getInteger(short exponent = 0) const { IntType ret; _getInteger(ret, exponent); return ret; } std::string toString() const; std::string toStringSci() const; std::string toStringFix() const; Decimal operator- () const { return Decimal(_mantissa, _exponent, !_negative); } bool operator== (const Decimal& other) const { return !isNaN() && _mantissa == other._mantissa && _exponent == other._exponent && _negative == other._negative; } bool operator!= (const Decimal& other) const { return !(*this == other); } bool operator< (const Decimal& other) const; bool operator> (const Decimal& other) const { return other < *this; } bool operator<= (const Decimal& other) const { return !(other < *this); } bool operator>= (const Decimal& other) const { return !(other > *this); } }; std::istream& operator>> (std::istream& in, Decimal& dec); std::ostream& operator<< (std::ostream& out, const Decimal& dec); } #endif // TNTDB_DECIMAL_H tntdb-1.4/include/tntdb/error.h000066400000000000000000000053521354703061500165420ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_ERROR_H #define TNTDB_ERROR_H #include #include namespace tntdb { /** Base class for database errors All errors are handled by throwing this or a derived class. */ class Error : public std::runtime_error { public: /// Constructor explicit Error(const std::string& msg); }; /// Exception thrown when selectRow or selectValue doesn't fetch any data class NotFound : public Error { public: NotFound(); }; /// Exception thrown when a Value::get...() is called on a NULL value class NullValue : public Error { public: NullValue(); }; /// Exception thrown when a Value can't be converted to a requested type class TypeError : public Error { public: explicit TypeError(const std::string& msg = "type error"); }; /// Exception thrown when the execution of an SQL statement caused an error class SqlError : public Error { std::string sql; public: explicit SqlError(const std::string& sql_, const std::string& msg = "sql error"); ~SqlError() throw() { } const std::string& getSql() const { return sql; } }; class FieldNotFound : public Error { std::string field; public: explicit FieldNotFound(const std::string& field); ~FieldNotFound() throw() { } const std::string& getField() const { return field; } }; } #endif // TNTDB_ERROR_H tntdb-1.4/include/tntdb/iface/000077500000000000000000000000001354703061500163025ustar00rootroot00000000000000tntdb-1.4/include/tntdb/iface/iblob.h000066400000000000000000000073311354703061500175460ustar00rootroot00000000000000/* * Copyright (C) 2007-2008 Tommi Maekitalo * Copyright (C) 2007-2008 Marc Boris Duerner * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_IFACE_IBLOB_H #define TNTDB_IFACE_IBLOB_H #include #include #include namespace tntdb { /** @brief Implementation base of Blob values This class serves as the base for the shared implementation classes used in Blob objects. The non-virtual interface consists of a pointer to the blob-data and its size. The implementor has to override three virtual methods, IBlob::assign, IBlob::create and IBlob::destroy. The main purpose of these methods is to customize memory allocation of blob-data, aswell as the shared implementation class derived from IBlob. A default implementation, called BlobImpl, is provided, that uses new/delete and the implementation class. */ class IBlob : public cxxtools::AtomicRefCounted { public: /** @brief Destructor */ virtual ~IBlob(); /** @brief Assign data of a given length The \a len bytes of the data pointed to by \a data are copied to this blob. */ virtual void assign(const char* data, std::size_t len) = 0; /** @brief Makes sure, the buffer has at least \a len bytes. */ virtual char* reserve(std::size_t len, bool shrink) = 0; /** @brief Create a value implementation Returns a pointer to a implementation class derived from IBlob. IBlob::destroy must be implemented accordingly to destroy this instance. */ virtual IBlob* create() const = 0; /** @brief Destroy a value implementation Destroys an instance previously created by the IBlob::create. */ virtual void destroy() = 0; /** @brief Returns the size of the blob-data. */ std::size_t size() const { return _size; } /** @brief Returns a pointer to the blob-data or 0 if the blob is empty */ const char* data() const { return _data; } /** @brief Returns true if the two instances contain the same data */ bool operator==(const IBlob& other) const { return _size == other._size && ( std::strncmp(_data, other._data, _size) == 0 ); } protected: IBlob() : _data(0) , _size(0) { } char* _data; std::size_t _size; }; } #endif tntdb-1.4/include/tntdb/iface/iconnection.h000066400000000000000000000070321354703061500207650ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_IFACE_ICONNECTION_H #define TNTDB_IFACE_ICONNECTION_H #include #include #include #include namespace tntdb { class Result; class Row; class Value; class Statement; class IStatement; class IConnection : public cxxtools::RefCounted { public: typedef unsigned size_type; virtual void beginTransaction() = 0; virtual void commitTransaction() = 0; virtual void rollbackTransaction() = 0; virtual size_type execute(const std::string& query) = 0; virtual Result select(const std::string& query) = 0; virtual Row selectRow(const std::string& query) = 0; virtual Value selectValue(const std::string& query) = 0; virtual Statement prepare(const std::string& query) = 0; virtual Statement prepareWithLimit(const std::string& query, const std::string& limit, const std::string& offset) = 0; virtual Statement prepareCached(const std::string& query, const std::string& key) = 0; virtual Statement prepareCachedWithLimit(const std::string& query, const std::string& limit, const std::string& offset, const std::string& key) = 0; virtual void clearStatementCache() = 0; virtual bool clearStatementCache(const std::string& key) = 0; virtual bool ping() = 0; virtual long lastInsertId(const std::string& name) = 0; virtual void lockTable(const std::string& tablename, bool exclusive) = 0; // helper function, which replaces '%u' with username and '%p' with password in url static std::string url(const std::string& url, const std::string& username, const std::string& password); }; class IStmtCacheConnection : public IConnection { typedef std::map > stmtCacheType; stmtCacheType stmtCache; public: virtual Statement prepareCached(const std::string& query, const std::string& key); virtual Statement prepareCachedWithLimit(const std::string& query, const std::string& limit, const std::string& offset, const std::string& key); virtual void clearStatementCache(); virtual bool clearStatementCache(const std::string& key); }; } #endif // TNTDB_IFACE_ICONNECTION_H tntdb-1.4/include/tntdb/iface/iconnectionmanager.h000066400000000000000000000043321354703061500223200ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_IFACE_ICONNECTIONMANAGER_H #define TNTDB_IFACE_ICONNECTIONMANAGER_H #include #define TNTDB_DRIVER_PRAEFIX connectionManager1_ #define TNTDB_CONNECTIONMANAGER_DECLARE(drivername) \ extern "C" { extern tntdb::drivername::ConnectionManager connectionManager1_ ## drivername; } #define TNTDB_CONNECTIONMANAGER_DEFINE(drivername) \ extern "C" { tntdb::drivername::ConnectionManager connectionManager1_ ## drivername; } namespace tntdb { class Connection; class IConnectionManager { IConnectionManager(const IConnectionManager&) { } IConnectionManager& operator=(const IConnectionManager&) { return *this; } public: IConnectionManager() { } virtual ~IConnectionManager() { } virtual Connection connect(const std::string& url, const std::string& username, const std::string& password) = 0; }; } #endif // TNTDB_IFACE_ICONNECTIONMANAGER_H tntdb-1.4/include/tntdb/iface/icursor.h000066400000000000000000000031221354703061500201370ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_IFACE_ICURSOR_H #define TNTDB_IFACE_ICURSOR_H #include namespace tntdb { class Row; class ICursor : public cxxtools::RefCounted { public: virtual Row fetch() = 0; }; } #endif // TNTDB_IFACE_ICURSOR_H tntdb-1.4/include/tntdb/iface/iresult.h000066400000000000000000000034541354703061500201500ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_IFACE_IRESULT_H #define TNTDB_IFACE_IRESULT_H #include namespace tntdb { class Row; /// common inteface for resultset class IResult : public cxxtools::RefCounted { public: typedef unsigned size_type; typedef Row value_type; virtual Row getRow(size_type tup_num) const = 0; virtual size_type size() const = 0; virtual size_type getFieldCount() const = 0; }; } #endif // TNTDB_IFACE_IRESULT_H tntdb-1.4/include/tntdb/iface/irow.h000066400000000000000000000036071354703061500174410ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_IFACE_IROW_H #define TNTDB_IFACE_IROW_H #include #include namespace tntdb { class Value; /// common interface for row-types class IRow : public cxxtools::RefCounted { public: typedef unsigned size_type; virtual size_type size() const = 0; virtual Value getValueByNumber(size_type field_num) const = 0; virtual Value getValueByName(const std::string& field_name) const = 0; virtual std::string getColumnName(size_type field_num) const = 0; }; } #endif // TNTDB_IFACE_IROW_H tntdb-1.4/include/tntdb/iface/istatement.h000066400000000000000000000073471354703061500206430ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_IFACE_ISTATEMENT_H #define TNTDB_IFACE_ISTATEMENT_H #include #include #include #include namespace tntdb { class Result; class Row; class Value; class Date; class Time; class Datetime; class Decimal; class ICursor; class Blob; class IStatement : public cxxtools::RefCounted { public: typedef unsigned size_type; virtual void clear() = 0; virtual void setNull(const std::string& col) = 0; virtual void setBool(const std::string& col, bool data) = 0; virtual void setShort(const std::string& col, short data) = 0; virtual void setInt(const std::string& col, int data) = 0; virtual void setLong(const std::string& col, long data) = 0; virtual void setUnsignedShort(const std::string& col, unsigned short data) = 0; virtual void setUnsigned(const std::string& col, unsigned data) = 0; virtual void setUnsignedLong(const std::string& col, unsigned long data) = 0; virtual void setInt32(const std::string& col, int32_t data) = 0; virtual void setUnsigned32(const std::string& col, uint32_t data) = 0; virtual void setInt64(const std::string& col, int64_t data) = 0; virtual void setUnsigned64(const std::string& col, uint64_t data) = 0; virtual void setDecimal(const std::string& col, const Decimal& data) = 0; virtual void setFloat(const std::string& col, float data) = 0; virtual void setDouble(const std::string& col, double data) = 0; virtual void setChar(const std::string& col, char data) = 0; virtual void setString(const std::string& col, const std::string& data) = 0; virtual void setBlob(const std::string& col, const Blob& data) = 0; virtual void setDate(const std::string& col, const Date& data) = 0; virtual void setTime(const std::string& col, const Time& data) = 0; virtual void setDatetime(const std::string& col, const Datetime& data) = 0; virtual void setUString(const std::string& col, const cxxtools::String& data); virtual size_type execute() = 0; virtual Result select() = 0; virtual Row selectRow() = 0; virtual Value selectValue() = 0; virtual ICursor* createCursor(unsigned fetchsize) = 0; virtual void maxNumDelay(size_type n); virtual size_type numDelayed() const; virtual size_type flush(); }; } #endif // TNTDB_IFACE_ISTATEMENT_H tntdb-1.4/include/tntdb/iface/ivalue.h000066400000000000000000000053231354703061500177430ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_IFACE_IVALUE_H #define TNTDB_IFACE_IVALUE_H #include #include #include #include namespace tntdb { class Date; class Time; class Datetime; class Decimal; class Blob; /// common inteface for resultvalues class IValue : public cxxtools::RefCounted { public: virtual bool isNull() const = 0; virtual bool getBool() const = 0; virtual short getShort() const = 0; virtual int getInt() const = 0; virtual long getLong() const = 0; virtual unsigned getUnsigned() const = 0; virtual unsigned short getUnsignedShort() const = 0; virtual unsigned long getUnsignedLong() const = 0; virtual int32_t getInt32() const = 0; virtual uint32_t getUnsigned32() const = 0; virtual int64_t getInt64() const = 0; virtual uint64_t getUnsigned64() const = 0; virtual Decimal getDecimal() const = 0; virtual float getFloat() const = 0; virtual double getDouble() const = 0; virtual char getChar() const = 0; virtual void getString(std::string& ret) const = 0; virtual void getBlob(Blob& ret) const = 0; virtual Date getDate() const = 0; virtual Time getTime() const = 0; virtual Datetime getDatetime() const = 0; virtual void getUString(cxxtools::String& ret) const; }; } #endif // TNTDB_IFACE_IVALUE_H tntdb-1.4/include/tntdb/impl/000077500000000000000000000000001354703061500161745ustar00rootroot00000000000000tntdb-1.4/include/tntdb/impl/blob.h000066400000000000000000000050421354703061500172640ustar00rootroot00000000000000/* * Copyright (C) 2007-2008 Tommi Maekitalo * Copyright (C) 2007-2008 Marc Boris Duerner * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_IMPL_BLOB_H #define TNTDB_IMPL_BLOB_H #include namespace tntdb { /** @brief Default Blob value implementation This implementation uses new/delete to create and destroy the shared objects and new/delete to allocate memory for the blob-data. */ class BlobImpl : public IBlob { public: BlobImpl() { } ~BlobImpl() { delete[] _data; } virtual void assign(const char* data, std::size_t len); virtual char* reserve(std::size_t len, bool shrink); virtual IBlob* create() const; virtual void destroy(); static BlobImpl* emptyInstance() { static BlobImpl empty(1); return ∅ } protected: // ctor, which constructs a instance, with a reference-counter of 1 explicit BlobImpl(int) { addRef(); } }; /** @internal Initialize statics in BlobImpl during static initialization Thread-safety. */ static struct BlobDataInitializer { BlobDataInitializer() { BlobImpl::emptyInstance(); } } tntdb_blobdata_initializer; } #endif // TNTDB_IMPL_BLOB_H tntdb-1.4/include/tntdb/impl/poolconnection.h000066400000000000000000000054401354703061500214010ustar00rootroot00000000000000/* * Copyright (C) 2006 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_IMPL_POOLCONNECTION_H #define TNTDB_IMPL_POOLCONNECTION_H #include #include namespace tntdb { class PoolConnection : public IConnection { ConnectionPool::PoolObjectType connection; bool inTransaction; bool drop; public: PoolConnection(ConnectionPool::PoolObjectType connection); ~PoolConnection(); virtual void beginTransaction(); virtual void commitTransaction(); virtual void rollbackTransaction(); virtual size_type execute(const std::string& query); virtual Result select(const std::string& query); virtual Row selectRow(const std::string& query); virtual Value selectValue(const std::string& query); virtual Statement prepare(const std::string& query); virtual Statement prepareWithLimit(const std::string& query, const std::string& limit, const std::string& offset); virtual Statement prepareCached(const std::string& query, const std::string& key); virtual Statement prepareCachedWithLimit(const std::string& query, const std::string& limit, const std::string& offset, const std::string& key); virtual void clearStatementCache(); virtual bool clearStatementCache(const std::string& key); virtual bool ping(); virtual long lastInsertId(const std::string& name); virtual void lockTable(const std::string& tablename, bool exclusive); }; } #endif // TNTDB_IMPL_POOLCONNECTION_H tntdb-1.4/include/tntdb/impl/result.h000066400000000000000000000040101354703061500176560ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_IMPL_RESULT_H #define TNTDB_IMPL_RESULT_H #include #include #include namespace tntdb { class ResultImpl : public IResult { public: typedef std::vector data_type; private: data_type data; public: ResultImpl() { } explicit ResultImpl(const data_type& data_) : data(data_) { } // methods from IResult virtual Row getRow(size_type tup_num) const; virtual size_type size() const; virtual size_type getFieldCount() const; // specific methods void add(const Row& row) { data.push_back(row); } }; } #endif // TNTDB_IMPL_RESULT_H tntdb-1.4/include/tntdb/impl/row.h000066400000000000000000000046271354703061500171650ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_IMPL_ROW_H #define TNTDB_IMPL_ROW_H #include #include #include namespace tntdb { class RowImpl : public IRow { public: struct ValueType { std::string name; Value value; ValueType() { } ValueType(const std::string& name_, const Value& value_) : name(name_), value(value_) { } }; typedef std::vector data_type; private: data_type data; public: RowImpl() { } explicit RowImpl(const data_type& data_) : data(data_) { } // methods from IResult virtual size_type size() const; virtual Value getValueByNumber(size_type field_num) const; virtual Value getValueByName(const std::string& field_name) const; virtual std::string getColumnName(size_type field_num) const; // specific methods void add(const std::string& field_name, const Value& value) { data.push_back(ValueType(field_name, value)); } }; } #endif // TNTDB_IMPL_ROW_H tntdb-1.4/include/tntdb/impl/value.h000066400000000000000000000050571354703061500174700ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_IMPL_VALUE_H #define TNTDB_IMPL_VALUE_H #include namespace tntdb { class ValueImpl : public IValue { bool null; std::string data; public: ValueImpl() : null(true) { } ValueImpl(const std::string& d) : null(false), data(d) { } virtual bool isNull() const; virtual bool getBool() const; virtual short getShort() const; virtual int getInt() const; virtual long getLong() const; virtual unsigned short getUnsignedShort() const; virtual unsigned getUnsigned() const; virtual unsigned long getUnsignedLong() const; virtual int32_t getInt32() const; virtual uint32_t getUnsigned32() const; virtual int64_t getInt64() const; virtual uint64_t getUnsigned64() const; virtual Decimal getDecimal() const; virtual float getFloat() const; virtual double getDouble() const; virtual char getChar() const; virtual void getString(std::string& ret) const; virtual void getBlob(Blob& ret) const; virtual Date getDate() const; virtual Time getTime() const; virtual Datetime getDatetime() const; }; } #endif // TNTDB_IMPL_VALUE_H tntdb-1.4/include/tntdb/librarymanager.h000066400000000000000000000037621354703061500204130ustar00rootroot00000000000000/* * Copyright (C) 2006 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_LIBRARYMANAGER_H #define TNTDB_LIBRARYMANAGER_H #include #include #include #include #include namespace tntdb { class LibraryManager { cxxtools::Library lib; IConnectionManager* connectionManager; public: LibraryManager() : connectionManager(0) { } LibraryManager(const std::string& libname); Connection connect(const std::string& url, const std::string& username, const std::string& password) { return connectionManager->connect(url, username, password); } }; } #endif // TNTDB_LIBRARYMANAGER_H tntdb-1.4/include/tntdb/mysql/000077500000000000000000000000001354703061500164005ustar00rootroot00000000000000tntdb-1.4/include/tntdb/mysql/bindutils.h000066400000000000000000000116061354703061500205520ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_MYSQL_BINDUTILS_H #define TNTDB_MYSQL_BINDUTILS_H #include #include #include namespace tntdb { class Blob; class Date; class Time; class Datetime; class Decimal; namespace mysql { void setNull(MYSQL_BIND& value); void setBool(MYSQL_BIND& value, bool data); void setShort(MYSQL_BIND& value, short data); void setInt(MYSQL_BIND& value, int data); void setLong(MYSQL_BIND& value, long data); void setUnsignedShort(MYSQL_BIND& value, unsigned short data); void setUnsigned(MYSQL_BIND& value, unsigned data); void setUnsignedLong(MYSQL_BIND& value, unsigned long data); void setInt32(MYSQL_BIND& value, int32_t data); void setUnsigned32(MYSQL_BIND& value, uint32_t data); void setInt64(MYSQL_BIND& value, int64_t data); void setUnsigned64(MYSQL_BIND& value, uint64_t data); void setDecimal(MYSQL_BIND& value, unsigned long& length, const Decimal& data); void setFloat(MYSQL_BIND& value, float data); void setDouble(MYSQL_BIND& value, double data); void setChar(MYSQL_BIND& value, unsigned long& length, char data); void setString(MYSQL_BIND& value, unsigned long& length, const char* data); void setString(MYSQL_BIND& value, unsigned long& length, const std::string& data); void setBlob(MYSQL_BIND& value, unsigned long& length, const Blob& data); void setDate(MYSQL_BIND& value, const Date& data); void setTime(MYSQL_BIND& value, const Time& data); void setDatetime(MYSQL_BIND& value, const Datetime& data); bool isNull(const MYSQL_BIND& value); bool getBool(const MYSQL_BIND& value); short getShort(const MYSQL_BIND& value); int getInt(const MYSQL_BIND& value); long getLong(const MYSQL_BIND& value); unsigned getUnsigned(const MYSQL_BIND& value); unsigned short getUnsignedShort(const MYSQL_BIND& value); unsigned long getUnsignedLong(const MYSQL_BIND& value); int32_t getInt32(const MYSQL_BIND& value); uint32_t getUnsigned32(const MYSQL_BIND& value); int64_t getInt64(const MYSQL_BIND& value); uint64_t getUnsigned64(const MYSQL_BIND& value); Decimal getDecimal(const MYSQL_BIND& value); long getLong(const MYSQL_BIND& value); float getFloat(const MYSQL_BIND& value); double getDouble(const MYSQL_BIND& value); char getChar(const MYSQL_BIND& value); void getString(const MYSQL_BIND& value, std::string& ret); void getBlob(const MYSQL_BIND& value, Blob& ret); Date getDate(const MYSQL_BIND& value); Time getTime(const MYSQL_BIND& value); Datetime getDatetime(const MYSQL_BIND& value); void transferValue(MYSQL_BIND& fromValue, MYSQL_BIND& toValue, bool doRelease = true); void copyValue(const MYSQL_BIND& fromValue, MYSQL_BIND& toValue, bool doRelease = true); void refValue(const MYSQL_BIND& fromValue, MYSQL_BIND& toValue, bool doRelease = true); void releaseValue(MYSQL_BIND& value); void release(MYSQL_BIND& bind); void reserve(MYSQL_BIND& bind, unsigned long size); void reserveKeep(MYSQL_BIND& bind, unsigned long size); template void setValue(MYSQL_BIND& bind, c_type value, enum_field_types mysql_type) { reserve(bind, sizeof(c_type)); *static_cast(bind.buffer) = value; bind.buffer_type = mysql_type; bind.is_null = 0; } } } #endif // TNTDB_MYSQL_BINDUTILS_H tntdb-1.4/include/tntdb/mysql/bindvalues.h000066400000000000000000000137401354703061500207120ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_MYSQL_BINDVALUES_H #define TNTDB_MYSQL_BINDVALUES_H #include #include #include #include namespace tntdb { namespace mysql { class BindValues { unsigned valuesSize; MYSQL_BIND* values; struct BindAttributes { unsigned long length; my_bool isNull; std::string name; BindAttributes() : length(0), isNull(true) { } }* bindAttributes; // non copyable BindValues(const BindValues&); BindValues& operator=(const BindValues&); public: explicit BindValues(unsigned n); BindValues(); ~BindValues(); MYSQL_BIND* getMysqlBind() const { return values; } void setSize(unsigned n); unsigned getSize() const { return valuesSize; } void setNull(unsigned n) { mysql::setNull(values[n]); } void setBool(unsigned n, bool data) { mysql::setBool(values[n], data); } void setShort(unsigned n, short data) { mysql::setShort(values[n], data); } void setInt(unsigned n, int data) { mysql::setInt(values[n], data); } void setLong(unsigned n, int data) { mysql::setLong(values[n], data); } void setUnsignedShort(unsigned n, unsigned short data) { mysql::setUnsignedShort(values[n], data); } void setUnsigned(unsigned n, unsigned data) { mysql::setUnsigned(values[n], data); } void setUnsignedLong(unsigned n, unsigned data) { mysql::setUnsignedLong(values[n], data); } void setInt32(unsigned n, int32_t data) { mysql::setInt32(values[n], data); } void setUnsigned32(unsigned n, uint32_t data) { mysql::setUnsigned32(values[n], data); } void setInt64(unsigned n, int64_t data) { mysql::setInt64(values[n], data); } void setUnsigned64(unsigned n, uint64_t data) { mysql::setUnsigned64(values[n], data); } void setDecimal(unsigned n, const Decimal& data) { mysql::setDecimal(values[n], bindAttributes[n].length, data); } void setFloat(unsigned n, float data) { mysql::setFloat(values[n], data); } void setDouble(unsigned n, double data) { mysql::setDouble(values[n], data); } void setChar(unsigned n, char data) { mysql::setChar(values[n], bindAttributes[n].length, data); } void setString(unsigned n, const char* data) { mysql::setString(values[n], bindAttributes[n].length, data); } void setString(unsigned n, const std::string& data) { mysql::setString(values[n], bindAttributes[n].length, data); } void setBlob(unsigned n, const Blob& data) { mysql::setBlob(values[n], bindAttributes[n].length, data); } void setDate(unsigned n, const Date& data) { mysql::setDate(values[n], data); } void setTime(unsigned n, const Time& data) { mysql::setTime(values[n], data); } void setDatetime(unsigned n, const Datetime& data) { mysql::setDatetime(values[n], data); } bool isNull(unsigned n) const { return mysql::isNull(values[n]); } bool getBool(unsigned n) const { return mysql::getBool(values[n]); } int getInt(unsigned n) const { return mysql::getInt(values[n]); } unsigned getUnsigned(unsigned n) const { return mysql::getUnsigned(values[n]); } int32_t getInt32(unsigned n) const { return mysql::getInt32(values[n]); } uint32_t getUnsigned32(unsigned n) const { return mysql::getUnsigned32(values[n]); } int64_t getInt64(unsigned n) const { return mysql::getInt64(values[n]); } uint64_t getUnsigned64(unsigned n) const { return mysql::getUnsigned64(values[n]); } Decimal getDecimal(unsigned n) const { return mysql::getDecimal(values[n]); } long getLong(unsigned n) const { return mysql::getLong(values[n]); } float getFloat(unsigned n) const { return mysql::getFloat(values[n]); } double getDouble(unsigned n) const { return mysql::getDouble(values[n]); } char getChar(unsigned n) const { return mysql::getChar(values[n]); } void getString(unsigned n, std::string& ret) const { mysql::getString(values[n], ret); } const std::string& getName(unsigned n) const { return bindAttributes[n].name; } void initOutBuffer(unsigned n, MYSQL_FIELD& f); void clear(); }; } } #endif // TNTDB_MYSQL_BINDVALUES_H tntdb-1.4/include/tntdb/mysql/cursor.h000066400000000000000000000027741354703061500201000ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_MYSQL_CURSOR_H #define TNTDB_MYSQL_CURSOR_H #include #include #endif // TNTDB_MYSQL_CURSOR_H tntdb-1.4/include/tntdb/mysql/error.h000066400000000000000000000036571354703061500177150ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_MYSQL_ERROR_H #define TNTDB_MYSQL_ERROR_H #include #include namespace tntdb { namespace mysql { class MysqlError : public Error { protected: MysqlError(const std::string& msg) : Error(msg) { } public: MysqlError(MYSQL* mysql); MysqlError(const char* function, MYSQL* mysql); }; class MysqlStmtError : public MysqlError { public: MysqlStmtError(MYSQL_STMT* stmt); MysqlStmtError(const char* function, MYSQL_STMT* stmt); }; } } #endif // TNTDB_MYSQL_ERROR_H tntdb-1.4/include/tntdb/mysql/impl/000077500000000000000000000000001354703061500173415ustar00rootroot00000000000000tntdb-1.4/include/tntdb/mysql/impl/boundrow.h000066400000000000000000000036511354703061500213560ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_MYSQL_IMPL_BOUNDROW_H #define TNTDB_MYSQL_IMPL_BOUNDROW_H #include #include namespace tntdb { namespace mysql { class BoundRow : public IRow, public BindValues { public: explicit BoundRow(unsigned n) : BindValues(n) { } size_type size() const; Value getValueByNumber(size_type field_num) const; Value getValueByName(const std::string& field_name) const; std::string getColumnName(size_type field_num) const; }; } } #endif // TNTDB_MYSQL_IMPL_BOUNDROW_H tntdb-1.4/include/tntdb/mysql/impl/boundvalue.h000066400000000000000000000055641354703061500216700ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_MYSQL_IMPL_BOUNDVALUE_H #define TNTDB_MYSQL_IMPL_BOUNDVALUE_H #include #include #include #include namespace tntdb { class Date; class Time; class Datetime; class Decimal; namespace mysql { class BoundValue : public IValue { public: typedef unsigned size_type; private: cxxtools::SmartPtr row; MYSQL_BIND& mysql_bind; public: BoundValue(IRow* row_, MYSQL_BIND& bind) : row(row_), mysql_bind(bind) { } virtual bool isNull() const; virtual bool getBool() const; virtual short getShort() const; virtual int getInt() const; virtual long getLong() const; virtual unsigned getUnsigned() const; virtual unsigned short getUnsignedShort() const; virtual unsigned long getUnsignedLong() const; virtual int32_t getInt32() const; virtual uint32_t getUnsigned32() const; virtual int64_t getInt64() const; virtual uint64_t getUnsigned64() const; virtual Decimal getDecimal() const; virtual float getFloat() const; virtual double getDouble() const; virtual char getChar() const; virtual void getString(std::string& ret) const; virtual void getBlob(Blob& ret) const; virtual Date getDate() const; virtual Time getTime() const; virtual Datetime getDatetime() const; }; } } #endif // TNTDB_MYSQL_IMPL_BOUNDVALUE_H tntdb-1.4/include/tntdb/mysql/impl/connection.h000066400000000000000000000100401354703061500216440ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_MYSQL_IMPL_CONNECTION_H #define TNTDB_MYSQL_IMPL_CONNECTION_H #include #include namespace tntdb { /** This namespace contains the implementation of the Mysql driver for tntdb. The driver makes it possible to access a Mysql database using tntdb. To get a connection to a Mysql database, the dburl to the tntdb::connect function must start with "mysql:". The remaining is a list of name value pairs separated by semicolon. The names and values are separated by '='. The value may be quoted by single or double quotes. Quote characters inside quoted values may be escaped using a backspace. If the value contains itself a backspace character, it must be doubled. Indeed each character prefixed with backspace is kept as is into the value. A typical connection with a Mysql driver looks like that: @code tntdb::Connection conn = tntdb::connect("mysql:db=DS2;user=web;passwd='foo\\'bar"); @endcode Here the username is "web" and the password is "foo'bar". Note that the backslash itself must be doubled in C++ code since the compiler processes the backspace first. */ namespace mysql { /// Implements a connection to a Mysql database. class Connection : public IStmtCacheConnection { MYSQL mysql; bool initialized; unsigned transactionActive; std::string lockTablesQuery; void open(const char* app, const char* host, const char* user, const char* passwd, const char* db, unsigned int port, const char* unix_socket, unsigned long client_flag); public: Connection(const std::string& conn, const std::string& username, const std::string& password); Connection(const char* app, const char* host, const char* user, const char* passwd, const char* db, unsigned int port = 3306, const char* unix_socket = 0, unsigned long client_flag = 0); ~Connection(); MYSQL* getHandle() { return &mysql; } void beginTransaction(); void commitTransaction(); void rollbackTransaction(); size_type execute(const std::string& query); tntdb::Result select(const std::string& query); tntdb::Row selectRow(const std::string& query); tntdb::Value selectValue(const std::string& query); tntdb::Statement prepare(const std::string& query); tntdb::Statement prepareWithLimit(const std::string& query, const std::string& limit, const std::string& offset); bool ping(); long lastInsertId(const std::string& name); void lockTable(const std::string& tablename, bool exclusive); }; } } #endif // TNTDB_MYSQL_IMPL_CONNECTION_H tntdb-1.4/include/tntdb/mysql/impl/connectionmanager.h000066400000000000000000000034441354703061500232110ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_MYSQL_IMPL_CONNECTIONMANAGER_H #define TNTDB_MYSQL_IMPL_CONNECTIONMANAGER_H #include namespace tntdb { namespace mysql { class ConnectionManager : public IConnectionManager { public: tntdb::Connection connect(const std::string& url, const std::string& username, const std::string& password); }; } } TNTDB_CONNECTIONMANAGER_DECLARE(mysql) #endif // TNTDB_MYSQL_IMPL_CONNECTIONMANAGER_H tntdb-1.4/include/tntdb/mysql/impl/cursor.h000066400000000000000000000036561354703061500210410ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_MYSQL_IMPL_CURSOR_H #define TNTDB_MYSQL_IMPL_CURSOR_H #include #include #include namespace tntdb { namespace mysql { class BoundRow; class Statement; class Cursor : public ICursor { cxxtools::SmartPtr row; cxxtools::SmartPtr mysqlStatement; MYSQL_STMT* stmt; public: Cursor(Statement* statement, unsigned fetchsize); ~Cursor(); // method for ICursor Row fetch(); }; } } #endif // TNTDB_MYSQL_IMPL_CURSOR_H tntdb-1.4/include/tntdb/mysql/impl/result.h000066400000000000000000000037661354703061500210440ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_MYSQL_IMPL_RESULT_H #define TNTDB_MYSQL_IMPL_RESULT_H #include #include #include namespace tntdb { namespace mysql { class Result : public IResult { tntdb::Connection conn; MYSQL* mysql; MYSQL_RES* result; size_type field_count; public: Result(const tntdb::Connection& c, MYSQL* m, MYSQL_RES* r); ~Result(); MYSQL_RES* getMysqlRes() const { return result; } Row getRow(size_type tup_num) const; size_type size() const; size_type getFieldCount() const; }; } } #endif // TNTDB_MYSQL_IMPL_RESULT_H tntdb-1.4/include/tntdb/mysql/impl/resultrow.h000066400000000000000000000041011354703061500215540ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_MYSQL_IMPL_RESULTROW_H #define TNTDB_MYSQL_IMPL_RESULTROW_H #include #include #include namespace tntdb { namespace mysql { /// Row of a result-set of type Result class ResultRow : public IRow { Result result; MYSQL_ROW row; unsigned long* lengths; MYSQL_FIELD* fields; public: ResultRow(const tntdb::Result& result_, MYSQL_RES* res, MYSQL_ROW row_); unsigned size() const; Value getValueByNumber(size_type field_num) const; Value getValueByName(const std::string& field_name) const; std::string getColumnName(size_type field_num) const; }; } } #endif // TNTDB_MYSQL_IMPL_RESULTROW_H tntdb-1.4/include/tntdb/mysql/impl/rowcontainer.h000066400000000000000000000036221354703061500222270ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_MYSQL_IMPL_ROWCONTAINER_H #define TNTDB_MYSQL_IMPL_ROWCONTAINER_H #include #include #include #include namespace tntdb { namespace mysql { class RowContainer : public IResult { std::vector > rows; public: void addRow(IRow* row) { rows.push_back(row); } Row getRow(size_type tup_num) const; size_type size() const; size_type getFieldCount() const; }; } } #endif // TNTDB_MYSQL_IMPL_ROWCONTAINER_H tntdb-1.4/include/tntdb/mysql/impl/rowvalue.h000066400000000000000000000060131354703061500213560ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_MYSQL_IMPL_ROWVALUE_H #define TNTDB_MYSQL_IMPL_ROWVALUE_H #include #include #include namespace tntdb { namespace mysql { class RowValue : public IValue { public: typedef unsigned size_type; private: Result result; MYSQL_ROW row; size_type col; size_type len; public: RowValue(const Result result_, MYSQL_ROW row_, size_type col_, size_type len_) : result(result_), row(row_), col(col_), len(len_) { } size_type size() const { return len; } virtual bool isNull() const; virtual bool getBool() const; virtual short getShort() const; virtual int getInt() const; virtual long getLong() const; virtual unsigned short getUnsignedShort() const; virtual unsigned getUnsigned() const; virtual unsigned long getUnsignedLong() const; virtual int32_t getInt32() const; virtual uint32_t getUnsigned32() const; virtual int64_t getInt64() const; virtual uint64_t getUnsigned64() const; virtual Decimal getDecimal() const; virtual float getFloat() const; virtual double getDouble() const; virtual char getChar() const; virtual void getString(std::string& ret) const; virtual void getBlob(Blob& ret) const; virtual Date getDate() const; virtual Time getTime() const; virtual Datetime getDatetime() const; std::string getString() const { std::string ret; getString(ret); return ret; } }; } } #endif // TNTDB_MYSQL_IMPL_ROWVALUE_H tntdb-1.4/include/tntdb/mysql/impl/statement.h000066400000000000000000000107301354703061500215170ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_MYSQL_IMPL_SQLSTATEMENT_H #define TNTDB_MYSQL_IMPL_SQLSTATEMENT_H #include #include #include #include #include #include namespace tntdb { namespace mysql { class Statement : public IStatement { typedef std::multimap hostvarMapType; Connection* conn; std::string query; BindValues inVars; hostvarMapType hostvarMap; MYSQL* mysql; MYSQL_STMT* stmt; MYSQL_FIELD* fields; unsigned field_count; cxxtools::SmartPtr rowPtr; cxxtools::SmartPtr getRow(); cxxtools::SmartPtr fetchRow(); public: Statement(Connection* conn, MYSQL* mysql, const std::string& query); ~Statement(); // methods of IStatement void clear(); void setNull(const std::string& col); void setBool(const std::string& col, bool data); void setShort(const std::string& col, short data); void setInt(const std::string& col, int data); void setLong(const std::string& col, long data); void setUnsignedShort(const std::string& col, unsigned short data); void setUnsigned(const std::string& col, unsigned data); void setUnsignedLong(const std::string& col, unsigned long data); void setInt32(const std::string& col, int32_t data); void setUnsigned32(const std::string& col, uint32_t data); void setInt64(const std::string& col, int64_t data); void setUnsigned64(const std::string& col, uint64_t data); void setDecimal(const std::string& col, const Decimal& data); void setFloat(const std::string& col, float data); void setDouble(const std::string& col, double data); void setChar(const std::string& col, char data); void setString(const std::string& col, const std::string& data); void setBlob(const std::string& col, const Blob& data); void setDate(const std::string& col, const Date& data); void setTime(const std::string& col, const Time& data); void setDatetime(const std::string& col, const Datetime& data); size_type execute(); tntdb::Result select(); tntdb::Row selectRow(); tntdb::Value selectValue(); ICursor* createCursor(unsigned fetchsize); // specfic methods /// getStmt returns a MYSQL_STMT. The caller is responsable to close /// the statement. If this class has already prepared a statement, /// this is returned and removed from this class. MYSQL_STMT* getStmt(); void execute(MYSQL_STMT* stmt, unsigned fetchsize); /// Statement-handles retrieved by getStmt can be offered for reuse /// with this method. Ownership is transfered back to this class. /// If there is already a statement, the offered statement is closed. void putback(MYSQL_STMT* stmt); MYSQL_FIELD* getFields(); unsigned getFieldCount(); }; } } #endif // TNTDB_MYSQL_IMPL_SQLSTATEMENT_H tntdb-1.4/include/tntdb/oracle/000077500000000000000000000000001354703061500165005ustar00rootroot00000000000000tntdb-1.4/include/tntdb/oracle/blob.h000066400000000000000000000046411354703061500175740ustar00rootroot00000000000000/* * Copyright (C) 2008 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_ORACLE_BLOB_H #define TNTDB_ORACLE_BLOB_H #include #include #include #include #include #include #include namespace tntdb { namespace oracle { class Blob { Connection* conn; OCILobLocator* lob; bool release; // low-level wrappers void ociDescriptorAlloc(); void ociDescriptorFree(); Blob(const Blob&) { } Blob& operator=(const Blob&) { return *this; } public: Blob() : lob(0), release(false) { } Blob(Connection* conn, OCILobLocator* lob, bool release = false); Blob(Connection* conn, const char* data, ub4 count); ~Blob() { if (release && lob) ociDescriptorFree(); } void allocateHandle(); void setData(Connection* conn, const char* data, ub4 count); void getData(tntdb::Blob& ret) const; OCILobLocator*& getHandle(Connection* conn); }; } } #endif // TNTDB_ORACLE_BLOB_H tntdb-1.4/include/tntdb/oracle/connection.h000066400000000000000000000102261354703061500210110ustar00rootroot00000000000000/* * Copyright (C) 2007 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_ORACLE_CONNECTION_H #define TNTDB_ORACLE_CONNECTION_H #include #include #include #include #include namespace tntdb { /** This namespace contains the implementation of the Oracle driver for tntdb. Note that the oracle driver is not compiled by default when tntdb is built. It must be enabled using the configure switch --with-oracle. The driver makes it possible to access a Oracle database using tntdb. To get a connection to a Oracle database, the dburl to the tntdb::connect function must start with "oracle:". The remaining string specifies the connection parameters to the oracle database. The attributes user and passwd are extracted and the rest is passed to the `OCIServerAttach` function of OCI. A typical connection with a Oracle driver looks like that: @code tntdb::Connection conn = tntdb::connect("oracle:XE;user=hr;passwd=hr"); @endcode */ namespace oracle { class Connection : public IStmtCacheConnection { OCIEnv* envhp; /* the environment handle */ OCIServer* srvhp; /* the server handle */ OCIError* errhp; /* the error handle */ OCISession* usrhp; /* user session handle */ OCISvcCtx* svchp; /* the service handle */ typedef std::map SeqStmtType; SeqStmtType seqStmt; pid_t pid; void logon(const std::string& dblink, const std::string& user, const std::string& password); unsigned transactionActive; public: void checkError(sword ret, const char* function = 0) const; Connection(const std::string& url, const std::string& username, const std::string& password); ~Connection(); void beginTransaction(); void commitTransaction(); void rollbackTransaction(); size_type execute(const std::string& query); tntdb::Result select(const std::string& query); tntdb::Row selectRow(const std::string& query); tntdb::Value selectValue(const std::string& query); tntdb::Statement prepare(const std::string& query); tntdb::Statement prepareWithLimit(const std::string& query, const std::string& limit, const std::string& offset); void clearStatementCache(); bool ping(); long lastInsertId(const std::string& name); void lockTable(const std::string& tablename, bool exclusive); OCIEnv* getEnvHandle() const { return envhp; } OCIError* getErrorHandle() const { return errhp; } OCIServer* getSrvHandle() const { return srvhp; } OCISvcCtx* getSvcCtxHandle() const { return svchp; } bool isTransactionActive() const { return transactionActive > 0; } }; } } #endif // TNTDB_ORACLE_CONNECTION_H tntdb-1.4/include/tntdb/oracle/connectionmanager.h000066400000000000000000000034321354703061500223450ustar00rootroot00000000000000/* * Copyright (C) 2007 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_ORACLE_CONNECTIONMANAGER_H #define TNTDB_ORACLE_CONNECTIONMANAGER_H #include namespace tntdb { namespace oracle { class ConnectionManager : public IConnectionManager { public: tntdb::Connection connect(const std::string& url, const std::string& username, const std::string& password); }; } } TNTDB_CONNECTIONMANAGER_DECLARE(oracle) #endif // TNTDB_ORACLE_CONNECTIONMANAGER_H tntdb-1.4/include/tntdb/oracle/cursor.h000066400000000000000000000037301354703061500201710ustar00rootroot00000000000000/* * Copyright (C) 2007 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_ORACLE_CURSOR_H #define TNTDB_ORACLE_CURSOR_H #include #include #include #include namespace tntdb { namespace oracle { class Statement; class SingleRow; class Cursor : public ICursor { cxxtools::SmartPtr stmt; OCIStmt* stmtp; tntdb::Row row; unsigned fetchsize; SingleRow* srow; ub4 rowcount; public: Cursor(Statement* stmt, unsigned fetchsize); ~Cursor(); // method for ICursor tntdb::Row fetch(); }; } } #endif // TNTDB_ORACLE_CURSOR_H tntdb-1.4/include/tntdb/oracle/datetime.h000066400000000000000000000060521354703061500204500ustar00rootroot00000000000000/* * Copyright (C) 2007 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_ORACLE_DATETIME_H #define TNTDB_ORACLE_DATETIME_H #include #include #include #include #include #include namespace tntdb { namespace oracle { class Datetime { Connection* conn; OCIDateTime* datetime; bool release; // low-level wrappers void ociDescriptorAlloc(); void ociDescriptorFree(); void ociConstruct(sb2 year, ub1 month, ub1 day, ub1 hour, ub1 min, ub1 sec, ub4 fsec); void ociAssign(OCIDateTime* src); void ociGetDate(sb2 &year, ub1 &month, ub1 &day) const; void ociGetTime(ub1 &hour, ub1 &min, ub1 &sec, ub4 &fsec) const; public: Datetime() : datetime(0), release(false) { } Datetime(Connection* conn, OCIDateTime* datetime, bool release = false); Datetime(Connection* conn, const tntdb::Datetime& s); Datetime(Connection* conn, const tntdb::Date& s); Datetime(Connection* conn, const tntdb::Time& s); Datetime(const Datetime& src); Datetime& operator= (const Datetime& src); void assign(Connection* conn, const tntdb::Datetime& s); void assign(Connection* conn, const tntdb::Date& s); void assign(Connection* conn, const tntdb::Time& s); OCIDateTime*& getReference(Connection* conn); ~Datetime() { if (release && datetime) ociDescriptorFree(); } tntdb::Date getDate() const; tntdb::Datetime getDatetime() const; tntdb::Time getTime() const; OCIDateTime*& getHandle() { return datetime; } }; } } #endif // TNTDB_ORACLE_DATETIME_H tntdb-1.4/include/tntdb/oracle/error.h000066400000000000000000000045541354703061500200120ustar00rootroot00000000000000/* * Copyright (C) 2007 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_ORACLE_ERROR_H #define TNTDB_ORACLE_ERROR_H #include #include namespace tntdb { namespace oracle { class Error : public tntdb::Error { public: explicit Error(OCIError* errhp, const char* function = 0); explicit Error(const std::string& msg, const char* function = 0); }; class InvalidHandle : public Error { public: explicit InvalidHandle(const char* function = 0) : Error("OCI_INVALID_HANDLE", function) { } }; class StillExecuting : public Error { public: explicit StillExecuting(const char* function = 0) : Error("OCI_STILL_EXECUTING", function) { } }; class ErrorContinue : public Error { public: explicit ErrorContinue(const char* function = 0) : Error("OCI_CONTINUE", function) { } }; namespace error { void checkError(OCIError* errhp, sword ret, const char* function); } } } #endif // TNTDB_ORACLE_ERROR_H tntdb-1.4/include/tntdb/oracle/multirow.h000066400000000000000000000045201354703061500205340ustar00rootroot00000000000000/* * Copyright (C) 2012 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_ORACLE_MULTIROW_H #define TNTDB_ORACLE_MULTIROW_H #include #include #include namespace tntdb { namespace oracle { class MultiRow : public cxxtools::RefCounted { typedef std::vector > Columns; typedef std::vector Values; Columns _columns; Values _values; public: typedef cxxtools::SmartPtr Ptr; MultiRow(Statement* stmt, unsigned rowcount); MultiRow(Statement* stmt, unsigned rowcount, unsigned columncount); unsigned size() const { return _columns.size(); } MultiValue::Ptr getValuesByNumber(unsigned field_num) const; MultiValue::Ptr getValuesByName(const std::string& field_name) const; Columns::size_type getColIndexByName(const std::string& field_name) const; std::string getColumnName(unsigned field_num) const; }; } } #endif // TNTDB_ORACLE_MULTIROW_H tntdb-1.4/include/tntdb/oracle/multivalue.h000066400000000000000000000117151354703061500210450ustar00rootroot00000000000000/* * Copyright (C) 2012 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_ORACLE_MULTIVALUE_H #define TNTDB_ORACLE_MULTIVALUE_H #include #include #include #include #include #include #include namespace tntdb { namespace oracle { class MultiValue : public cxxtools::RefCounted { OCIDefine* _defp; mutable Connection* _conn; ub2 _type; ub2 _collen; ub2* _len; ub2* _nullind; unsigned _n; std::string _colName; // _data points to allocated data depending of _type: // // _type _data points to // ------------------ ------------------------------- // SQLT_INT long * // SQLT_UIN unsigned long * // SQLT_FLT double* // SQLT_NUM tntdb::oracle::Number* // SQLT_VNU tntdb::oracle::Number* // SQLT_DAT OCIDateTime* // SQLT_TIMESTAMP OCIDateTime* // SQLT_TIMESTAMP_TZ OCIDateTime* // SQLT_TIMESTAMP_LTZ OCIDateTime* // SQLT_BLOB tntdb::oracle::Blob* // other char* char* _data; void init(Statement* stmt, OCIParam* paramp, ub4 pos); long longValue(unsigned n) const { return reinterpret_cast(_data)[n]; } unsigned long unsignedValue(unsigned n) const { return reinterpret_cast(_data)[n]; } double doubleValue(unsigned n) const { return reinterpret_cast(_data)[n]; } OCIDateTime* datetime(unsigned n) const { return reinterpret_cast(_data)[n]; } const OCINumber& number(unsigned n) const { return reinterpret_cast(_data)[n]; } Decimal decimal(unsigned n) const { return Number::getDecimal(&number(n), _conn->getErrorHandle()); } OCILobLocator* blob(unsigned n) const { return reinterpret_cast(_data)[n]; } const char* data(unsigned n) const { return &_data[n * (_collen + 16)]; } // make non copyable: MultiValue(const MultiValue&) { } MultiValue& operator= (MultiValue&) { return *this; } public: typedef cxxtools::SmartPtr Ptr; MultiValue(Statement* stmt, OCIParam* paramp_, ub4 pos, unsigned n); MultiValue(Statement* stmt, ub4 pos, unsigned n); ~MultiValue(); unsigned size() const { return _n; } bool isNull(unsigned n) const; bool getBool(unsigned n) const; short getShort(unsigned n) const; int getInt(unsigned n) const; long getLong(unsigned n) const; unsigned short getUnsignedShort(unsigned n) const; unsigned getUnsigned(unsigned n) const; unsigned long getUnsignedLong(unsigned n) const; int32_t getInt32(unsigned n) const; uint32_t getUnsigned32(unsigned n) const; int64_t getInt64(unsigned n) const; uint64_t getUnsigned64(unsigned n) const; Decimal getDecimal(unsigned n) const; float getFloat(unsigned n) const; double getDouble(unsigned n) const; char getChar(unsigned n) const; void getString(unsigned n, std::string& ret) const; void getBlob(unsigned n, tntdb::Blob& ret) const; Date getDate(unsigned n) const; Time getTime(unsigned n) const; tntdb::Datetime getDatetime(unsigned n) const; const std::string& getColumnName() const { return _colName; } }; } } #endif // TNTDB_ORACLE_MULTIVALUE_H tntdb-1.4/include/tntdb/oracle/number.h000066400000000000000000000043551354703061500201500ustar00rootroot00000000000000/* * Copyright (C) 2007 Tommi Maekitalo, Mark Wright * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_ORACLE_NUMBER_H #define TNTDB_ORACLE_NUMBER_H #include #include #include #include #include namespace tntdb { namespace oracle { class Number { OCINumber ociNumber; public: Number(); Number(const Decimal &decimal, OCIError* errhp); void setLong(long data, OCIError* errhp); void setUnsignedLong(unsigned long data, OCIError* errhp); void setInt64(int64_t data, OCIError* errhp); void setUnsigned64(uint64_t data, OCIError* errhp); void setDecimal(const Decimal &decimal, OCIError* errhp); static Decimal getDecimal(const OCINumber* handle, OCIError* errhp); Decimal getDecimal(OCIError* errhp) const { return getDecimal(const_cast(&ociNumber), errhp); } unsigned char* getHandle() { return ociNumber.OCINumberPart; } }; } } #endif tntdb-1.4/include/tntdb/oracle/result.h000066400000000000000000000036471354703061500202010ustar00rootroot00000000000000/* * Copyright (C) 2007 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_ORACLE_RESULT_H #define TNTDB_ORACLE_RESULT_H #include #include #include #include namespace tntdb { namespace oracle { class Statement; class Result : public IResult { ub4 columncount; std::vector rows; public: Result(oracle::Statement* conn); Result(oracle::Statement* conn, unsigned fetchsize); Row getRow(size_type tup_num) const; size_type size() const; size_type getFieldCount() const; }; } } #endif // TNTDB_ORACLE_RESULT_H tntdb-1.4/include/tntdb/oracle/row.h000066400000000000000000000040471354703061500174650ustar00rootroot00000000000000/* * Copyright (C) 2007 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_ORACLE_ROW_H #define TNTDB_ORACLE_ROW_H #include #include #include #include namespace tntdb { namespace oracle { class Row : public IRow { typedef std::vector Values; Values values; public: explicit Row(Statement* stmt); Row(Statement* stmt, unsigned columncount); virtual size_type size() const; virtual tntdb::Value getValueByNumber(size_type field_num) const; virtual tntdb::Value getValueByName(const std::string& field_name) const; virtual std::string getColumnName(size_type field_num) const; }; } } #endif // TNTDB_ORACLE_ROW_H tntdb-1.4/include/tntdb/oracle/singlerow.h000066400000000000000000000042261354703061500206660ustar00rootroot00000000000000/* * Copyright (C) 2012 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_ORACLE_SINGLEROW_H #define TNTDB_ORACLE_SINGLEROW_H #include #include #include namespace tntdb { namespace oracle { class SingleRow : public IRow { MultiRow::Ptr _mr; unsigned _row; typedef std::vector Values; Values _values; public: SingleRow(MultiRow::Ptr mr, unsigned row); unsigned row() const { return _row; } void row(unsigned r); virtual size_type size() const; virtual tntdb::Value getValueByNumber(size_type field_num) const; virtual tntdb::Value getValueByName(const std::string& field_name) const; virtual std::string getColumnName(size_type field_num) const; }; } } #endif // TNTDB_ORACLE_SINGLEROW_H tntdb-1.4/include/tntdb/oracle/singlevalue.h000066400000000000000000000055661354703061500212030ustar00rootroot00000000000000/* * Copyright (C) 2012 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_ORACLE_SINGLEVALUE_H #define TNTDB_ORACLE_SINGLEVALUE_H #include #include #include namespace tntdb { namespace oracle { class SingleValue : public IValue { MultiValue::Ptr _mv; unsigned _row; public: typedef cxxtools::SmartPtr Ptr; SingleValue(MultiValue::Ptr mv, unsigned row) : _mv(mv), _row(row) { } unsigned row() const { return _row; } void row(unsigned r) { _row = r; } virtual bool isNull() const; virtual bool getBool() const; virtual short getShort() const; virtual int getInt() const; virtual long getLong() const; virtual unsigned short getUnsignedShort() const; virtual unsigned getUnsigned() const; virtual unsigned long getUnsignedLong() const; virtual int32_t getInt32() const; virtual uint32_t getUnsigned32() const; virtual int64_t getInt64() const; virtual uint64_t getUnsigned64() const; virtual Decimal getDecimal() const; virtual float getFloat() const; virtual double getDouble() const; virtual char getChar() const; virtual void getString(std::string& ret) const; virtual void getBlob(tntdb::Blob& ret) const; virtual Date getDate() const; virtual Time getTime() const; virtual tntdb::Datetime getDatetime() const; }; } } #endif // TNTDB_ORACLE_SINGLEVALUE_H // vim:sw=2:et tntdb-1.4/include/tntdb/oracle/statement.h000066400000000000000000000122211354703061500206530ustar00rootroot00000000000000/* * Copyright (C) 2007 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_ORACLE_SQLSTATEMENT_H #define TNTDB_ORACLE_SQLSTATEMENT_H #include #include #include #include #include #include #include #include #include #include #include namespace tntdb { namespace oracle { class Connection; class Cursor; class Statement : public IStatement { friend class Cursor; Connection* conn; std::string query; OCIStmt* stmtp; class Bind : public cxxtools::RefCounted { public: OCIBind* ptr; std::vector data; sb2 indicator; String string; Datetime datetime; Blob blob; Number number; const char* boundPtr; int boundType; unsigned boundLength; Bind() : ptr(0), indicator(0), boundPtr(0), boundType(0), boundLength(0) { } void setData(const std::string& value) { data.resize(value.size()); value.copy(&data[0], value.size()); } void setData(const char* value, unsigned size) { data.resize(size); memcpy(&data[0], value, size); } void setNull(bool sw = true) { indicator = sw ? -1 : 0; } }; typedef std::map > BindMapType; BindMapType bindMap; Bind* getBindPtr(const std::string& col); Bind& getBind(const std::string& col) { return *getBindPtr(col); } public: /** convenience method */ void checkError(sword ret, const char* function = 0) const { conn->checkError(ret, function); } Statement(Connection* conn, const std::string& query); ~Statement(); // methods of IStatement void clear(); void setNull(const std::string& col); void setBool(const std::string& col, bool data); void setShort(const std::string& col, short data); void setInt(const std::string& col, int data); void setLong(const std::string& col, long data); void setUnsignedShort(const std::string& col, unsigned short data); void setUnsigned(const std::string& col, unsigned data); void setUnsignedLong(const std::string& col, unsigned long data); void setInt32(const std::string& col, int32_t data); void setUnsigned32(const std::string& col, uint32_t data); void setInt64(const std::string& col, int64_t data); void setUnsigned64(const std::string& col, uint64_t data); void setDecimal(const std::string& col, const Decimal& data); void setFloat(const std::string& col, float data); void setDouble(const std::string& col, double data); void setChar(const std::string& col, char data); void setString(const std::string& col, const std::string& data); void setBlob(const std::string& col, const tntdb::Blob& data); void setDate(const std::string& col, const Date& data); void setTime(const std::string& col, const Time& data); void setDatetime(const std::string& col, const tntdb::Datetime& data); size_type execute(); tntdb::Result select(); tntdb::Row selectRow(); tntdb::Value selectValue(); ICursor* createCursor(unsigned fetchsize); // getter Connection* getConnection() const { return conn; } OCIStmt* getHandle(); OCIError* getErrorHandle() const { return conn->getErrorHandle(); } }; } } #endif // TNTDB_ORACLE_SQLSTATEMENT_H tntdb-1.4/include/tntdb/oracle/string.h000066400000000000000000000040061354703061500201570ustar00rootroot00000000000000/* * Copyright (C) 2018 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_ORACLE_STRING_H #define TNTDB_ORACLE_STRING_H #include #include #include namespace tntdb { namespace oracle { class String { Connection* conn; OCIString* handle; public: String() : handle(0) { } void assign(Connection* conn, const std::string& s); void assign(Connection* conn, char ch) { assign(conn, std::string(1, ch)); } const char* data() const; ub4 size() const; OCIString*& getHandle() { return handle; } }; } } #endif // TNTDB_ORACLE_DATETIME_H tntdb-1.4/include/tntdb/oracle/value.h000066400000000000000000000063151354703061500177720ustar00rootroot00000000000000/* * Copyright (C) 2007 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_ORACLE_VALUE_H #define TNTDB_ORACLE_VALUE_H #include #include #include #include #include #include namespace tntdb { namespace oracle { class Statement; class Value : public IValue { OCIDefine* defp; OCIParam* paramp; OCIError* errhp; ub2 len; ub2 type; ub2 nullind; std::vector data; Datetime datetime; long longValue; uint32_t uint32Value; double doubleValue; Number number; Blob blob; std::string colName; void init(Statement* stmt, OCIParam* paramp_, ub4 pos); public: Value(Statement* stmt, OCIParam* paramp_, ub4 pos); Value(Statement* stmt, ub4 pos); ~Value(); virtual bool isNull() const; virtual bool getBool() const; virtual short getShort() const; virtual int getInt() const; virtual long getLong() const; virtual unsigned short getUnsignedShort() const; virtual unsigned getUnsigned() const; virtual unsigned long getUnsignedLong() const; virtual int32_t getInt32() const; virtual uint32_t getUnsigned32() const; virtual int64_t getInt64() const; virtual uint64_t getUnsigned64() const; virtual Decimal getDecimal() const; virtual float getFloat() const; virtual double getDouble() const; virtual char getChar() const; virtual void getString(std::string& ret) const; virtual void getBlob(tntdb::Blob& ret) const; virtual Date getDate() const; virtual Time getTime() const; virtual tntdb::Datetime getDatetime() const; const std::string& getColumnName() const { return colName; } }; } } #endif // TNTDB_ORACLE_VALUE_H tntdb-1.4/include/tntdb/postgresql/000077500000000000000000000000001354703061500174365ustar00rootroot00000000000000tntdb-1.4/include/tntdb/postgresql/error.h000066400000000000000000000045561354703061500207520ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_POSTGRESQL_ERROR_H #define TNTDB_POSTGRESQL_ERROR_H #include #include namespace tntdb { namespace postgresql { class PgError { protected: PgError() { } }; class PgConnError : public Error, public PgError { protected: PgConnError(const std::string& msg) : Error(msg) { } public: PgConnError(PGconn* conn); PgConnError(const char* function, PGconn* conn); PgConnError(PGresult* result, bool free); PgConnError(const char* function, PGresult* result, bool free); }; class PgSqlError : public SqlError, public PgError { public: PgSqlError(const std::string& sql, PGconn* conn); PgSqlError(const std::string& sql, const char* function, PGconn* conn); PgSqlError(const std::string& sql, PGresult* result, bool free); PgSqlError(const std::string& sql, const char* function, PGresult* result, bool free); }; } } #endif // TNTDB_POSTGRESQL_ERROR_H tntdb-1.4/include/tntdb/postgresql/impl/000077500000000000000000000000001354703061500203775ustar00rootroot00000000000000tntdb-1.4/include/tntdb/postgresql/impl/connection.h000066400000000000000000000074741354703061500227230ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_POSTGRESQL_IMPL_CONNECTION_H #define TNTDB_POSTGRESQL_IMPL_CONNECTION_H #include #include #include #include namespace tntdb { /** This namespace contains the implementation of the PostgreSQL driver for tntdb. The driver makes it possible to access a PostgreSQL database using tntdb. To get a connection to a PostgreSQL database, the dburl to the tntdb::connect function must start with "postgresql:". The remaining string is passed to the `PQconnectdb` function of libpq. A typical connection with a PostgreSQL driver looks like that: @code tntdb::Connection conn = tntdb::connect("postgresql:host=localhost port=5432 dbname=mydb user=foo password=bar"); @endcode */ namespace postgresql { /// Implements a connection to a PostgreSQL database. class Connection : public IStmtCacheConnection { PGconn* conn; tntdb::Statement currvalStmt; tntdb::Statement lastvalStmt; unsigned transactionActive; unsigned stmtCounter; std::vector stmtsToDeallocate; public: Connection(const std::string& url, const std::string& username, const std::string& password); ~Connection(); void beginTransaction(); void commitTransaction(); void rollbackTransaction(); size_type execute(const std::string& query); tntdb::Result select(const std::string& query); tntdb::Row selectRow(const std::string& query); tntdb::Value selectValue(const std::string& query); tntdb::Statement prepare(const std::string& query); tntdb::Statement prepareWithLimit(const std::string& query, const std::string& limit, const std::string& offset); bool ping(); long lastInsertId(const std::string& name); void lockTable(const std::string& tablename, bool exclusive); PGconn* getPGConn() const { return conn; } unsigned getNextStmtNumber() { return ++stmtCounter; } void deallocateStatement(const std::string& stmtName); void deallocateStatements(); }; /// @cond internal inline bool isError(const PGresult* res) { ExecStatusType status = PQresultStatus(res); return status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK && status != PGRES_COPY_OUT && status != PGRES_COPY_IN; } /// @endcond internal } } #endif // TNTDB_POSTGRESQL_IMPL_CONNECTION_H tntdb-1.4/include/tntdb/postgresql/impl/connectionmanager.h000066400000000000000000000034751354703061500242530ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_POSTGRESQL_IMPL_CONNECTIONMANAGER_H #define TNTDB_POSTGRESQL_IMPL_CONNECTIONMANAGER_H #include namespace tntdb { namespace postgresql { class ConnectionManager : public IConnectionManager { public: tntdb::Connection connect(const std::string& url, const std::string& username, const std::string& password); }; } } TNTDB_CONNECTIONMANAGER_DECLARE(postgresql) #endif // TNTDB_POSTGRESQL_IMPL_CONNECTIONMANAGER_H tntdb-1.4/include/tntdb/postgresql/impl/cursor.h000066400000000000000000000047441354703061500220760ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_POSTGRESQL_IMPL_CURSOR_H #define TNTDB_POSTGRESQL_IMPL_CURSOR_H #include #include #include #include namespace tntdb { namespace postgresql { class Cursor : public ICursor { tntdb::Statement tntdbStmt; Statement* stmt; std::string cursorName; tntdb::Result currentResult; unsigned currentRow; unsigned fetchSize; public: Cursor(Statement* statement, unsigned fetchSize); ~Cursor(); // method for ICursor Row fetch(); // specific methods PGconn* getPGConn() { return stmt->getPGConn(); } /** * Data is fetched in blocks. The fetchsize specifies, how many blocks * are fetched at once. This is fully transparent to the user, so there * is normally no need to change the default value, which is 100. */ void setFetchSize(unsigned fs) { fetchSize = fs; } unsigned getFetchSize() const { return fetchSize; } }; } } #endif // TNTDB_POSTGRESQL_IMPL_CURSOR_H tntdb-1.4/include/tntdb/postgresql/impl/result.h000066400000000000000000000037231354703061500220730ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_POSTGRESQL_IMPL_RESULT_H #define TNTDB_POSTGRESQL_IMPL_RESULT_H #include #include #include namespace tntdb { namespace postgresql { class Result : public IResult { tntdb::Connection conn; PGresult* result; public: Result(const tntdb::Connection& conn, PGresult* result); ~Result(); PGresult* getPGresult() const { return result; } Row getRow(size_type tup_num) const; size_type size() const; size_type getFieldCount() const; }; } } #endif // TNTDB_POSTGRESQL_IMPL_RESULT_H tntdb-1.4/include/tntdb/postgresql/impl/resultrow.h000066400000000000000000000044641354703061500226260ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_POSTGRESQL_IMPL_RESULTROW_H #define TNTDB_POSTGRESQL_IMPL_RESULTROW_H #include #include #include namespace tntdb { namespace postgresql { class Result; /// Row of a result-set of type Result class ResultRow : public IRow { tntdb::Result tntdbResult; // keeps a reference to the result Result* result; // redundant type-safe pointer to tntdbResult // (tntdbResult.getImpl() == result) size_type rownumber; public: ResultRow(Result* result, size_type rownumber); unsigned size() const; Value getValueByNumber(size_type field_num) const; Value getValueByName(const std::string& field_name) const; std::string getColumnName(size_type field_num) const; size_type getRowNumber() const { return rownumber; } PGresult* getPGresult() const; }; } } #endif // TNTDB_POSTGRESQL_IMPL_RESULTROW_H tntdb-1.4/include/tntdb/postgresql/impl/resultvalue.h000066400000000000000000000061371354703061500231320ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_POSTGRESQL_IMPL_RESULTVALUE_H #define TNTDB_POSTGRESQL_IMPL_RESULTVALUE_H #include #include #include #include namespace tntdb { namespace postgresql { class ResultValue : public IValue { tntdb::Row tntdbRow; // keeps a reference to the row ResultRow* row; // redundant type-safe pointer to tntdbRow // (tntdbRow.getImpl() == row) int tup_num; public: ResultValue(ResultRow* row_, int tup_num_) : tntdbRow(row_), row(row_), tup_num(tup_num_) { } virtual bool isNull() const; virtual bool getBool() const; virtual short getShort() const; virtual int getInt() const; virtual long getLong() const; virtual unsigned short getUnsignedShort() const; virtual unsigned getUnsigned() const; virtual unsigned long getUnsignedLong() const; virtual int32_t getInt32() const; virtual uint32_t getUnsigned32() const; virtual int64_t getInt64() const; virtual uint64_t getUnsigned64() const; virtual Decimal getDecimal() const; virtual float getFloat() const; virtual double getDouble() const; virtual char getChar() const; virtual void getString(std::string& ret) const; virtual void getBlob(Blob& ret) const; virtual Date getDate() const; virtual Time getTime() const; virtual Datetime getDatetime() const; std::string getString() const { std::string ret; getString(ret); return ret; } PGresult* getPGresult() const { return row->getPGresult(); } }; } } #endif // TNTDB_POSTGRESQL_IMPL_RESULTVALUE_H tntdb-1.4/include/tntdb/postgresql/impl/statement.h000066400000000000000000000125371354703061500225640ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_POSTGRESQL_IMPL_SQLSTATEMENT_H #define TNTDB_POSTGRESQL_IMPL_SQLSTATEMENT_H #include #include #include #include #include namespace tntdb { namespace postgresql { class Connection; class Statement : public IStatement { Connection* conn; std::string query; std::string stmtName; typedef std::map hostvarMapType; hostvarMapType hostvarMap; class valueType { bool isNull; std::string value; #ifndef HAVE_PQPREPARE std::string type; #endif public: #ifndef HAVE_PQPREPARE valueType() : type("text") { } #endif void setNull() { isNull = true; } void setValue(const std::string& v) { value = v; isNull = false; } const char* getValue() { return isNull ? 0 : value.data(); } unsigned getLength() { return isNull ? 0 : value.size(); } #ifndef HAVE_PQPREPARE void setType(const std::string& t) { type = t; } const std::string& getType() const { return type; } #endif }; typedef std::vector valuesType; valuesType values; std::vector paramValues; std::vector paramLengths; std::vector paramFormats; // helper-methods for setting values template void setValue(const std::string& col, T data); template void setStringValue(const std::string& col, T data, bool binary = false); template void setIsoValue(const std::string& col, T data); #ifndef HAVE_PQPREPARE void setType(const std::string& col, const std::string& type); #endif void doPrepare(); PGresult* execPrepared(); public: Statement(Connection* conn, const std::string& query); ~Statement(); // methods of IStatement void clear(); void setNull(const std::string& col); void setBool(const std::string& col, bool data); void setShort(const std::string& col, short data); void setInt(const std::string& col, int data); void setLong(const std::string& col, long data); void setUnsignedShort(const std::string& col, unsigned short data); void setUnsigned(const std::string& col, unsigned data); void setUnsignedLong(const std::string& col, unsigned long data); void setInt32(const std::string& col, int32_t data); void setUnsigned32(const std::string& col, uint32_t data); void setInt64(const std::string& col, int64_t data); void setUnsigned64(const std::string& col, uint64_t data); void setDecimal(const std::string& col, const Decimal& data); void setFloat(const std::string& col, float data); void setDouble(const std::string& col, double data); void setChar(const std::string& col, char data); void setString(const std::string& col, const std::string& data); void setBlob(const std::string& col, const Blob& data); void setDate(const std::string& col, const Date& data); void setTime(const std::string& col, const Time& data); void setDatetime(const std::string& col, const Datetime& data); size_type execute(); tntdb::Result select(); tntdb::Row selectRow(); tntdb::Value selectValue(); ICursor* createCursor(unsigned fetchsize); // specific methods const std::string& getQuery() const { return query; } int getNParams() { return values.size(); } const char* const* getParamValues(); const int* getParamLengths(); const int* getParamFormats() { return ¶mFormats[0]; } PGconn* getPGConn(); Connection* getConnection() { return conn; } }; } } #endif // TNTDB_POSTGRESQL_IMPL_SQLSTATEMENT_H tntdb-1.4/include/tntdb/replicate/000077500000000000000000000000001354703061500172035ustar00rootroot00000000000000tntdb-1.4/include/tntdb/replicate/connection.h000066400000000000000000000051641354703061500215210ustar00rootroot00000000000000/* * Copyright (C) 2011 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_REPLICATE_IMPL_CONNECTION_H #define TNTDB_REPLICATE_IMPL_CONNECTION_H #include #include #include namespace tntdb { namespace replicate { class Statement; class Connection : public IStmtCacheConnection { friend class Statement; typedef std::vector Connections; Connections connections; tntdb::Connection primaryConnection; public: Connection(const std::string& url, const std::string& username, const std::string& password); ~Connection(); void beginTransaction(); void commitTransaction(); void rollbackTransaction(); size_type execute(const std::string& query); tntdb::Result select(const std::string& query); tntdb::Row selectRow(const std::string& query); tntdb::Value selectValue(const std::string& query); tntdb::Statement prepare(const std::string& query); tntdb::Statement prepareWithLimit(const std::string& query, const std::string& limit, const std::string& offset); bool ping(); long lastInsertId(const std::string& name); void lockTable(const std::string& tablename, bool exclusive); }; } } #endif // TNTDB_REPLICATE_IMPL_CONNECTION_H tntdb-1.4/include/tntdb/replicate/connectionmanager.h000066400000000000000000000034701354703061500230520ustar00rootroot00000000000000/* * Copyright (C) 2011 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_REPLICATE_IMPL_CONNECTIONMANAGER_H #define TNTDB_REPLICATE_IMPL_CONNECTIONMANAGER_H #include namespace tntdb { namespace replicate { class ConnectionManager : public IConnectionManager { public: tntdb::Connection connect(const std::string& url, const std::string& username, const std::string& password); }; } } TNTDB_CONNECTIONMANAGER_DECLARE(replicate) #endif // TNTDB_REPLICATE_IMPL_CONNECTIONMANAGER_H tntdb-1.4/include/tntdb/replicate/statement.h000066400000000000000000000067061354703061500213710ustar00rootroot00000000000000/* * Copyright (C) 2011 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_REPLICATE_STATEMENT_H #define TNTDB_REPLICATE_STATEMENT_H #include #include #include namespace tntdb { namespace replicate { class Connection; class Statement : public IStatement { Connection* conn; typedef std::vector Statements; Statements statements; public: Statement(Connection* conn, const std::string& query, const std::string& limit = std::string(), const std::string& offset = std::string()); // methods of IStatement void clear(); void setNull(const std::string& col); void setBool(const std::string& col, bool data); void setShort(const std::string& col, short data); void setInt(const std::string& col, int data); void setLong(const std::string& col, long data); void setUnsignedShort(const std::string& col, unsigned short data); void setUnsigned(const std::string& col, unsigned data); void setUnsignedLong(const std::string& col, unsigned long data); void setInt32(const std::string& col, int32_t data); void setUnsigned32(const std::string& col, uint32_t data); void setInt64(const std::string& col, int64_t data); void setUnsigned64(const std::string& col, uint64_t data); void setDecimal(const std::string& col, const Decimal& data); void setFloat(const std::string& col, float data); void setDouble(const std::string& col, double data); void setChar(const std::string& col, char data); void setString(const std::string& col, const std::string& data); void setBlob(const std::string& col, const Blob& data); void setDate(const std::string& col, const Date& data); void setTime(const std::string& col, const Time& data); void setDatetime(const std::string& col, const Datetime& data); size_type execute(); tntdb::Result select(); tntdb::Row selectRow(); tntdb::Value selectValue(); ICursor* createCursor(unsigned fetchsize); }; } } #endif // TNTDB_REPLICATE_STATEMENT_H tntdb-1.4/include/tntdb/result.h000066400000000000000000000034051354703061500167240ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_RESULT_H #define TNTDB_RESULT_H #include #include namespace tntdb { /// C++11 style _begin_ function for tntdb::Result. inline Result::const_iterator begin(const Result& stmt) { return stmt.begin(); } /// C++11 style _end_ function for tntdb::Result. inline Result::const_iterator end(const Result& stmt) { return stmt.end(); } } #endif // TNTDB_RESULT_H tntdb-1.4/include/tntdb/row.h000066400000000000000000000034451354703061500162210ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_ROW_H #define TNTDB_ROW_H #include #include #include #include namespace tntdb { /// C++11 style _begin_ function for tntdb::Row. inline Row::const_iterator begin(const Row& stmt) { return stmt.begin(); } /// C++11 style _end_ function for tntdb::Row. inline Row::const_iterator end(const Row& stmt) { return stmt.end(); } } #endif // TNTDB_ROW_H tntdb-1.4/include/tntdb/serialization.h000066400000000000000000000063321354703061500202650ustar00rootroot00000000000000/* * Copyright (C) 2015 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_SERIALIZATION_H #define TNTDB_SERIALIZATION_H #include namespace tntdb { class Value; class Row; class Result; class Statement; /** Makes tntdb::Value serializable in cxxtools serialization framework */ void operator<<= (cxxtools::SerializationInfo& si, const Value& value); /** Makes tntdb::Row serializable in cxxtools serialization framework */ void operator<<= (cxxtools::SerializationInfo& si, const Row& row); /** Makes tntdb::Result serializable in cxxtools serialization framework */ void operator<<= (cxxtools::SerializationInfo& si, const Result& res); /** Makes tntdb::Statement serializable in cxxtools serialization framework */ void operator<<= (cxxtools::SerializationInfo& si, const Statement& res); /** Serialize operator for tntdb::Statement. */ void operator>>= (const cxxtools::SerializationInfo& si, Statement& stmt); /** Serialize objects into tntdb::Statement. * This sets the placeholder variables in statement to the value of the * object to serialize. * * Example: * /code * MyObject obj = ...; * stmt = db.prepare("insert into ..."); * stmt <<= obj; // this serializes MyObject into the statement * // by using the serialization operator of MyObject * // and setting the members in the statement one by one * * stmt.execute(); * /endcode */ template Statement& operator<<= (Statement& stmt, const T& obj) { cxxtools::SerializationInfo si; si <<= obj; si >>= stmt; return stmt; } template void operator>>= (const Row& row, T& obj) { cxxtools::SerializationInfo si; si <<= row; si >>= obj; } } #endif // TNTDB_SERIALIZATION_H tntdb-1.4/include/tntdb/sqlbuilder.h000066400000000000000000000133221354703061500175530ustar00rootroot00000000000000/* * Copyright (C) 2011 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_SQLBUILDER_H #define TNTDB_SQLBUILDER_H #include namespace tntdb { /** Helper class for building sql statements. Sql statments take placeholders, which can be filled with values for execution. Those placeholders are limited to take scalar values and only where scalar values are expected in the sql statement. Sometimes the user needs to pass sets of values. Since it is not directly supported by sql the user has to build a list of placeholders into the sql statement. If the number of needed placeholders is not known at compile time, a sql statement needs to be created dynamically. Anoter problem is, that placeholders are not allowed everywhere in the sql statment. To parametrise e.g. the table name, again the user has to replace the table name before passing the sql to the database. This class has helpers for both cases. Placeholders here start with a percent character followed by alphanumeric characters. */ class SqlBuilder { public: /// The class is default constructable. SqlBuilder() { } /// Create a sql builder with a string with optional placeholders. SqlBuilder(const std::string& sql_) : sql(sql_) { } /** Replace a sqlbuilder placeholder with a list of sql placeholders with index. The varname specifies the placeholder and the count the number of generated placeholders. example: @code std::set myValues; myValues.insert(2); myValues.insert(3); myValues.insert(6); tntdb::Statement st = conn.prepare( tntdb::SqlBuilder( "select foo from bar where baz in (%set)") .extendParam("set", myValues.size()) ); st.set("set", s); // => select foo from bar where baz in (:set1,:set2,:set3) @endcode This generates a sql statement with 3 sql placeholders and fills those with values from a std::set. */ SqlBuilder& extendParam(const std::string& varname, unsigned count); /** Replace a placeholder with a value. This method replaces a sqlbuilder placeholder with a value. Note that no escaping is done so that passing user input may result in sql injection. example: @code std::string myTablename = "bar"; tntdb::Statement st = conn.prepare( tntdb::SqlBuilder( "select foo from %tab") .replace("tab", myTablename) ); // => select foo from bar @endcode */ SqlBuilder& replace(const std::string& varname, const std::string& value); /** Replace a placeholder conditionally with a value. This adds a condition to the replace method. This helps when optional conditions are needed. @code std::string searchString = ""; tntdb::Statement st1 = conn.prepare( tntdb::SqlBuilder( "select foo from mytable where bar = 17 %cond" .replaceIf(!searchString.empty(), "cond", "and bar like :s") ); // => select foo from mytable where bar = 17 searchString = "foo%"; tntdb::Statement st2 = conn.prepare( tntdb::SqlBuilder( "select foo from mytable where bar = 17 %cond" .replaceIf(!searchString.empty(), "cond", "and bar like :s") ); // => select foo from mytable where bar = 17 and bar like :s @endcode */ SqlBuilder& replaceIf(bool condition, const std::string& varname, const std::string& value, const std::string& elsevalue = std::string()) { replace(varname, condition ? value : elsevalue); return *this; } /// sets the underlying string to the passed value void str(const std::string& s) { sql = s; } /// returns the resulting sql string. const std::string& str() const { return sql; } /// returns the resulting sql string implicitly. operator const std::string&() const { return sql; } private: std::string sql; }; } #endif // TNTDB_SQLBUILDER_H tntdb-1.4/include/tntdb/sqlite/000077500000000000000000000000001354703061500165345ustar00rootroot00000000000000tntdb-1.4/include/tntdb/sqlite/error.h000066400000000000000000000052301354703061500200360ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_SQLITE_ERROR_H #define TNTDB_SQLITE_ERROR_H #include #include #include namespace tntdb { namespace sqlite { class SqliteError : public Error { const char* function; public: SqliteError(const char* function, const std::string& msg) : Error(std::string(function) + ": " + msg) { } SqliteError(const char* function, const char* errmsg) : Error(std::string(function) + ": " + (errmsg ? errmsg : "unknown error")) { } SqliteError(const char* function, char* errmsg, bool do_free); const char* getFunction() const { return function; } }; class Execerror : public SqliteError { int errcode; public: Execerror(const char* function, sqlite3* db, int _errcode); Execerror(const char* function, sqlite3_stmt* stmt, int _errcode); Execerror(const char* function, int _errcode, const char* errmsg) : SqliteError(function, errmsg), errcode(_errcode) { } Execerror(const char* function, int _errcode, char* errmsg, bool do_free) : SqliteError(function, errmsg, do_free), errcode(_errcode) { } int getErrorcode() const { return errcode; } }; } } #endif // TNTDB_SQLITE_ERROR_H tntdb-1.4/include/tntdb/sqlite/impl/000077500000000000000000000000001354703061500174755ustar00rootroot00000000000000tntdb-1.4/include/tntdb/sqlite/impl/connection.h000066400000000000000000000060731354703061500220130ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_SQLITE_IMPL_CONNECTION_H #define TNTDB_SQLITE_IMPL_CONNECTION_H #include #include namespace tntdb { /** This namespace contains the implementation of the Sqlite driver for tntdb. The driver makes it possible to access a Sqlite3 database using tntdb. Note that only sqlite api version 3 is supported. To get a connection to a Sqlite3 file, the dburl to the tntdb::connect function must start with "sqlite:". The remaining string is passed to the `sqlite3_open` function of sqlite. A typical connection with a Sqlite3 driver looks like that: @code tntdb::Connection conn = tntdb::connect("sqlite:mydatabase.db"); @endcode */ namespace sqlite { /// Implements a connection to a Sqlite3 database file. class Connection : public IStmtCacheConnection { sqlite3* db; unsigned transactionActive; public: explicit Connection(const char* conninfo); ~Connection(); void beginTransaction(); void commitTransaction(); void rollbackTransaction(); size_type execute(const std::string& query); tntdb::Result select(const std::string& query); tntdb::Row selectRow(const std::string& query); tntdb::Value selectValue(const std::string& query); tntdb::Statement prepare(const std::string& query); tntdb::Statement prepareWithLimit(const std::string& query, const std::string& limit, const std::string& offset); bool ping(); long lastInsertId(const std::string& name); void lockTable(const std::string& tablename, bool exclusive); sqlite3* getSqlite3() const { return db; } }; } } #endif // TNTDB_SQLITE_IMPL_CONNECTION_H tntdb-1.4/include/tntdb/sqlite/impl/connectionmanager.h000066400000000000000000000034511354703061500233430ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_SQLITE_IMPL_CONNECTIONMANAGER_H #define TNTDB_SQLITE_IMPL_CONNECTIONMANAGER_H #include namespace tntdb { namespace sqlite { class ConnectionManager : public IConnectionManager { public: tntdb::Connection connect(const std::string& url, const std::string& username, const std::string& password); }; } } TNTDB_CONNECTIONMANAGER_DECLARE(sqlite) #endif // TNTDB_SQLITE_IMPL_CONNECTIONMANAGER_H tntdb-1.4/include/tntdb/sqlite/impl/cursor.h000066400000000000000000000037111354703061500211650ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_SQLITE_IMPL_CURSOR_H #define TNTDB_SQLITE_IMPL_CURSOR_H #include #include #include namespace tntdb { namespace sqlite { class Statement; class Cursor : public ICursor { cxxtools::SmartPtr statement; sqlite3_stmt* stmt; public: Cursor(Statement* statement, sqlite3_stmt* stmt); ~Cursor(); // method for ICursor Row fetch(); // specific methods of sqlite-driver sqlite3_stmt* getStmt() const { return stmt; } }; } } #endif // TNTDB_SQLITE_IMPL_CURSOR_H tntdb-1.4/include/tntdb/sqlite/impl/statement.h000066400000000000000000000075561354703061500216670ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_SQLITE_IMPL_SQLSTATEMENT_H #define TNTDB_SQLITE_IMPL_SQLSTATEMENT_H #include #include namespace tntdb { namespace sqlite { class Connection; class Statement : public IStatement { sqlite3_stmt* stmt; sqlite3_stmt* stmtInUse; Connection* conn; const std::string query; sqlite3_stmt* getBindStmt(); int getBindIndex(const std::string& col); bool needReset; void reset(); public: Statement(Connection* conn, const std::string& query); ~Statement(); // methods of IStatement virtual void clear(); virtual void setNull(const std::string& col); virtual void setBool(const std::string& col, bool data); virtual void setShort(const std::string& col, short data); virtual void setInt(const std::string& col, int data); virtual void setLong(const std::string& col, long data); virtual void setUnsignedShort(const std::string& col, unsigned short data); virtual void setUnsigned(const std::string& col, unsigned data); virtual void setUnsignedLong(const std::string& col, unsigned long data); virtual void setInt32(const std::string& col, int32_t data); virtual void setUnsigned32(const std::string& col, uint32_t data); virtual void setInt64(const std::string& col, int64_t data); virtual void setUnsigned64(const std::string& col, uint64_t data); virtual void setDecimal(const std::string& col, const Decimal& data); virtual void setFloat(const std::string& col, float data); virtual void setDouble(const std::string& col, double data); virtual void setChar(const std::string& col, char data); virtual void setString(const std::string& col, const std::string& data); virtual void setBlob(const std::string& col, const Blob& data); virtual void setDate(const std::string& col, const Date& data); virtual void setTime(const std::string& col, const Time& data); virtual void setDatetime(const std::string& col, const Datetime& data); virtual size_type execute(); virtual tntdb::Result select(); virtual tntdb::Row selectRow(); virtual tntdb::Value selectValue(); virtual ICursor* createCursor(unsigned fetchsize); // specific methods of sqlite-driver sqlite3_stmt* getStmt() const { return stmt; } void putback(sqlite3_stmt* stmt); }; } } #endif // TNTDB_SQLITE_IMPL_SQLSTATEMENT_H tntdb-1.4/include/tntdb/sqlite/impl/stmtrow.h000066400000000000000000000040661354703061500213730ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_SQLITE_IMPL_STMTROW_H #define TNTDB_SQLITE_IMPL_STMTROW_H #include #include namespace tntdb { namespace sqlite { /// Row of a statement class StmtRow : public IRow { sqlite3_stmt* stmt; public: StmtRow(sqlite3_stmt* stmt_) : stmt(stmt_) { } unsigned size() const; Value getValueByNumber(size_type field_num) const; Value getValueByName(const std::string& field_name) const; std::string getColumnName(size_type field_num) const; // specific methods of sqlite-driver sqlite3_stmt* getStmt() const { return stmt; } }; } } #endif // TNTDB_SQLITE_IMPL_STMTROW_H tntdb-1.4/include/tntdb/sqlite/impl/stmtvalue.h000066400000000000000000000056611354703061500217020ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_SQLITE_IMPL_STMTVALUE_H #define TNTDB_SQLITE_IMPL_STMTVALUE_H #include #include namespace tntdb { namespace sqlite { class StmtValue : public IValue { sqlite3_stmt* stmt; int iCol; public: StmtValue(sqlite3_stmt* stmt_, int iCol_) : stmt(stmt_), iCol(iCol_) { } StmtValue(sqlite3_stmt* stmt, const std::string& name); virtual bool isNull() const; virtual bool getBool() const; virtual short getShort() const; virtual int getInt() const; virtual long getLong() const; virtual unsigned short getUnsignedShort() const; virtual unsigned getUnsigned() const; virtual unsigned long getUnsignedLong() const; virtual int32_t getInt32() const; virtual uint32_t getUnsigned32() const; virtual int64_t getInt64() const; virtual uint64_t getUnsigned64() const; virtual Decimal getDecimal() const; virtual float getFloat() const; virtual double getDouble() const; virtual char getChar() const; virtual void getString(std::string& ret) const; virtual void getBlob(Blob& ret) const; virtual Date getDate() const; virtual Time getTime() const; virtual Datetime getDatetime() const; // specific methods of sqlite-driver std::string getString() const { std::string ret; getString(ret); return ret; } sqlite3_stmt* getStmt() const { return stmt; } }; } } #endif // TNTDB_SQLITE_IMPL_STMTVALUE_H tntdb-1.4/include/tntdb/statement.h000066400000000000000000000043431354703061500174140ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_SQL_STATEMENT_H #define TNTDB_SQL_STATEMENT_H #include #include #include namespace tntdb { /// C++11 style _begin_ function for tntdb::Statement. inline Statement::const_iterator begin(const Statement& stmt, unsigned fetchsize = 100) { return stmt.begin(fetchsize); } /// C++11 style _end_ function for tntdb::Statement. inline Statement::const_iterator end(const Statement& stmt) { return stmt.end(); } inline Statement::const_iterator Statement::end() const { return const_iterator(); } template RowReader Statement::const_iterator::get(T& ret) const { return RowReader(current).get(ret); } template RowReader Statement::const_iterator::get(T& ret, bool& nullInd) const { return RowReader(current).get(ret, nullInd); } } #endif // TNTDB_SQL_STATEMENT_H tntdb-1.4/include/tntdb/stmtparser.h000066400000000000000000000050431354703061500176120ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_STMTPARSER_H #define TNTDB_STMTPARSER_H #include namespace tntdb { class StmtEvent { public: virtual ~StmtEvent() {} // returns replacementvalue virtual std::string onHostVar(const std::string& name) = 0; }; /** Search host variables Host variables start with a ':' followed by alpha characters. For each variable found the event handler StmtEvent is called. The host variable is removed and replaced with the value returned by the event handler. The character '\' is treated as an escape character. It is removed and the following character is processed as is. Name parsing is stopped at '\', so if you need to put alpha characters directly after a host variable, you can escape the character following the host variables name. Strings enclosed in ', " or ` are skipped. */ class StmtParser { char praefixChar; std::string sql; public: explicit StmtParser(char praefixChar_ = ':') : praefixChar(praefixChar_) { } void parse(const std::string& sqlIn, StmtEvent& event); const std::string& getSql() const { return sql; } }; } #endif // TNTDB_STMTPARSER_H tntdb-1.4/include/tntdb/time.h000066400000000000000000000102301354703061500163360ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_TIME_H #define TNTDB_TIME_H #include namespace tntdb { /// This class holds a time. class Time { private: short _hour; unsigned short _minute; unsigned short _second; unsigned short _millis; public: /// Create a Time object with empty values Time() : _hour(-1), _minute(0), _second(0), _millis(0) { } /** Create a Time object with the given values No range checks are done. */ Time(unsigned short hour, unsigned short minute, unsigned short second, unsigned short millis = 0) : _hour(hour), _minute(minute), _second(second), _millis(millis) { } static Time localtime(); static Time gmtime(); /// Get the hour part of the Time unsigned short getHour() const { return static_cast(_hour); } /// Get the minute part of the Time unsigned short getMinute() const { return _minute; } /// Get the second part of the Time unsigned short getSecond() const { return _second; } /// Get the millisecond part of the Time unsigned short getMillis() const { return _millis; } bool isNull() const { return _hour < 0; } /** Sets the time No range checks are done */ void set(unsigned short hour, unsigned short minute, unsigned short second, unsigned short millis = 0) { _hour = static_cast(hour); _minute = minute; _second = second; _millis = millis; } /// Get the time in ISO format (hh:mm:ss.hhh) std::string getIso() const; /** Construct a Time object from the given ISO date string If the string is not in ISO format, an exception of type tntdb::TypeError is thrown. */ static Time fromIso(const std::string& s); bool operator== (const Time& dt) const { return _hour == dt._hour && _minute == dt._minute && _second == dt._second && _millis == dt._millis; } bool operator!= (const Time& dt) const { return !operator==(dt); } bool operator< (const Time& dt) const { return _hour < dt._hour ? true : _hour > dt._hour ? false : _minute < dt._minute ? true : _minute > dt._minute ? false : _second < dt._second ? true : _second > dt._second ? false : _millis < dt._millis; } bool operator> (const Time& dt) const { return dt < *this; } bool operator<= (const Time& dt) const { return !(*this > dt); } bool operator>= (const Time& dt) const { return !(*this < dt); } }; } #endif // TNTDB_TIME_H tntdb-1.4/include/tntdb/transaction.h000066400000000000000000000057301354703061500177360ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_TRANSACTION_H #define TNTDB_TRANSACTION_H #include namespace tntdb { /** The class Transaction monitors the state of a transaction on a database connection The constructor by default starts a transaction on the database. The transaction state is held in the class. The destructor rolls back the transaction if it isn't explicitely commited or rolled back. */ class Transaction { Connection db; bool active; Transaction(const Transaction&) { } Transaction& operator=(const Transaction&) { return *this; } public: /// Create a %Transaction object Transaction(const Connection& db_, bool starttransaction = true); /// Roll back transaction if still active ~Transaction(); const Connection& getConnection() const { return db; } Connection& getConnection() { return db; } /// Start a new transaction. If there is an active transaction, it is rolled back first void begin(); /** Commit the current transaction. If there is no active transaction, nothing is done. The transaction state is reset. */ void commit(); /** Roll back the current transaction If there is no active transaction, nothing is done. The transaction state is reset. */ void rollback(); /** Lock the specified table Locks are released when the transaction is committed or rolled back either explicitly or implicitly by the destructor. */ void lockTable(const std::string& tableName, bool exclusive = true); }; } #endif // TNTDB_TRANSACTION_H tntdb-1.4/include/tntdb/value.h000066400000000000000000000026621354703061500165260ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TNTDB_VALUE_H #define TNTDB_VALUE_H #include #endif // TNTDB_VALUE_H tntdb-1.4/m4/000077500000000000000000000000001354703061500130155ustar00rootroot00000000000000tntdb-1.4/m4/acx_pthread.m4000066400000000000000000000224171354703061500155470ustar00rootroot00000000000000dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) dnl dnl @summary figure out how to build C programs using POSIX threads dnl dnl This macro figures out how to build C programs using POSIX threads. dnl It sets the PTHREAD_LIBS output variable to the threads library and dnl linker flags, and the PTHREAD_CFLAGS output variable to any special dnl C compiler flags that are needed. (The user can also force certain dnl compiler flags/libs to be tested by setting these environment dnl variables.) dnl dnl Also sets PTHREAD_CC to any special C compiler that is needed for dnl multi-threaded programs (defaults to the value of CC otherwise). dnl (This is necessary on AIX to use the special cc_r compiler alias.) dnl dnl NOTE: You are assumed to not only compile your program with these dnl flags, but also link it with them as well. e.g. you should link dnl with $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS dnl $LIBS dnl dnl If you are only building threads programs, you may wish to use dnl these variables in your default LIBS, CFLAGS, and CC: dnl dnl LIBS="$PTHREAD_LIBS $LIBS" dnl CFLAGS="$CFLAGS $PTHREAD_CFLAGS" dnl CC="$PTHREAD_CC" dnl dnl In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute dnl constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to dnl that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). dnl dnl ACTION-IF-FOUND is a list of shell commands to run if a threads dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands to dnl run it if it is not found. If ACTION-IF-FOUND is not specified, the dnl default action will define HAVE_PTHREAD. dnl dnl Please let the authors know if this macro fails on any platform, or dnl if you have any other suggestions or comments. This macro was based dnl on work by SGJ on autoconf scripts for FFTW (www.fftw.org) (with dnl help from M. Frigo), as well as ac_pthread and hb_pthread macros dnl posted by Alejandro Forero Cuervo to the autoconf macro repository. dnl We are also grateful for the helpful feedback of numerous users. dnl dnl @category InstalledPackages dnl @author Steven G. Johnson dnl @version 2005-06-15 dnl @license GPLWithACException AC_DEFUN([ACX_PTHREAD], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_LANG_SAVE AC_LANG_C acx_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on True64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes) AC_MSG_RESULT($acx_pthread_ok) if test x"$acx_pthread_ok" = xno; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. acx_pthread_flags="pthreads pthread none -Kthread -kthread lthread -pthread -pthreads -mthreads -mt --thread-safe pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) # -pthreads: Solaris/gcc # -mthreads: Mingw32/gcc, Lynx/gcc # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # ... -mt is also the pthreads flag for HP/aCC # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) case "${host_cpu}-${host_os}" in *solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthreads/-mt/ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: acx_pthread_flags="-pthreads -mt pthread -pthread $acx_pthread_flags" ;; esac if test x"$acx_pthread_ok" = xno; then for flag in $acx_pthread_flags; do case $flag in none) AC_MSG_CHECKING([whether pthreads work without any flags]) ;; -*) AC_MSG_CHECKING([whether pthreads work with $flag]) PTHREAD_CFLAGS="$flag" ;; pthread-config) AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no) if test x"$acx_pthread_config" = xno; then continue; fi PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) AC_MSG_CHECKING([for the pthreads library -l$flag]) PTHREAD_LIBS="-l$flag" ;; esac save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. AC_TRY_LINK([#include ], [pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], [acx_pthread_ok=yes]) LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" AC_MSG_RESULT($acx_pthread_ok) if test "x$acx_pthread_ok" = xyes; then break; fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$acx_pthread_ok" = xyes; then save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. AC_MSG_CHECKING([for joinable pthread attribute]) attr_name=unknown for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do AC_TRY_LINK([#include ], [int attr=$attr; return attr;], [attr_name=$attr; break]) done AC_MSG_RESULT($attr_name) if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name, [Define to necessary symbol if this constant uses a non-standard name on your system.]) fi AC_MSG_CHECKING([if more special flags are required for pthreads]) flag=no case "${host_cpu}-${host_os}" in *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; esac AC_MSG_RESULT(${flag}) if test "x$flag" != xno; then PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" # More AIX lossage: must compile with cc_r AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC}) AC_CHECK_PROG(PTHREAD_CXX, CC_r, CC_r, ${CXX}) else PTHREAD_CC="$CC" PTHREAD_CXX="$CXX" fi AC_SUBST(PTHREAD_LIBS) AC_SUBST(PTHREAD_CFLAGS) AC_SUBST(PTHREAD_CC) AC_SUBST(PTHREAD_CXX) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x"$acx_pthread_ok" = xyes; then ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) : else acx_pthread_ok=no $2 fi AC_LANG_RESTORE ])dnl ACX_PTHREAD tntdb-1.4/m4/ax_check_compile_flag.m4000066400000000000000000000062511354703061500175310ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html # =========================================================================== # # SYNOPSIS # # AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS]) # # DESCRIPTION # # Check whether the given FLAG works with the current language's compiler # or gives an error. (Warnings, however, are ignored) # # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on # success/failure. # # If EXTRA-FLAGS is defined, it is added to the current language's default # flags (e.g. CFLAGS) when the check is done. The check is thus made with # the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to # force the compiler to issue an error when a bad flag is given. # # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this # macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. # # LICENSE # # Copyright (c) 2008 Guido U. Draheim # Copyright (c) 2011 Maarten Bosmans # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU 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 General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 2 AC_DEFUN([AX_CHECK_COMPILE_FLAG], [AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" AC_COMPILE_IFELSE([AC_LANG_PROGRAM()], [AS_VAR_SET(CACHEVAR,[yes])], [AS_VAR_SET(CACHEVAR,[no])]) _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], [m4_default([$2], :)], [m4_default([$3], :)]) AS_VAR_POPDEF([CACHEVAR])dnl ])dnl AX_CHECK_COMPILE_FLAGS tntdb-1.4/m4/ax_compiler_vendor.m4000066400000000000000000000066161354703061500171470ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_compiler_vendor.html # =========================================================================== # # SYNOPSIS # # AX_COMPILER_VENDOR # # DESCRIPTION # # Determine the vendor of the C/C++ compiler, e.g., gnu, intel, ibm, sun, # hp, borland, comeau, dec, cray, kai, lcc, metrowerks, sgi, microsoft, # watcom, etc. The vendor is returned in the cache variable # $ax_cv_c_compiler_vendor for C and $ax_cv_cxx_compiler_vendor for C++. # # LICENSE # # Copyright (c) 2008 Steven G. Johnson # Copyright (c) 2008 Matteo Frigo # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU 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 General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 11 AC_DEFUN([AX_COMPILER_VENDOR], [AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor, [# note: don't check for gcc first since some other compilers define __GNUC__ vendors="intel: __ICC,__ECC,__INTEL_COMPILER ibm: __xlc__,__xlC__,__IBMC__,__IBMCPP__ pathscale: __PATHCC__,__PATHSCALE__ clang: __clang__ gnu: __GNUC__ sun: __SUNPRO_C,__SUNPRO_CC hp: __HP_cc,__HP_aCC dec: __DECC,__DECCXX,__DECC_VER,__DECCXX_VER borland: __BORLANDC__,__TURBOC__ comeau: __COMO__ cray: _CRAYC kai: __KCC lcc: __LCC__ sgi: __sgi,sgi microsoft: _MSC_VER metrowerks: __MWERKS__ watcom: __WATCOMC__ portland: __PGI unknown: UNKNOWN" for ventest in $vendors; do case $ventest in *:) vendor=$ventest; continue ;; *) vencpp="defined("`echo $ventest | sed 's/,/) || defined(/g'`")" ;; esac AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[ #if !($vencpp) thisisanerror; #endif ])], [break]) done ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=`echo $vendor | cut -d: -f1` ]) ]) tntdb-1.4/m4/ax_cxx_compile_stdcxx_11.m4000066400000000000000000000112751354703061500201650ustar00rootroot00000000000000# ============================================================================ # http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html # ============================================================================ # # SYNOPSIS # # AX_CXX_COMPILE_STDCXX_11([ext|noext],[mandatory|optional]) # # DESCRIPTION # # Check for baseline language coverage in the compiler for the C++11 # standard; if necessary, add switches to CXXFLAGS to enable support. # # The first argument, if specified, indicates whether you insist on an # extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. # -std=c++11). If neither is specified, you get whatever works, with # preference for an extended mode. # # The second argument, if specified 'mandatory' or if left unspecified, # indicates that baseline C++11 support is required and that the macro # should error out if no mode with that support is found. If specified # 'optional', then configuration proceeds regardless, after defining # HAVE_CXX11 if and only if a supporting mode is found. # # LICENSE # # Copyright (c) 2008 Benjamin Kosnik # Copyright (c) 2012 Zack Weinberg # Copyright (c) 2013 Roy Stogner # Copyright (c) 2014 Alexey Sokolov # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 4 m4_define([_AX_CXX_COMPILE_STDCXX_11_testbody], [[ template struct check { static_assert(sizeof(int) <= sizeof(T), "not big enough"); }; struct Base { virtual void f() {} }; struct Child : public Base { virtual void f() override {} }; typedef check> right_angle_brackets; int a; decltype(a) b; typedef check check_type; check_type c; check_type&& cr = static_cast(c); auto d = a; auto l = [](){}; ]]) AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [dnl m4_if([$1], [], [], [$1], [ext], [], [$1], [noext], [], [m4_fatal([invalid argument `$1' to AX_CXX_COMPILE_STDCXX_11])])dnl m4_if([$2], [], [ax_cxx_compile_cxx11_required=true], [$2], [mandatory], [ax_cxx_compile_cxx11_required=true], [$2], [optional], [ax_cxx_compile_cxx11_required=false], [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX_11])]) AC_LANG_PUSH([C++])dnl ac_success=no AC_CACHE_CHECK(whether $CXX supports C++11 features by default, ax_cv_cxx_compile_cxx11, [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], [ax_cv_cxx_compile_cxx11=yes], [ax_cv_cxx_compile_cxx11=no])]) if test x$ax_cv_cxx_compile_cxx11 = xyes; then ac_success=yes fi m4_if([$1], [noext], [], [dnl if test x$ac_success = xno; then for switch in -std=gnu++11 -std=gnu++0x; do cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch]) AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch, $cachevar, [ac_save_CXXFLAGS="$CXXFLAGS" CXXFLAGS="$CXXFLAGS $switch" AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], [eval $cachevar=yes], [eval $cachevar=no]) CXXFLAGS="$ac_save_CXXFLAGS"]) if eval test x\$$cachevar = xyes; then CXXFLAGS="$CXXFLAGS $switch" ac_success=yes break fi done fi]) m4_if([$1], [ext], [], [dnl if test x$ac_success = xno; then for switch in -std=c++11 -std=c++0x; do cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch]) AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch, $cachevar, [ac_save_CXXFLAGS="$CXXFLAGS" CXXFLAGS="$CXXFLAGS $switch" AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], [eval $cachevar=yes], [eval $cachevar=no]) CXXFLAGS="$ac_save_CXXFLAGS"]) if eval test x\$$cachevar = xyes; then CXXFLAGS="$CXXFLAGS $switch" ac_success=yes break fi done fi]) AC_LANG_POP([C++]) if test x$ax_cxx_compile_cxx11_required = xtrue; then if test x$ac_success = xno; then AC_MSG_ERROR([*** A compiler with support for C++11 language features is required.]) fi else if test x$ac_success = xno; then HAVE_CXX11=0 AC_MSG_NOTICE([No compiler with C++11 support was found]) else HAVE_CXX11=1 AC_DEFINE(HAVE_CXX11,1, [define if the compiler supports basic C++11 syntax]) fi AC_SUBST(HAVE_CXX11) fi ]) tntdb-1.4/pkgconfig/000077500000000000000000000000001354703061500144445ustar00rootroot00000000000000tntdb-1.4/pkgconfig/tntdb.pc.in000066400000000000000000000003771354703061500165170ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: tntdb Description: C++ class library for easy database access Version: @PACKAGE_VERSION@ Libs: -L${libdir} -ltntdb Cflags: -I${includedir} Requires.private: cxxtools tntdb-1.4/src/000077500000000000000000000000001354703061500132645ustar00rootroot00000000000000tntdb-1.4/src/Makefile.am000066400000000000000000000012221354703061500153150ustar00rootroot00000000000000AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include lib_LTLIBRARIES = libtntdb.la libtntdb_la_SOURCES = \ blob.cpp \ blobstream.cpp \ connect.cpp \ connection.cpp \ connectionpool.cpp \ date.cpp \ datetime.cpp \ decimal.cpp \ error.cpp \ librarymanager.cpp \ poolconnection.cpp \ result.cpp \ resultimpl.cpp \ row.cpp \ rowimpl.cpp \ serialization.cpp \ sqlbuilder.cpp \ statement.cpp \ statement_iterator.cpp \ stmtparser.cpp \ time.cpp \ transaction.cpp \ valueimpl.cpp libtntdb_la_LDFLAGS = -version-info @sonumber@ @SHARED_LIB_FLAG@ libtntdb_la_CXXFLAGS = -DDRIVERDIR=\"@driverdir@\" -DABI_CURRENT=\"@abi_current@\" tntdb-1.4/src/blob.cpp000066400000000000000000000042301354703061500147050ustar00rootroot00000000000000/* * Copyright (C) 2007-2008 Tommi Maekitalo * Copyright (C) 2007-2008 Marc Boris Duerner * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include namespace tntdb { IBlob::~IBlob() { } void BlobImpl::assign(const char* data, std::size_t len) { reserve(len, false); std::memcpy(_data, data, len); _size = len; } char* BlobImpl::reserve(std::size_t len, bool shrink) { if (len == 0 && shrink) { delete[] _data; _data = 0; _size = 0; } else { if ((shrink && len != this->size()) || len > this->size()) { delete[] _data; _data = new char[len]; } _size = len; } return _data; } IBlob* BlobImpl::create() const { return new BlobImpl(); } void BlobImpl::destroy() { delete this; } } tntdb-1.4/src/blobstream.cpp000066400000000000000000000035001354703061500161200ustar00rootroot00000000000000/* * Copyright (C) 2011 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include namespace tntdb { BlobStreamBuf::BlobStreamBuf(Blob& blob) { char* ptr = const_cast(blob.data()); if (ptr) setg(ptr, ptr, ptr + blob.size()); } BlobStreamBuf::int_type BlobStreamBuf::overflow(BlobStreamBuf::int_type c) { return traits_type::eof(); } BlobStreamBuf::int_type BlobStreamBuf::underflow() { return traits_type::eof(); } int BlobStreamBuf::sync() { return 0; } } tntdb-1.4/src/connect.cpp000066400000000000000000000100501354703061500154150ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include "config.h" log_define("tntdb.connect") namespace tntdb { typedef std::map librariesType; static librariesType libraries; static cxxtools::Mutex mutex; Connection connect(const std::string& url, const std::string& username, const std::string& password) { log_debug("connect(\"" << url << "\", \"" << username << "\", password)"); std::string::size_type n = url.find(':'); if (n == std::string::npos) throw Error("invalid dburl \"" + url + '"'); std::string driverName = url.substr(0, n); std::string libraryUrl = url.substr(n + 1); log_debug("driver \"" << driverName << "\" url=\"" << libraryUrl << '"'); cxxtools::MutexLock lock(mutex); // lookup library-manager LibraryManager libraryManager; librariesType::const_iterator it = libraries.find(driverName); if (it == libraries.end()) { libraryManager = LibraryManager(driverName); libraries[driverName] = libraryManager; } else libraryManager = it->second; lock.unlock(); return libraryManager.connect(libraryUrl, username, password); } Connection connect(const std::string& url) { return connect(url, std::string(), std::string()); } static ConnectionPools connectionPools; unsigned cachedConnections() { return connectionPools.getCurrentSize(); } unsigned cachedConnections(const std::string& url, const std::string& username, const std::string& password) { return connectionPools.getCurrentSize(url, username, password); } unsigned cachedConnections(const std::string& url) { return connectionPools.getCurrentSize(url, std::string(), std::string()); } Connection connectCached(const std::string& url, const std::string& username, const std::string& password) { log_debug("connectCached(\"" << url << "\", \"" << username << "\", password)"); return connectionPools.connect(url, username, password); } Connection connectCached(const std::string& url) { return connectCached(url, std::string(), std::string()); } unsigned dropCached(unsigned keep) { return connectionPools.drop(keep); } unsigned dropCached(const std::string& url, const std::string& username, const std::string& password, unsigned keep) { return connectionPools.drop(url, username, password, keep); } void setMaxPoolSize(unsigned max) { connectionPools.setMaximumSize(max); } unsigned getMaxPoolSize() { return connectionPools.getMaximumSize(); } } tntdb-1.4/src/connection.cpp000066400000000000000000000157601354703061500161400ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include log_define("tntdb.connection") namespace tntdb { void Connection::beginTransaction() { log_trace("Connection::beginTransaction()"); _conn->beginTransaction(); } void Connection::commitTransaction() { log_trace("Connection::commitTransaction"); _conn->commitTransaction(); } void Connection::rollbackTransaction() { log_trace("Connection::rollbackTransaction"); _conn->rollbackTransaction(); } Connection::size_type Connection::execute(const std::string& query) { log_trace("Connection::execute(\"" << query << "\")"); return _conn->execute(query); } Result Connection::select(const std::string& query) { log_trace("Connection::select(\"" << query << "\")"); return _conn->select(query); } Row Connection::selectRow(const std::string& query) { log_trace("Connection::selectRow(\"" << query << "\")"); return _conn->selectRow(query); } Value Connection::selectValue(const std::string& query) { log_trace("Connection::selectValue(\"" << query << "\")"); return _conn->selectValue(query); } Statement Connection::prepare(const std::string& query) { log_trace("Connection::prepare(\"" << query << "\")"); return _conn->prepare(query); } Statement Connection::prepareWithLimit(const std::string& query, const std::string& limit, const std::string& offset) { log_trace("Connection::prepareWithLimit(\"" << query << ", " << limit << "\", \"" << offset << "\")"); return _conn->prepareWithLimit(query, limit, offset); } Statement Connection::prepareCached(const std::string& query, const std::string& key) { log_trace("Connection::prepareCached(\"" << query << "\")"); return _conn->prepareCached(query, key); } Statement Connection::prepareCachedWithLimit(const std::string& query, const std::string& limit, const std::string& offset, const std::string& key) { log_trace("Connection::prepareCachedWithLimit(\"" << query << ", " << limit << "\", \"" << offset << "\", \"" << key << "\")"); return _conn->prepareCachedWithLimit(query, limit, offset, key); } std::string IConnection::url(const std::string& url, const std::string& username, const std::string& password) { enum { state_0, state_p, state_e } state = state_0; std::string ret; for (std::string::const_iterator it = url.begin(); it != url.end(); ++it) { char ch = *it; switch (state) { case state_0: if (ch == '%') state = state_p; else if (ch == '\\') state = state_e; else ret += ch; break; case state_p: if (ch == 'u') { ret += username; state = state_0; } else if (ch == 'p') { ret += password; state = state_0; } else if (ch == '%') ret += '%'; else if (ch == '\\') { ret += '%'; state = state_e; } else { ret += '%'; ret += ch; state = state_0; } break; case state_e: ret += ch; state = state_0; break; } } switch (state) { case state_0: break; case state_p: ret += '%'; break; case state_e: ret += '\\'; break; } return ret; } Statement IStmtCacheConnection::prepareCached(const std::string& query, const std::string& key) { log_trace("IStmtCacheConnection::prepareCached(\"" << query << ", " << key << "\")"); stmtCacheType::iterator it = stmtCache.find(key); if (it == stmtCache.end()) { log_debug("statement for query \"" << key << "\" not found in cache"); Statement stmt = prepare(query); IStatement* istmt = const_cast(stmt.getImpl()); stmtCache.insert(stmtCacheType::value_type(key, istmt)); return stmt; } else { log_debug("statement for query \"" << key << "\" fetched from cache"); return Statement(it->second.getPointer()); } } Statement IStmtCacheConnection::prepareCachedWithLimit(const std::string& query, const std::string& limit, const std::string& offset, const std::string& key) { log_trace("IStmtCacheConnection::prepareCachedWithLimit(\"" << query << ", " << limit << "\", \"" << offset << "\", \"" << key << "\")"); std::string lkey = key + ':' + limit + ':' + offset; stmtCacheType::iterator it = stmtCache.find(lkey); if (it == stmtCache.end()) { log_debug("statement for query \"" << lkey << "\" not found in cache"); Statement stmt = prepareWithLimit(query, limit, offset); IStatement* istmt = const_cast(stmt.getImpl()); stmtCache.insert(stmtCacheType::value_type(lkey, istmt)); return stmt; } else { log_debug("statement for query \"" << lkey << "\" fetched from cache"); return Statement(it->second.getPointer()); } } void IStmtCacheConnection::clearStatementCache() { log_trace("IStmtCacheConnection::clearStatementCache()"); stmtCache.clear(); } bool IStmtCacheConnection::clearStatementCache(const std::string& key) { log_trace("IStmtCacheConnection::clearStatementCache(\"" << key << "\")"); stmtCacheType::iterator it = stmtCache.find(key); if (it == stmtCache.end()) return false; log_debug("remove statement for query \"" << key << "\" from cache"); stmtCache.erase(it); return true; } } tntdb-1.4/src/connectionpool.cpp000066400000000000000000000141651354703061500170300ustar00rootroot00000000000000/* * Copyright (C) 2006 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include log_define("tntdb.connectionpool") namespace tntdb { //////////////////////////////////////////////////////////////////////// // Connector // Connection* ConnectionPool::Connector::operator() () { log_debug("create new connection for url \"" << url << "\" user \"" << username << '"'); return new Connection(tntdb::connect(url, username, password)); } //////////////////////////////////////////////////////////////////////// // ConnectionPool // Connection ConnectionPool::connect() { log_debug("ConnectionPool::connect()"); log_debug("current pool size " << getCurrentSize() << " max " << getMaximumSize()); unsigned max = getCurrentSize() * 2; for (unsigned n = 0; n < max; ++n) { Connection conn(new PoolConnection(pool.get())); if (conn.ping()) return conn; // a pool-connection don't put itself back into the pool after a failed ping log_warn("drop dead connection from pool"); } return Connection(new PoolConnection(pool.get())); } unsigned ConnectionPool::drop(unsigned keep) { unsigned size = pool.size(); pool.drop(keep); return size - pool.size(); } //////////////////////////////////////////////////////////////////////// // ConnectionPools // ConnectionPools::~ConnectionPools() { cxxtools::MutexLock lock(mutex); for (PoolsType::iterator it = pools.begin(); it != pools.end(); ++it) delete it->second; } Connection ConnectionPools::connect(const std::string& url, const std::string& username, const std::string& password) { log_debug("ConnectionPools::connect(\"" << url << "\", \"" << username << "\", password)"); PoolsType::iterator it; { cxxtools::MutexLock lock(mutex); it = pools.find(ConnectionParameter(url, username, password)); if (it == pools.end()) { log_debug("create pool for url \"" << url << "\" user \"" << username << "\" with " << maxcount << " connections"); PoolType* pool = new PoolType(url, username, password, maxcount); it = pools.insert(PoolsType::value_type(ConnectionParameter(url, username, password), pool)).first; } else log_debug("pool for url \"" << url << "\" found"); } log_debug("current pool size " << it->second->getCurrentSize()); return it->second->connect(); } unsigned ConnectionPools::drop(unsigned keep) { log_debug("drop(" << keep << ')'); cxxtools::MutexLock lock(mutex); unsigned dropcount = 0; for (PoolsType::iterator it = pools.begin(); it != pools.end(); ++it) { log_debug("pool url \"" << it->first.url << "\" username \"" << it->first.username << "\"; current size " << it->second->getCurrentSize()); dropcount += it->second->drop(); log_debug("connections released " << it->second->getCurrentSize() << " kept"); } return dropcount; } unsigned ConnectionPools::drop(const std::string& url, const std::string& username, const std::string& password, unsigned keep) { log_debug("drop(\"" << url << "\", \"" << username << "\", password, " << keep << ')'); cxxtools::MutexLock lock(mutex); unsigned dropcount = 0; PoolsType::iterator it = pools.find(ConnectionParameter(url, username, password)); if (it != pools.end()) { log_debug("pool \"" << url << "\" found; current size " << it->second->getCurrentSize()); dropcount = it->second->drop(keep); log_debug(dropcount << " connections released " << it->second->getCurrentSize() << " kept"); if (it->second->getCurrentSize() == 0) { log_debug("delete connectionpool for url \"" << url << "\", username \"" << username << '"'); delete it->second; pools.erase(it); } } else log_debug("pool for url \"" << url << "\" username \"" << username << "\" not found"); return dropcount; } unsigned ConnectionPools::getCurrentSize(const std::string& url, const std::string& username, const std::string& password) const { cxxtools::MutexLock lock(mutex); PoolsType::const_iterator it = pools.find(ConnectionParameter(url, username, password)); return it == pools.end() ? 0 : it->second->getCurrentSize(); } unsigned ConnectionPools::getCurrentSize() const { cxxtools::MutexLock lock(mutex); unsigned size = 0; for (PoolsType::const_iterator it = pools.begin(); it != pools.end(); ++it) size += it->second->getCurrentSize(); return size; } void ConnectionPools::setMaximumSize(unsigned m) { cxxtools::MutexLock lock(mutex); maxcount = m; for (PoolsType::const_iterator it = pools.begin(); it != pools.end(); ++it) it->second->setMaximumSize(m); } } tntdb-1.4/src/date.cpp000066400000000000000000000071061354703061500147110ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include namespace tntdb { Date Date::localtime() { struct timeval tv; struct tm tm; gettimeofday(&tv, 0); time_t t = static_cast(tv.tv_sec); localtime_r(&t, &tm); return Date(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); } Date Date::gmtime() { struct timeval tv; struct tm tm; gettimeofday(&tv, 0); time_t t = static_cast(tv.tv_sec); gmtime_r(&t, &tm); return Date(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); } unsigned short Date::getWDay() const { struct tm tm; memset(&tm, 0, sizeof(struct tm)); tm.tm_mday = _day; tm.tm_mon = _month - 1; tm.tm_year = _year - 1900; time_t t = mktime(&tm); localtime_r(&t, &tm); return tm.tm_wday; } std::string Date::getIso() const { // format YYYY-MM-DD // 0....+....1 char ret[10]; unsigned short n = _year; ret[3] = '0' + n % 10; n /= 10; ret[2] = '0' + n % 10; n /= 10; ret[1] = '0' + n % 10; n /= 10; ret[0] = '0' + n % 10; ret[4] = '-'; ret[5] = '0' + _month / 10; ret[6] = '0' + _month % 10; ret[7] = '-'; ret[8] = '0' + _day / 10; ret[9] = '0' + _day % 10; return std::string(ret, 10); } inline unsigned short getNumber2(const char* s) { if (!std::isdigit(s[0]) || !std::isdigit(s[1])) throw TypeError(); return (s[0] - '0') * 10 + (s[1] - '0'); } inline unsigned short getNumber4(const char* s) { if (!std::isdigit(s[0]) || !std::isdigit(s[1]) || !std::isdigit(s[2]) || !std::isdigit(s[3])) throw TypeError(); return (s[0] - '0') * 1000 + (s[1] - '0') * 100 + (s[2] - '0') * 10 + (s[3] - '0'); } Date Date::fromIso(const std::string& s) { Date ret; const char* d = s.data(); try { if (s.size() < 10 || d[4] != '-' || d[7] != '-') throw TypeError(); ret.set(getNumber4(d), getNumber2(d + 5), getNumber2(d + 8)); } catch (const TypeError&) { throw TypeError("failed to convert string \"" + s + "\" into date"); } return ret; } } tntdb-1.4/src/datetime.cpp000066400000000000000000000113441354703061500155670ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include namespace tntdb { Datetime Datetime::localtime() { struct timeval tv; struct tm tm; gettimeofday(&tv, 0); time_t t = static_cast(tv.tv_sec); localtime_r(&t, &tm); return Datetime(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, tv.tv_usec / 1000); } Datetime Datetime::gmtime() { struct timeval tv; struct tm tm; gettimeofday(&tv, 0); time_t t = static_cast(tv.tv_sec); gmtime_r(&t, &tm); return Datetime(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, tv.tv_usec / 1000); } std::string Datetime::getIso() const { // format YYYY-MM-DD hh:mm:ss.sss // 0....+....1....+....2....+ char ret[25]; unsigned short n = _year; ret[3] = '0' + n % 10; n /= 10; ret[2] = '0' + n % 10; n /= 10; ret[1] = '0' + n % 10; n /= 10; ret[0] = '0' + n % 10; ret[4] = '-'; ret[5] = '0' + _month / 10; ret[6] = '0' + _month % 10; ret[7] = '-'; ret[8] = '0' + _day / 10; ret[9] = '0' + _day % 10; ret[10] = ' '; ret[11] = '0' + _hour / 10; ret[12] = '0' + _hour % 10; ret[13] = ':'; ret[14] = '0' + _minute / 10; ret[15] = '0' + _minute % 10; ret[16] = ':'; ret[17] = '0' + _second / 10; ret[18] = '0' + _second % 10; ret[19] = '.'; n = _millis; ret[22] = '0' + n % 10; n /= 10; ret[21] = '0' + n % 10; n /= 10; ret[20] = '0' + n % 10; return std::string(ret, 23); } inline unsigned short getNumber2(const char* s) { if (!std::isdigit(s[0]) || !std::isdigit(s[1])) throw TypeError(); return (s[0] - '0') * 10 + (s[1] - '0'); } inline unsigned short getNumber3(const char* s) { if (!std::isdigit(s[0]) || !std::isdigit(s[1]) || !std::isdigit(s[2])) throw TypeError(); return (s[0] - '0') * 100 + (s[1] - '0') * 10 + (s[2] - '0'); } inline unsigned short getNumber4(const char* s) { if (!std::isdigit(s[0]) || !std::isdigit(s[1]) || !std::isdigit(s[2]) || !std::isdigit(s[3])) throw TypeError(); return (s[0] - '0') * 1000 + (s[1] - '0') * 100 + (s[2] - '0') * 10 + (s[3] - '0'); } Datetime Datetime::fromIso(const std::string& s) { Datetime ret; const char* d = s.data(); try { if (s.size() == 23 && d[4] == '-' && d[7] == '-' && d[10] == ' ' && d[13] == ':' && d[16] == ':' && d[19] == '.') { ret.set(getNumber4(d), getNumber2(d + 5), getNumber2(d + 8), getNumber2(d + 11), getNumber2(d + 14), getNumber2(d + 17), getNumber3(d + 20)); } else if (s.size() == 19 && d[4] == '-' && d[7] == '-' && d[10] == ' ' && d[13] == ':' && d[16] == ':') { ret.set(getNumber4(d), getNumber2(d + 5), getNumber2(d + 8), getNumber2(d + 11), getNumber2(d + 14), getNumber2(d + 17)); } else throw TypeError(); } catch (const TypeError&) { throw TypeError("failed to convert string \"" + s + "\" into datetime"); } return ret; } } tntdb-1.4/src/decimal.cpp000066400000000000000000000406651354703061500154010ustar00rootroot00000000000000/* * Copyright (C) 2007,2012 Tommi Maekitalo, Mark Wright * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include log_define("tntdb.decimal") namespace tntdb { namespace { void throwConversionError(const std::string& s) { log_warn("failed to convert \"" << s << "\" to decimal"); throw std::runtime_error("failed to convert \"" + s + "\" to decimal"); } void throwOverflowError(const Decimal& d) { log_warn("overflow when trying to read integer from decimal " << d.toString()); throw std::overflow_error("overflow when trying to read integer from decimal " + d.toString()); } int stringCompareIgnoreCase(const char* const& s1, const char* const& s2) { const char* it1 = s1; const char* it2 = s2; while (*it1 && *it2) { if (*it1 != *it2) { char c1 = std::toupper(*it1); char c2 = std::toupper(*it2); if (c1 < c2) return -1; else if (c2 < c1) return 1; } ++it1; ++it2; } return *it1 ? 1 : *it2 ? -1 : 0; } void stripZeros(std::string& s) { std::string::size_type pos; for (pos = s.size(); pos > 1; --pos) { if (s[pos - 1] != '0') break; } s.erase(pos); } } class Decimal::Parser { enum { state_0, state_man0, state_man, state_fract0, state_fract, state_exp0, state_exp1, state_exp, state_special, state_end } _state; Decimal* _value; std::string _str; short _eoff; bool _eneg; public: Parser() : _value(0), _eoff(0), _eneg(false) { } void begin(Decimal& d); void parse(char ch); void finish(); }; void Decimal::Parser::begin(Decimal& d) { _state = state_0; _value = &d; _str.clear(); _eoff = 0; _eneg = false; d._mantissa.clear(); d._exponent = 0; d._negative = false; } void Decimal::Parser::parse(char ch) { _str += ch; switch (_state) { case state_0: if (ch == '+') { _state = state_man0; } else if (ch == '-') { _value->_negative = true; _state = state_man0; } else if (ch == '.') { _state = state_fract0; } else if (ch == '0') { _state = state_man; } else if (ch >= '1' && ch <= '9') { _value->_mantissa = ch; _state = state_man; } else if (std::isalpha(ch)) _state = state_special; else if (!std::isspace(ch)) throwConversionError(_str); break; case state_man0: if (ch == '.') { _state = state_fract0; } else if (ch == '0') { _state = state_man; } else if (ch >= '1' && ch <= '9') { _value->_mantissa = ch; _state = state_man; } else if (std::isalpha(ch)) _state = state_special; else throwConversionError(_str); break; case state_man: if (ch == '0' && _value->_mantissa.empty()) { } else if (ch >= '0' && ch <= '9') { _value->_mantissa += ch; } else { _eoff = _value->_mantissa.size(); if (ch == '.') { _state = _value->_mantissa.empty() ? state_fract0 : state_fract; } else if (ch == 'e' || ch == 'E') { _state = state_exp0; } else if (std::isspace(ch)) _state = state_end; else throwConversionError(_str); } break; case state_fract0: if (ch == '0') { --_eoff; break; } else if (ch == 'e' || ch == 'E') { if (_eoff == 0) throwConversionError(_str); _value->_mantissa = '0'; _eoff = 0; _state = state_exp0; break; } _state = state_fract; // nobreak case state_fract: if (ch >= '0' && ch <= '9') { _value->_mantissa += ch; } else if (ch == 'e' || ch == 'E') { _state = state_exp0; } else if (std::isspace(ch)) _state = state_end; else throwConversionError(_str); break; case state_exp0: if (ch == '+') { _state = state_exp1; break; } else if (ch == '-') { _eneg = true; break; } _state = state_exp1; // nobreak case state_exp1: case state_exp: if (ch >= '0' && ch <= '9') { if (_value->_exponent > (std::numeric_limits::max() - (ch - '0') / 10)) throw std::overflow_error("overflow error when converting \"" + _str + "\" to decimal"); _value->_exponent = _value->_exponent * 10 + (ch - '0'); _state = state_exp; } else if (std::isspace(ch)) _state = state_end; else throwConversionError(_str); break; case state_special: if (_str.size() > 4) throwConversionError(_str); if (std::isalpha(ch) && _str.size() >= 3) { if (stringCompareIgnoreCase(_str.c_str(), "inf") == 0 || stringCompareIgnoreCase(_str.c_str(), "+inf") == 0) { _value->_exponent = std::numeric_limits::max(); _state = state_end; } else if (stringCompareIgnoreCase(_str.c_str(), "-inf") == 0) { _value->_negative = true; _value->_exponent = std::numeric_limits::max(); _state = state_end; } else if (stringCompareIgnoreCase(_str.c_str(), "nan") == 0) { _value->_exponent = 0; _state = state_end; } } break; case state_end: if (!std::isspace(ch)) throwConversionError(_str); } } void Decimal::Parser::finish() { if (_state == state_0 || _state == state_man0 || _state == state_exp0 || _state == state_exp1 || _state == state_special) throwConversionError(_str); if (_state == state_man) { if (_value->_mantissa.empty()) _value->_mantissa = '0'; else _eoff = _value->_mantissa.size(); } else if (_state == state_end && _value->_mantissa.empty()) { return; } if (_eneg) _value->_exponent = -_value->_exponent; _value->_exponent += _eoff; stripZeros(_value->_mantissa); if (_value->_mantissa.empty()) { _value->_mantissa = "0"; _value->_exponent = 0; } } Decimal::Decimal() : _mantissa("0"), _exponent(0), _negative(false) { } Decimal::LongType Decimal::_getInteger(LongType min, LongType max, short exponent) const { log_debug("getInteger; min=" << min << " max=" << max << " value=" << getDouble()); if (!negative()) return static_cast(_getUnsigned(static_cast(max), exponent)); if (isPositiveInfinity() || isNegativeInfinity() || isNaN()) throwOverflowError(*this); // TODO check for overflow: short exp = _exponent + exponent; if (exp < 0) return 0; if (exp == 0) return !_mantissa.empty() && _mantissa[0] >= '5' ? -1 : 0; LongType ret = 0; std::string::size_type n; for (n = 0; exp - n > 0; ++n) { LongType d = n < _mantissa.size() ? (_mantissa[n] - '0') : 0; if (ret < (min + d) / 10) throwOverflowError(*this); ret = ret * 10 - d; } if (n < _mantissa.size() && _mantissa[n] >= '5') { if (ret == min) throwOverflowError(*this); --ret; } return ret; } Decimal::UnsignedLongType Decimal::_getUnsigned(UnsignedLongType max, short exponent) const { log_debug("getUnsigned; max=" << max << " value=" << getDouble()); if (negative() || isPositiveInfinity() || isNegativeInfinity() || isNaN()) throwOverflowError(*this); short exp = _exponent + exponent; if (exp < 0) return 0; if (exp == 0) return !_mantissa.empty() && _mantissa[0] >= '5' ? 1 : 0; UnsignedLongType ret = 0; std::string::size_type n; for (n = 0; exp - n > 0; ++n) { UnsignedLongType d = n < _mantissa.size() ? (_mantissa[n] - '0') : 0; if (ret > (max - d) / 10) throwOverflowError(*this); ret = ret * 10 + d; } if (n < _mantissa.size() && _mantissa[n] >= '5') { if (ret == max) throwOverflowError(*this); ++ret; } return ret; } void Decimal::setDouble(long double value) { if (value == std::numeric_limits::infinity()) { _negative = false; _exponent = std::numeric_limits::max(); } else if (value == -std::numeric_limits::infinity()) { _negative = true; _exponent = std::numeric_limits::max(); } else if (value != value) // check for nan { _negative = false; _exponent = 0; } else { long double v = value; _negative = v < 0; if (_negative) v = -v; _exponent = static_cast(std::log10(v)) + 1; if (_exponent > std::numeric_limits::max_exponent10) { v /= 10; v /= std::pow(static_cast(10), static_cast(_exponent - 1)); } else if (_exponent < -std::numeric_limits::max_exponent10) { v *= 10; v /= std::pow(static_cast(10), static_cast(_exponent + 1)); } else v /= std::pow(static_cast(10), static_cast(_exponent)); for (int n = 0; n <= std::numeric_limits::digits10; ++n) { unsigned short d = static_cast(v * 10); v = v * 10 - d; _mantissa += static_cast(d + '0'); } unsigned short d = static_cast(v * 10); if (d >= 5) ++_mantissa[_mantissa.size()-1]; stripZeros(_mantissa); } log_debug("double value=" << value << " => negative=" << _negative << " mantissa=" << _mantissa << " exponent=" << _exponent); } Decimal::Decimal(const std::string& value) : _exponent(0), _negative(false) { Parser parser; parser.begin(*this); for (std::string::const_iterator it = value.begin(); it != value.end(); ++it) parser.parse(*it); parser.finish(); log_debug("string value \"" << value << "\" => negative=" << _negative << " mantissa=" << _mantissa << " exponent=" << _exponent); } long double Decimal::getDouble() const { if (isPositiveInfinity()) return std::numeric_limits::infinity(); if (isNegativeInfinity()) return -std::numeric_limits::infinity(); if (isNaN()) return std::numeric_limits::quiet_NaN(); long double ret = 0; long double mul = 1; for (std::string::const_iterator it = _mantissa.begin(); it != _mantissa.end(); ++it) { mul /= 10; ret += (*it - '0') * mul; } if (_exponent == std::numeric_limits::max_exponent10 + 1) { ret *= std::pow(static_cast(10), static_cast(_exponent - 1)); ret *= 10; if (ret == std::numeric_limits::infinity()) ret = std::numeric_limits::max(); } else if (_exponent == std::numeric_limits::min_exponent10 - 1) { ret *= std::pow(static_cast(10), static_cast(_exponent + 1)); ret /= 10; if (ret == -std::numeric_limits::infinity()) ret = std::numeric_limits::min(); } else { ret *= std::pow(static_cast(10), static_cast(_exponent)); } if (_negative) ret = -ret; log_debug("getDouble mantissa=" << _mantissa << " exponent=" << _exponent << " negative=" << _negative << " => " << ret); return ret; } void Decimal::_setInteger(LongType l, short exponent) { _mantissa = cxxtools::convert(l); if (_mantissa[0] == '-') { _mantissa.erase(0, 1); _negative = true; } else _negative = false; _exponent = exponent + _mantissa.size(); stripZeros(_mantissa); log_debug("setInteger(" << l << ", " << exponent << ") => negative=" << _negative << " mantissa=" << _mantissa << " exponent=" << _exponent); } void Decimal::_setUnsigned(UnsignedLongType l, short exponent) { _mantissa = cxxtools::convert(l); _negative = false; _exponent = exponent + _mantissa.size(); stripZeros(_mantissa); log_debug("setUnsigned(" << l << ", " << exponent << ") => mantissa=" << _mantissa << " exponent=" << _exponent); } bool Decimal::operator< (const Decimal& other) const { if (_negative != other._negative) return _negative; if (_exponent != other._exponent) return _exponent < other._exponent; return _mantissa < other._mantissa; } std::string Decimal::toString() const { return (_exponent < 0 || _exponent > 8) ? toStringSci() : toStringFix(); } std::string Decimal::toStringSci() const { if (isPositiveInfinity()) return "inf"; else if (isNegativeInfinity()) return "-inf"; else if (isNaN()) return "nan"; else { std::string ret; if (_negative) ret = '-'; ret += _mantissa[0]; if (_mantissa.size() > 1) { ret += '.'; ret.append(_mantissa, 1, _mantissa.size() - 1); } ret += 'e'; ret += cxxtools::convert(_exponent - 1); return ret; } } std::string Decimal::toStringFix() const { if (isPositiveInfinity()) return "inf"; else if (isNegativeInfinity()) return "-inf"; else if (isNaN()) return "nan"; else { std::string ret; if (_exponent < 1) { ret = "0."; ret.append(-_exponent, '0'); ret.append(_mantissa); } else { ret = _mantissa; if (_exponent < static_cast(_mantissa.size())) ret.insert(_exponent, 1, '.'); else ret.append(_exponent - _mantissa.size(), '0'); } if (_negative) ret.insert(0u, 1u, '-'); return ret; } } std::istream& operator>> (std::istream& in, Decimal& dec) { Decimal::Parser parser; parser.begin(dec); int ch; while ((ch = in.rdbuf()->sbumpc()) != std::istream::traits_type::eof() && !std::isspace(std::istream::traits_type::to_char_type(ch))) { parser.parse(std::istream::traits_type::to_char_type(ch)); } parser.finish(); return in; } std::ostream& operator<< (std::ostream& out, const Decimal& dec) { out << dec.toString(); return out; } } // vim:et:sw=2 tntdb-1.4/src/error.cpp000066400000000000000000000037301354703061500151240ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include log_define("tntdb.error") namespace tntdb { Error::Error(const std::string& msg) : std::runtime_error(msg) { log_debug("Error: " << what()); } NotFound::NotFound() : Error("not found") { } NullValue::NullValue() : Error("null value") { } TypeError::TypeError(const std::string& msg) : Error(msg) { } SqlError::SqlError(const std::string& sql_, const std::string& msg) : Error(msg), sql(sql_) { } FieldNotFound::FieldNotFound(const std::string& field_) : Error("field \"" + field_ + "\" not found"), field(field_) { } } tntdb-1.4/src/librarymanager.cpp000066400000000000000000000057301354703061500167740ustar00rootroot00000000000000/* * Copyright (C) 2006 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #ifndef DRIVERDIR #define DRIVERDIR "tntdb" #endif #define TNTDB_STRINGIFY(x) #x #define TNTDB_TOSTRING(x) TNTDB_STRINGIFY(x) log_define("tntdb.librarymanager") namespace tntdb { static const std::string libraryPrefix = "tntdb" ABI_CURRENT "-"; LibraryManager::LibraryManager(const std::string& driverName) { try { log_debug("loading library \"" << libraryPrefix << driverName << '"'); lib = cxxtools::Library(libraryPrefix + driverName); } catch (const cxxtools::FileNotFound& e) { log_debug("library \"" << libraryPrefix << driverName << "\" not found: " << e.what()); } catch (const cxxtools::OpenLibraryFailed& e) { log_debug("opening library \"" << libraryPrefix << driverName << "\" failed: " << e.what()); } try { if (!lib) { std::string d = DRIVERDIR + cxxtools::Directory::sep() + libraryPrefix + driverName; log_debug("loading library \"" << d << '"'); lib = cxxtools::Library(d); } } catch (const std::exception& e) { std::ostringstream msg; msg << "failed to load driver \"" << libraryPrefix << driverName << '"'; log_warn(msg.str() << ": " << e.what()); throw Error(msg.str()); } std::string symbolName = TNTDB_TOSTRING(TNTDB_DRIVER_PRAEFIX) + driverName; void* sym = lib.getSymbol(symbolName.c_str()); connectionManager = static_cast(sym); log_debug("driver " << driverName << " successfully loaded"); } } tntdb-1.4/src/mysql/000077500000000000000000000000001354703061500144315ustar00rootroot00000000000000tntdb-1.4/src/mysql/Makefile.am000066400000000000000000000010721354703061500164650ustar00rootroot00000000000000AM_CPPFLAGS = @MYSQL_CFLAGS@ -I$(top_srcdir)/include -I$(top_builddir)/include sources = bindutils.cpp bindvalues.cpp boundrow.cpp boundvalue.cpp connection.cpp connectionmanager.cpp cursor.cpp error.cpp resultrow.cpp rowcontainer.cpp rowvalue.cpp statement.cpp result.cpp if MAKE_MYSQL driver_LTLIBRARIES = tntdb@abi_current@-mysql.la tntdb@abi_current@_mysql_la_SOURCES = $(sources) tntdb@abi_current@_mysql_la_LDFLAGS = -module -version-info @sonumber@ @MYSQL_LDFLAGS@ @SHARED_LIB_FLAG@ tntdb@abi_current@_mysql_la_LIBADD = $(top_builddir)/src/libtntdb.la endif tntdb-1.4/src/mysql/bindutils.cpp000066400000000000000000000525361354703061500171450ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include log_define("tntdb.mysql.bindutils") namespace tntdb { namespace mysql { void release(MYSQL_BIND& bind) { log_debug("release buffer"); delete[] static_cast(bind.buffer); bind.buffer = 0; bind.buffer_length = 0; bind.is_null = 0; } void reserve(MYSQL_BIND& bind, unsigned long size) { // At least for timestamp-data metadata returns a too small size-value, // so we grow it to at least 64 bytes. I don't know if this is a bug in // mysql or here. if (size < 64) size = 64; if (bind.buffer_length < size) { log_debug("grow buffer to " << size << " initial " << bind.buffer_length); delete[] static_cast(bind.buffer); bind.buffer = new char[size]; bind.buffer_length = size; } } void reserveKeep(MYSQL_BIND& bind, unsigned long size) { if (bind.buffer_length < size) { log_debug("grow buffer to " << size << " initial " << bind.buffer_length); char* b = new char[size + 1]; if (bind.buffer) { ::memcpy(b, bind.buffer, bind.buffer_length); delete[] static_cast(bind.buffer); } bind.buffer = b; bind.buffer_length = size; } } template int_type getInteger(const MYSQL_BIND& bind) { if (isNull(bind)) throw NullValue(); switch (bind.buffer_type) { case MYSQL_TYPE_TINY: if (bind.is_unsigned) return *static_cast(bind.buffer); else return *static_cast(bind.buffer); case MYSQL_TYPE_SHORT: if (bind.is_unsigned) return *static_cast(bind.buffer); else return *static_cast(bind.buffer); case MYSQL_TYPE_INT24: { unsigned char* ptr = reinterpret_cast(bind.buffer); if (bind.is_unsigned) { #if __BYTE_ORDER == __LITTLE_ENDIAN return (static_cast(ptr[0])) + (static_cast(ptr[1]) << 8) + (static_cast(ptr[2]) << 16); #else return (static_cast(ptr[2])) + (static_cast(ptr[1]) << 8) + (static_cast(ptr[0]) << 16); #endif } else { #if __BYTE_ORDER == __LITTLE_ENDIAN if (ptr[2] < 128) { return static_cast(ptr[0]) + (static_cast(ptr[1]) << 8) + (static_cast(ptr[2]) << 16); } else { int32_t val; unsigned char* vptr = reinterpret_cast(&val); vptr[0] = ptr[0]; vptr[1] = ptr[1]; vptr[2] = ptr[2]; vptr[3] = '\xff'; return static_cast(val); } #else if (ptr[2] < 128) { return (static_cast(ptr[2])) + (static_cast(ptr[1]) << 8) + (static_cast(ptr[0]) << 16); } else { int32_t val; unsigned char* vptr = reinterpret_cast(&val); vptr[0] = '\xff'; vptr[1] = ptr[0]; vptr[2] = ptr[1]; vptr[3] = ptr[2]; return static_cast(val); } #endif } } case MYSQL_TYPE_LONG: if (bind.is_unsigned) return *static_cast(bind.buffer); else return *static_cast(bind.buffer); case MYSQL_TYPE_LONGLONG: if (bind.is_unsigned) return *static_cast(bind.buffer); else return *static_cast(bind.buffer); case MYSQL_TYPE_DECIMAL: case MYSQL_TYPE_NEWDECIMAL: { std::string data(static_cast(bind.buffer), *bind.length); log_debug("extract integer-type from decimal \"" << data << '"'); Decimal decimal(data); return decimal.getInteger(); } case MYSQL_TYPE_VAR_STRING: case MYSQL_TYPE_STRING: { std::string data(static_cast(bind.buffer), *bind.length); log_debug("extract integer-type from string \"" << data << '"'); std::istringstream in(data); int_type ret; in >> ret; if (in.eof() || !in.fail()) return ret; // no break!!! } default: log_error("type-error in getInteger, type=" << bind.buffer_type); throw TypeError("type-error in getInteger"); } } template float_type getFloat(const MYSQL_BIND& bind) { if (isNull(bind)) throw NullValue(); switch (bind.buffer_type) { case MYSQL_TYPE_TINY: case MYSQL_TYPE_SHORT: case MYSQL_TYPE_INT24: case MYSQL_TYPE_LONG: return getInteger(bind); case MYSQL_TYPE_FLOAT: return *static_cast(bind.buffer); case MYSQL_TYPE_DOUBLE: return *static_cast(bind.buffer); case MYSQL_TYPE_DECIMAL: case MYSQL_TYPE_NEWDECIMAL: case MYSQL_TYPE_VAR_STRING: case MYSQL_TYPE_STRING: { std::string data(static_cast(bind.buffer), *bind.length); log_debug("extract float-type from string \"" << data << '"'); std::istringstream in(data); float_type ret; in >> ret; if (in.eof() || !in.fail()) return ret; // no break!!! } default: log_error("type-error in getFloat, type=" << bind.buffer_type); throw TypeError("type-error in getFloat"); } } void setNull(MYSQL_BIND& bind) { release(bind); bind.buffer_type = MYSQL_TYPE_NULL; } void setBool(MYSQL_BIND& bind, bool data) { setValue(bind, static_cast(data), MYSQL_TYPE_SHORT); bind.is_unsigned = 1; } void setShort(MYSQL_BIND& bind, short data) { setValue(bind, data, MYSQL_TYPE_LONG); bind.is_unsigned = 0; } void setInt(MYSQL_BIND& bind, int data) { setValue(bind, data, MYSQL_TYPE_LONG); bind.is_unsigned = 0; } void setLong(MYSQL_BIND& bind, long data) { setValue(bind, data, MYSQL_TYPE_LONG); bind.is_unsigned = 0; } void setUnsignedShort(MYSQL_BIND& bind, unsigned short data) { setValue(bind, data, MYSQL_TYPE_LONG); bind.is_unsigned = 1; } void setUnsigned(MYSQL_BIND& bind, unsigned data) { setValue(bind, data, MYSQL_TYPE_LONG); bind.is_unsigned = 1; } void setUnsignedLong(MYSQL_BIND& bind, unsigned long data) { setValue(bind, data, MYSQL_TYPE_LONG); bind.is_unsigned = 1; } void setInt32(MYSQL_BIND& bind, int32_t data) { setValue(bind, data, MYSQL_TYPE_LONG); bind.is_unsigned = 0; } void setUnsigned32(MYSQL_BIND& bind, uint32_t data) { setValue(bind, data, MYSQL_TYPE_LONG); bind.is_unsigned = 1; } void setInt64(MYSQL_BIND& bind, int64_t data) { setValue(bind, data, MYSQL_TYPE_LONGLONG); bind.is_unsigned = 0; } void setUnsigned64(MYSQL_BIND& bind, uint64_t data) { setValue(bind, data, MYSQL_TYPE_LONGLONG); bind.is_unsigned = 1; } void setDecimal(MYSQL_BIND& bind, unsigned long& length, const Decimal& data) { std::string d = data.toString(); reserve(bind, d.size()); d.copy(static_cast(bind.buffer), d.size()); bind.buffer_type = MYSQL_TYPE_NEWDECIMAL; bind.is_null = 0; length = d.size(); bind.length = &length; bind.is_unsigned = 0; } void setFloat(MYSQL_BIND& bind, float data) { setValue(bind, data, MYSQL_TYPE_FLOAT); } void setDouble(MYSQL_BIND& bind, double data) { setValue(bind, data, MYSQL_TYPE_DOUBLE); } void setChar(MYSQL_BIND& bind, unsigned long& length, char data) { length = 1; reserve(bind, length); *static_cast(bind.buffer) = data; bind.buffer_type = MYSQL_TYPE_VAR_STRING; bind.is_null = 0; bind.length = &length; } void setString(MYSQL_BIND& bind, unsigned long& length, const char* data) { length = ::strlen(data); reserve(bind, length + 1); memcpy(static_cast(bind.buffer), data, length + 1); bind.buffer_type = MYSQL_TYPE_BLOB; bind.is_null = 0; bind.length = &length; } void setBlob(MYSQL_BIND& bind, unsigned long& length, const Blob& data) { length = data.size(); reserve(bind, length); memcpy(static_cast(bind.buffer), data.data(), length); bind.buffer_type = MYSQL_TYPE_VAR_STRING; bind.is_null = 0; bind.length = &length; } void setString(MYSQL_BIND& bind, unsigned long& length, const std::string& data) { reserve(bind, data.size()); data.copy(static_cast(bind.buffer), data.size()); bind.buffer_type = MYSQL_TYPE_VAR_STRING; bind.is_null = 0; length = data.size(); bind.length = &length; } void setDate(MYSQL_BIND& bind, const Date& data) { reserve(bind, sizeof(MYSQL_TIME)); memset(bind.buffer, 0, sizeof(MYSQL_TIME)); MYSQL_TIME* ts = static_cast(bind.buffer); ts->year = data.getYear(); ts->month = data.getMonth(); ts->day = data.getDay(); bind.buffer_type = MYSQL_TYPE_DATE; bind.is_null = 0; bind.length = 0; } void setTime(MYSQL_BIND& bind, const Time& data) { reserve(bind, sizeof(MYSQL_TIME)); memset(bind.buffer, 0, sizeof(MYSQL_TIME)); MYSQL_TIME* ts = static_cast(bind.buffer); ts->hour = data.getHour(); ts->minute = data.getMinute(); ts->second = data.getSecond(); bind.buffer_type = MYSQL_TYPE_TIME; bind.is_null = 0; bind.length = 0; } void setDatetime(MYSQL_BIND& bind, const Datetime& data) { reserve(bind, sizeof(MYSQL_TIME)); memset(bind.buffer, 0, sizeof(MYSQL_TIME)); MYSQL_TIME* ts = static_cast(bind.buffer); ts->year = data.getYear(); ts->month = data.getMonth(); ts->day = data.getDay(); ts->hour = data.getHour(); ts->minute = data.getMinute(); ts->second = data.getSecond(); bind.buffer_type = MYSQL_TYPE_DATETIME; bind.is_null = 0; bind.length = 0; } bool isNull(const MYSQL_BIND& bind) { return bind.buffer_type == MYSQL_TYPE_NULL || (bind.is_null && *bind.is_null); } bool getBool(const MYSQL_BIND& bind) { char ch = getChar(bind); return ch == 't' || ch == 'T' || ch == 'y' || ch == 'Y' || ch == '1'; } short getShort(const MYSQL_BIND& bind) { return getInteger(bind); } int getInt(const MYSQL_BIND& bind) { return getInteger(bind); } long getLong(const MYSQL_BIND& bind) { return getInteger(bind); } unsigned short getUnsignedShort(const MYSQL_BIND& bind) { return getInteger(bind); } unsigned getUnsigned(const MYSQL_BIND& bind) { return getInteger(bind); } unsigned long getUnsignedLong(const MYSQL_BIND& bind) { return getInteger(bind); } int32_t getInt32(const MYSQL_BIND& bind) { return getInteger(bind); } uint32_t getUnsigned32(const MYSQL_BIND& bind) { return getInteger(bind); } int64_t getInt64(const MYSQL_BIND& bind) { return getInteger(bind); } uint64_t getUnsigned64(const MYSQL_BIND& bind) { return getInteger(bind); } Decimal getDecimal(const MYSQL_BIND& bind) { if (isNull(bind)) throw NullValue(); switch (bind.buffer_type) { case MYSQL_TYPE_TINY: case MYSQL_TYPE_SHORT: case MYSQL_TYPE_INT24: case MYSQL_TYPE_LONG: case MYSQL_TYPE_LONGLONG: { int64_t i = getInteger(bind); Decimal d(i, 0); return d; } case MYSQL_TYPE_FLOAT: case MYSQL_TYPE_DOUBLE: { double f = getFloat(bind); Decimal d(f); return d; } case MYSQL_TYPE_DECIMAL: case MYSQL_TYPE_NEWDECIMAL: case MYSQL_TYPE_VAR_STRING: case MYSQL_TYPE_STRING: { std::string data(static_cast(bind.buffer), *bind.length); return Decimal(data); // no break!!! } default: log_error("type-error in getDecimal, type=" << bind.buffer_type); throw TypeError("type-error in getDecimal"); } } float getFloat(const MYSQL_BIND& bind) { return getFloat(bind); } double getDouble(const MYSQL_BIND& bind) { return getFloat(bind); } char getChar(const MYSQL_BIND& bind) { if (isNull(bind)) throw NullValue(); switch (bind.buffer_type) { case MYSQL_TYPE_TINY: if (bind.is_unsigned) return *static_cast(bind.buffer); else return *static_cast(bind.buffer); case MYSQL_TYPE_STRING: case MYSQL_TYPE_VAR_STRING: if (*bind.length > 0) return *static_cast(bind.buffer); // no break! default: log_error("type-error in getChar, type=" << bind.buffer_type); throw TypeError("type-error in getChar"); } } void getString(const MYSQL_BIND& bind, std::string& ret) { if (isNull(bind)) throw NullValue(); switch (bind.buffer_type) { case MYSQL_TYPE_STRING: case MYSQL_TYPE_VAR_STRING: case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_DECIMAL: case MYSQL_TYPE_NEWDECIMAL: ret.assign(static_cast(bind.buffer), *bind.length); break; case MYSQL_TYPE_DATE: { MYSQL_TIME* ts = static_cast(bind.buffer); ret.assign(Date(ts->year, ts->month, ts->day).getIso()); break; } case MYSQL_TYPE_TIME: { MYSQL_TIME* ts = static_cast(bind.buffer); ret.assign(Time(ts->hour, ts->minute, ts->second).getIso()); break; } case MYSQL_TYPE_DATETIME: case MYSQL_TYPE_TIMESTAMP: { MYSQL_TIME* ts = static_cast(bind.buffer); ret.assign(Datetime(ts->year, ts->month, ts->day, ts->hour, ts->minute, ts->second, ts->second_part).getIso()); break; } default: { std::ostringstream s; switch (bind.buffer_type) { case MYSQL_TYPE_TINY: case MYSQL_TYPE_SHORT: case MYSQL_TYPE_INT24: case MYSQL_TYPE_LONG: if (bind.is_unsigned) s << getInteger(bind); else s << getInteger(bind); break; case MYSQL_TYPE_LONGLONG: if (bind.is_unsigned) s << *static_cast(bind.buffer); else s << *static_cast(bind.buffer); break; case MYSQL_TYPE_FLOAT: s << *static_cast(bind.buffer); break; case MYSQL_TYPE_DOUBLE: s << *static_cast(bind.buffer); break; default: log_error("type-error in getString, type=" << bind.buffer_type); throw TypeError("type-error in getString"); } ret.assign(s.str()); } } } void getBlob(const MYSQL_BIND& bind, Blob& ret) { if (isNull(bind)) throw NullValue(); switch (bind.buffer_type) { case MYSQL_TYPE_STRING: case MYSQL_TYPE_VAR_STRING: case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: ret.assign(static_cast(bind.buffer), *bind.length); break; default: log_error("type-error in getBlob, type=" << bind.buffer_type); throw TypeError("type-error in getBlob"); } } Date getDate(const MYSQL_BIND& bind) { if (isNull(bind)) throw NullValue(); switch (bind.buffer_type) { case MYSQL_TYPE_DATE: case MYSQL_TYPE_DATETIME: case MYSQL_TYPE_TIMESTAMP: { MYSQL_TIME* ts = static_cast(bind.buffer); return Date(ts->year, ts->month, ts->day); } default: log_error("type-error in getDate, type=" << bind.buffer_type); throw TypeError("type-error in getDate"); } } Time getTime(const MYSQL_BIND& bind) { if (isNull(bind)) throw NullValue(); switch (bind.buffer_type) { case MYSQL_TYPE_TIME: case MYSQL_TYPE_DATETIME: case MYSQL_TYPE_TIMESTAMP: { MYSQL_TIME* ts = static_cast(bind.buffer); return Time(ts->hour, ts->minute, ts->second); } default: log_error("type-error in getTime, type=" << bind.buffer_type); throw TypeError("type-error in getTime"); } } Datetime getDatetime(const MYSQL_BIND& bind) { if (isNull(bind)) throw NullValue(); switch (bind.buffer_type) { case MYSQL_TYPE_DATE: case MYSQL_TYPE_TIME: case MYSQL_TYPE_DATETIME: case MYSQL_TYPE_TIMESTAMP: { MYSQL_TIME* ts = static_cast(bind.buffer); return Datetime(ts->year, ts->month, ts->day, ts->hour, ts->minute, ts->second); } default: log_error("type-error in getDatetime, type=" << bind.buffer_type); throw TypeError("type-error in getDatetime"); } } void transferValue(MYSQL_BIND& fromValue, MYSQL_BIND& toValue, bool doRelease) { if (doRelease) release(toValue); toValue.buffer = fromValue.buffer; toValue.buffer_type = fromValue.buffer_type; toValue.buffer_length = fromValue.buffer_length; toValue.is_null = fromValue.is_null; toValue.length = fromValue.length; setNull(fromValue); } void copyValue(const MYSQL_BIND& fromValue, MYSQL_BIND& toValue, bool doRelease) { if (doRelease) release(toValue); toValue.buffer = 0; reserveKeep(toValue, fromValue.buffer_length); toValue.buffer_type = fromValue.buffer_type; toValue.buffer_length = fromValue.buffer_length; toValue.is_null = fromValue.is_null; toValue.length = fromValue.length; } void refValue(const MYSQL_BIND& fromValue, MYSQL_BIND& toValue, bool doRelease) { if (doRelease) release(toValue); toValue.buffer = fromValue.buffer; toValue.buffer_type = fromValue.buffer_type; toValue.buffer_length = fromValue.buffer_length; toValue.is_null = fromValue.is_null; toValue.length = fromValue.length; } void releaseValue(MYSQL_BIND& value) { release(value); } } } tntdb-1.4/src/mysql/bindvalues.cpp000066400000000000000000000073501354703061500172760ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include log_define("tntdb.mysql.bindvalues") namespace tntdb { namespace mysql { BindValues::BindValues() : valuesSize(0), values(0), bindAttributes(0) { } BindValues::BindValues(unsigned n) : valuesSize(n), values(new MYSQL_BIND[n]), bindAttributes(new BindAttributes[n]) { ::memset(values, 0, sizeof(MYSQL_BIND) * valuesSize); for (unsigned n = 0; n < valuesSize; ++n) { values[n].length = &bindAttributes[n].length; values[n].is_null = &bindAttributes[n].isNull; } } BindValues::~BindValues() { if (values) for (unsigned n = 0; n < valuesSize; ++n) delete[] static_cast(values[n].buffer); delete[] values; delete[] bindAttributes; } void BindValues::setSize(unsigned n) { if (valuesSize == n) return; if (values) { for (unsigned nn = 0; nn < valuesSize; ++nn) delete[] static_cast(values[nn].buffer); delete[] values; delete[] bindAttributes; } valuesSize = n, values = new MYSQL_BIND[n]; bindAttributes = new BindAttributes[n]; ::memset(values, 0, sizeof(MYSQL_BIND) * valuesSize); for (unsigned n = 0; n < valuesSize; ++n) { values[n].length = &bindAttributes[n].length; values[n].is_null = &bindAttributes[n].isNull; } } void BindValues::initOutBuffer(unsigned n, MYSQL_FIELD& f) { log_debug("initOutBuffer name=" << f.name << " n=" << n << " length=" << f.length << " type=" << f.type << " max_length=" << f.max_length << " flags=" << f.flags << " unsigned=" << bool(f.flags & UNSIGNED_FLAG)); reserve(values[n], std::max(f.length, f.max_length)); if (f.type == 0) log_debug("no type in metadata for field " << n << "; using MYSQL_TYPE_VAR_STRING"); values[n].buffer_type = f.type ? f.type : MYSQL_TYPE_VAR_STRING; values[n].is_unsigned = bool(f.flags & UNSIGNED_FLAG); if (f.name) bindAttributes[n].name = f.name; else bindAttributes[n].name.clear(); } void BindValues::clear() { for (unsigned n = 0; n < valuesSize; ++n) bindAttributes[n].isNull = 1; } } } tntdb-1.4/src/mysql/boundrow.cpp000066400000000000000000000046711354703061500170040ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include namespace tntdb { namespace mysql { BoundRow::size_type BoundRow::size() const { return BindValues::getSize(); } Value BoundRow::getValueByNumber(size_type field_num) const { // TODO eliminate creation of BoundValue, by preallocating them. // We can maintain a vector and prevent dynamic deallocation // of elements by overriding BoundValue::release return Value(new BoundValue(const_cast(static_cast(this)), getMysqlBind()[field_num])); } Value BoundRow::getValueByName(const std::string& field_name) const { size_type field_num; for (field_num = 0; field_num < size(); ++field_num) if (getName(field_num) == field_name) break; if (field_num >= size()) throw FieldNotFound(field_name); return getValueByNumber(field_num); } std::string BoundRow::getColumnName(size_type field_num) const { return getName(field_num); } } } tntdb-1.4/src/mysql/boundvalue.cpp000066400000000000000000000071051354703061500173040ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include namespace tntdb { namespace mysql { bool BoundValue::isNull() const { return mysql::isNull(mysql_bind); } bool BoundValue::getBool() const { return mysql::getBool(mysql_bind); } short BoundValue::getShort() const { return mysql::getShort(mysql_bind); } int BoundValue::getInt() const { return mysql::getInt(mysql_bind); } long BoundValue::getLong() const { return mysql::getInt(mysql_bind); } unsigned short BoundValue::getUnsignedShort() const { return mysql::getUnsignedShort(mysql_bind); } unsigned BoundValue::getUnsigned() const { return mysql::getUnsigned(mysql_bind); } unsigned long BoundValue::getUnsignedLong() const { return mysql::getUnsignedLong(mysql_bind); } int32_t BoundValue::getInt32() const { return mysql::getInt32(mysql_bind); } uint32_t BoundValue::getUnsigned32() const { return mysql::getUnsigned32(mysql_bind); } int64_t BoundValue::getInt64() const { return mysql::getInt64(mysql_bind); } uint64_t BoundValue::getUnsigned64() const { return mysql::getUnsigned64(mysql_bind); } Decimal BoundValue::getDecimal() const { return mysql::getDecimal(mysql_bind); } float BoundValue::getFloat() const { return mysql::getFloat(mysql_bind); } double BoundValue::getDouble() const { return mysql::getDouble(mysql_bind); } char BoundValue::getChar() const { return mysql::getChar(mysql_bind); } void BoundValue::getString(std::string& ret) const { mysql::getString(mysql_bind, ret); } void BoundValue::getBlob(Blob& ret) const { mysql::getBlob(mysql_bind, ret); } Date BoundValue::getDate() const { return mysql::getDate(mysql_bind); } Time BoundValue::getTime() const { return mysql::getTime(mysql_bind); } Datetime BoundValue::getDatetime() const { return mysql::getDatetime(mysql_bind); } } } tntdb-1.4/src/mysql/connection.cpp000066400000000000000000000302021354703061500172710ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include log_define("tntdb.mysql.connection") namespace tntdb { namespace mysql { namespace { std::string str(const char* s) { return s && *s ? std::string("\"") + s + '"' : std::string("null"); } const char* zstr(const char* s) { return s && s[0] ? s : 0; } } void Connection::open(const char* app, const char* host, const char* user, const char* passwd, const char* db, unsigned int port, const char* unix_socket, unsigned long client_flag) { log_debug("mysql_real_connect(MYSQL, " << str(app) << ", " << str(host) << ", " << str(user) << ", " << str(passwd) << ", " << str(db) << ", " << port << ", " << str(unix_socket) << ", " << client_flag << ')'); if (::mysql_init(&mysql) == 0) throw std::runtime_error("cannot initalize mysql"); initialized = true; if (::mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, app && app[0] ? app : "tntdb") != 0) throw MysqlError("mysql_options", &mysql); if (!::mysql_real_connect(&mysql, zstr(host), zstr(user), zstr(passwd), zstr(db), port, zstr(unix_socket), client_flag)) throw MysqlError("mysql_real_connect", &mysql); } Connection::Connection(const char* app, const char* host, const char* user, const char* passwd, const char* db, unsigned int port, const char* unix_socket, unsigned long client_flag) : initialized(false), transactionActive(0) { open(app, host, user, passwd, db, port, unix_socket, client_flag); } Connection::Connection(const std::string& conn, const std::string& username_, const std::string& password_) : initialized(false), transactionActive(0) { log_debug("Connection::Connection(\"" << conn << "\", \"" << username_ << "\", password)"); std::string app; std::string host; std::string user = username_; std::string passwd = password_; std::string db; unsigned int port = 3306; std::string unix_socket; unsigned long client_flag = 0; enum state_type { state_key, state_value, state_value_esc, state_qvalue, state_qvaluee, state_qvalue_esc, state_port, state_flag } state = state_key; std::string key; std::string* value; char quote = '\0'; for (std::string::const_iterator p = conn.begin(); p != conn.end(); ++p) { switch (state) { case state_key: if (*p == '=') { if (key == "port") { port = 0; key.clear(); state = state_port; } else if (key == "flags") { key.clear(); state = state_flag; } else { if (key == "app") value = &app; else if (key == "host") value = &host; else if (key == "user") value = &user; else if (key == "passwd" || key == "password") { log_warn("password set in dburl"); value = &passwd; } else if (key == "db" || key == "dbname" || key == "database") value = &db; else if (key == "unix_socket") value = &unix_socket; else throw std::runtime_error("invalid key \"" + key + "\" in connectionstring \"" + conn + '"'); if (!value->empty()) throw std::runtime_error("value already set for key \"" + key + "\" in connectionstring \"" + conn + '"'); key.clear(); value->clear(); state = state_value; } } else if (key.empty() && std::isspace(*p)) ; else key += *p; break; case state_value: if (*p == ';' || std::isspace(*p)) state = state_key; else if (*p == '\\') state = state_value_esc; else if (value->empty() && (*p == '\'' || *p == '"')) { quote = *p; state = state_qvalue; } else *value += *p; break; case state_value_esc: *value += *p; state = state_value; break; case state_qvalue: if (*p == quote) state = state_key; else if (*p == '\\') state = state_qvalue_esc; else *value += *p; break; case state_qvaluee: if (*p == ';' || std::isspace(*p)) state = state_key; else throw std::runtime_error(std::string("delimiter expected in connectionstring ") + conn); break; case state_qvalue_esc: *value += *p; state = state_qvalue; break; case state_port: if (*p == ';' || std::isspace(*p)) state = state_key; else if (std::isdigit(*p)) port = port * 10 + (*p - '0'); else throw std::runtime_error( std::string("invalid port in connectionstring ") + conn); break; case state_flag: if (*p == ';' || std::isspace(*p)) state = state_key; else if (std::isdigit(*p)) client_flag = client_flag * 10 + (*p - '0'); else throw std::runtime_error( std::string("invalid flag in connectionstring ") + conn); break; } } if (state == state_key && !key.empty()) throw std::runtime_error(std::string("invalid connectionstring ") + conn); open(app.c_str(), host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, unix_socket.c_str(), client_flag); } Connection::~Connection() { if (initialized) { clearStatementCache(); if (!lockTablesQuery.empty()) { log_debug("mysql_query(\"UNLOCK TABLES\")"); if (::mysql_query(&mysql, "UNLOCK TABLES") != 0) log_warn(MysqlError("mysql_query", &mysql).what()); } log_debug("mysql_close(" << &mysql << ')'); ::mysql_close(&mysql); } } void Connection::beginTransaction() { if (transactionActive == 0) { log_debug("mysql_autocomit(" << &mysql << ", " << 0 << ')'); if (::mysql_autocommit(&mysql, 0) != 0) throw MysqlError("mysql_autocommit", &mysql); } ++transactionActive; } void Connection::commitTransaction() { if (transactionActive == 0 || --transactionActive == 0) { log_debug("mysql_commit(" << &mysql << ')'); if (::mysql_commit(&mysql) != 0) throw MysqlError("mysql_commit", &mysql); if (!lockTablesQuery.empty()) { log_debug("mysql_query(\"UNLOCK TABLES\")"); if (::mysql_query(&mysql, "UNLOCK TABLES") != 0) throw MysqlError("mysql_query", &mysql); lockTablesQuery.clear(); } log_debug("mysql_autocomit(" << &mysql << ", " << 1 << ')'); if (::mysql_autocommit(&mysql, 1) != 0) throw MysqlError("mysql_autocommit", &mysql); } } void Connection::rollbackTransaction() { if (transactionActive == 0 || --transactionActive == 0) { log_debug("mysql_rollback(" << &mysql << ')'); if (::mysql_rollback(&mysql) != 0) throw MysqlError("mysql_rollback", &mysql); if (!lockTablesQuery.empty()) { log_debug("mysql_query(\"UNLOCK TABLES\")"); if (::mysql_query(&mysql, "UNLOCK TABLES") != 0) throw MysqlError("mysql_query", &mysql); lockTablesQuery.clear(); } log_debug("mysql_autocommit(" << &mysql << ", " << 1 << ')'); if (::mysql_autocommit(&mysql, 1) != 0) throw MysqlError("mysql_autocommit", &mysql); } } Connection::size_type Connection::execute(const std::string& query) { log_debug("mysql_query(\"" << query << "\")"); if (::mysql_query(&mysql, query.c_str()) != 0) throw MysqlError("mysql_query", &mysql); log_debug("mysql_affected_rows(" << &mysql << ')'); return ::mysql_affected_rows(&mysql); } tntdb::Result Connection::select(const std::string& query) { execute(query); log_debug("mysql_store_result(" << &mysql << ')'); MYSQL_RES* res = ::mysql_store_result(&mysql); if (res == 0) throw MysqlError("mysql_store_result", &mysql); return tntdb::Result(new Result(tntdb::Connection(this), &mysql, res)); } Row Connection::selectRow(const std::string& query) { tntdb::Result result = select(query); if (result.empty()) throw NotFound(); return result.getRow(0); } Value Connection::selectValue(const std::string& query) { Row t = selectRow(query); if (t.empty()) throw NotFound(); return t.getValue(0); } tntdb::Statement Connection::prepare(const std::string& query) { return tntdb::Statement(new Statement(this, &mysql, query)); } tntdb::Statement Connection::prepareWithLimit(const std::string& query, const std::string& limit, const std::string& offset) { std::string q = query; if (!limit.empty()) { q += " limit :"; q += limit; } if (!offset.empty()) { q += " offset :"; q += offset; } return prepare(q); } bool Connection::ping() { int ret = ::mysql_ping(&mysql); log_debug("mysql_ping() => " << ret); return ret == 0; } long Connection::lastInsertId(const std::string& name) { return static_cast(::mysql_insert_id(&mysql)); } void Connection::lockTable(const std::string& tablename, bool exclusive) { if (lockTablesQuery.empty()) lockTablesQuery = "LOCK TABLES "; else lockTablesQuery += ", "; lockTablesQuery += tablename; lockTablesQuery += exclusive ? " WRITE" : " READ"; log_debug("mysql_query(\"" << lockTablesQuery << "\")"); if (::mysql_query(&mysql, lockTablesQuery.c_str()) != 0) throw MysqlError("mysql_query", &mysql); } } } tntdb-1.4/src/mysql/connectionmanager.cpp000066400000000000000000000033621354703061500206330ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include namespace tntdb { namespace mysql { tntdb::Connection ConnectionManager::connect(const std::string& url, const std::string& username, const std::string& password) { return tntdb::Connection(new Connection(url, username, password)); } } } TNTDB_CONNECTIONMANAGER_DEFINE(mysql) tntdb-1.4/src/mysql/cursor.cpp000066400000000000000000000072201354703061500164530ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include log_define("tntdb.mysql.cursor") namespace tntdb { namespace mysql { Cursor::Cursor(Statement* statement, unsigned fetchsize) : row(new BoundRow(statement->getFieldCount())), mysqlStatement(statement), stmt(statement->getStmt()) { MYSQL_FIELD* fields = statement->getFields(); unsigned field_count = row->getSize(); for (unsigned n = 0; n < field_count; ++n) { if (fields[n].length > 0x10000) // do not allocate buffers > 64k - use mysql_stmt_fetch_column instead later fields[n].length = 0x10000; row->initOutBuffer(n, fields[n]); } log_debug("mysql_stmt_bind_result"); if (mysql_stmt_bind_result(stmt, row->getMysqlBind()) != 0) throw MysqlStmtError("mysql_stmt_bind_result", stmt); statement->execute(stmt, fetchsize); } Cursor::~Cursor() { if (stmt) mysqlStatement->putback(stmt); } Row Cursor::fetch() { log_debug("mysql_stmt_fetch(" << stmt << ')'); int ret = mysql_stmt_fetch(stmt); if (ret == MYSQL_DATA_TRUNCATED) { // fetch column data where truncated MYSQL_FIELD* fields = mysqlStatement->getFields(); for (unsigned n = 0; n < row->getSize(); ++n) { if (*row->getMysqlBind()[n].length > row->getMysqlBind()[n].buffer_length) { // actual length was longer than buffer_length, so this column is truncated fields[n].length = *row->getMysqlBind()[n].length; row->initOutBuffer(n, fields[n]); log_debug("mysql_stmt_fetch_column(" << stmt << ", BIND, " << n << ", 0) with " << fields[n].length << " bytes"); if (mysql_stmt_fetch_column(stmt, row->getMysqlBind() + n, n, 0) != 0) throw MysqlStmtError("mysql_stmt_fetch_column", stmt); } } } else if (ret == MYSQL_NO_DATA) { log_debug("MYSQL_NO_DATA"); row = 0; return Row(); } else if (ret == 1) throw MysqlStmtError("mysql_stmt_fetch", stmt); return Row(&*row); } } } tntdb-1.4/src/mysql/cursor_iterator.cpp000066400000000000000000000047361354703061500203750ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include log_define("tntdb.mysql.cursor.iterator") namespace tntdb { namespace mysql { Cursor::const_iterator::const_iterator(const Cursor& cursor_) : cursor(cursor_) { // if not already done // parse hostvars // mysql_stmt_prepare // mysql_stmt_result_metadata // allocate parameter // mysql_stmt_bind_parm // allocate result // mysql_stmt_bind_result // mysql_stmt_execute // fetch first row } Cursor::const_iterator& Cursor::const_iterator::operator++() { // fetch next row log_debug("mysql_stmt_fetch"); int ret = ::mysql_stmt_fetch(getStmt()); if (ret == 1) throw Error("mysql_stmt_fetch", getDb()); else if (ret == MYSQL_NO_DATA) cursor = Cursor(); #ifdef MYSQL_DATA_TRUNCATED else if (ret == MYSQL_DATA_TRUNCATED) { log_error("mysql_stmt_fetch returned MYSQL_DATA_TRUNCATED"); throw std::runtime_error("mysql_stmt_fetch returned MYSQL_DATA_TRUNCATED"); } #endif } } } tntdb-1.4/src/mysql/error.cpp000066400000000000000000000055651354703061500163010ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include namespace tntdb { namespace mysql { namespace { std::string errorMessage(const char* function, MYSQL* mysql) { std::ostringstream msg; msg << "Mysql-Error " << mysql_errno(mysql) << " in " << function << ": " << ::mysql_error(mysql); return msg.str(); } std::string errorMessage(MYSQL* mysql) { std::ostringstream msg; msg << "Mysql-Error " << mysql_errno(mysql) << ": " << ::mysql_error(mysql); return msg.str(); } std::string errorMessage(const char* function, MYSQL_STMT* stmt) { std::ostringstream msg; msg << "Mysql-Error " << mysql_stmt_errno(stmt) << " in " << function << ": " << ::mysql_stmt_error(stmt); return msg.str(); } std::string errorMessage(MYSQL_STMT* stmt) { std::ostringstream msg; msg << "Mysql-Error " << mysql_stmt_errno(stmt) << ": " << ::mysql_stmt_error(stmt); return msg.str(); } } MysqlError::MysqlError(MYSQL* mysql) : Error(errorMessage(mysql)) { } MysqlError::MysqlError(const char* function, MYSQL* mysql) : Error(errorMessage(function, mysql)) { } MysqlStmtError::MysqlStmtError(MYSQL_STMT* stmt) : MysqlError(errorMessage(stmt)) { } MysqlStmtError::MysqlStmtError(const char* function, MYSQL_STMT* stmt) : MysqlError(errorMessage(function, stmt)) { } } } tntdb-1.4/src/mysql/result.cpp000066400000000000000000000052701354703061500164570ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include log_define("tntdb.mysql.result") namespace tntdb { namespace mysql { Result::Result(const tntdb::Connection& c, MYSQL* m, MYSQL_RES* r) : conn(c), mysql(m), result(r) { log_debug("mysql-result " << r); log_debug("mysql_field_count"); field_count = ::mysql_field_count(m); } Result::~Result() { if (result) { log_debug("mysql_free_result(" << result << ')'); ::mysql_free_result(result); } } Row Result::getRow(size_type tup_num) const { log_debug("mysql_data_seek(" << tup_num << ')'); ::mysql_data_seek(result, tup_num); log_debug("mysql_fetch_row"); MYSQL_ROW row = ::mysql_fetch_row(result); if (row == 0) throw MysqlError("mysql_fetch_row", mysql); const IResult* resc = this; IResult* res = const_cast(resc); return Row(new ResultRow(tntdb::Result(res), result, row)); } Result::size_type Result::size() const { log_debug("mysql_num_rows"); return ::mysql_num_rows(result); } Result::size_type Result::getFieldCount() const { return field_count; } } } tntdb-1.4/src/mysql/resultrow.cpp000066400000000000000000000051101354703061500172000ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include log_define("tntdb.mysql.resultrow") namespace tntdb { namespace mysql { ResultRow::ResultRow(const tntdb::Result& result_, MYSQL_RES* res, MYSQL_ROW row_) : result(result_), row(row_) { log_debug("mysql_fetch_lengths"); lengths = ::mysql_fetch_lengths(res); log_debug("mysql_fetch_fields"); fields = ::mysql_fetch_fields(res); } unsigned ResultRow::size() const { return result.getFieldCount(); } Value ResultRow::getValueByNumber(size_type field_num) const { return Value(new RowValue(result, row, field_num, lengths[field_num])); } Value ResultRow::getValueByName(const std::string& field_name) const { size_type field_num; for (field_num = 0; field_num < size(); ++field_num) if (fields[field_num].name == field_name) break; if (field_num >= size()) throw FieldNotFound(field_name); return getValueByNumber(field_num); } std::string ResultRow::getColumnName(size_type field_num) const { return fields[field_num].name; } } } tntdb-1.4/src/mysql/row.cpp000066400000000000000000000035301354703061500157450ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include log_define("tntdb.mysql.row") namespace tntdb { namespace mysql { Row::Row(const Result result_, MYSQL_RES* res, MYSQL_ROW row_) : row(new ResultRow(result_, res, row_)) { } Row::const_iterator Row::begin() const { return const_iterator(*this, 0); } Row::const_iterator Row::end() const { return const_iterator(*this, size()); } } } tntdb-1.4/src/mysql/rowcontainer.cpp000066400000000000000000000034641354703061500176560ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include namespace tntdb { namespace mysql { Row RowContainer::getRow(size_type tup_num) const { IRow* p = &*rows[tup_num]; return Row(p); } RowContainer::size_type RowContainer::size() const { return rows.size(); } RowContainer::size_type RowContainer::getFieldCount() const { return rows.empty() ? 0 : (*rows.begin())->size(); } } } tntdb-1.4/src/mysql/rowvalue.cpp000066400000000000000000000104551354703061500170060ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include namespace tntdb { namespace mysql { bool RowValue::isNull() const { return row[col] == 0; } bool RowValue::getBool() const { return row[col][0] == '1' || row[col][0] == 'y' || row[col][0] == 'Y' || row[col][0] == 't' || row[col][0] == 'T'; } short RowValue::getShort() const { short ret = 0; std::istringstream v(getString()); v >> ret; return ret; } int RowValue::getInt() const { int ret = 0; std::istringstream v(getString()); v >> ret; return ret; } long RowValue::getLong() const { long ret = 0; std::istringstream v(getString()); v >> ret; return ret; } unsigned short RowValue::getUnsignedShort() const { unsigned short ret = 0; std::istringstream v(getString()); v >> ret; return ret; } unsigned RowValue::getUnsigned() const { unsigned ret = 0; std::istringstream v(getString()); v >> ret; return ret; } unsigned long RowValue::getUnsignedLong() const { unsigned long ret = 0; std::istringstream v(getString()); v >> ret; return ret; } int32_t RowValue::getInt32() const { int32_t ret = 0; std::istringstream v(getString()); v >> ret; return ret; } uint32_t RowValue::getUnsigned32() const { uint32_t ret = 0; std::istringstream v(getString()); v >> ret; return ret; } int64_t RowValue::getInt64() const { int64_t ret = 0; std::istringstream v(getString()); v >> ret; return ret; } uint64_t RowValue::getUnsigned64() const { uint64_t ret = 0; std::istringstream v(getString()); v >> ret; return ret; } Decimal RowValue::getDecimal() const { Decimal ret; std::istringstream v(getString()); v >> ret; return ret; } float RowValue::getFloat() const { float ret = 0; std::istringstream v(getString()); v >> ret; return ret; } double RowValue::getDouble() const { double ret = 0; std::istringstream v(getString()); v >> ret; return ret; } char RowValue::getChar() const { return row[col][0]; } void RowValue::getString(std::string& ret) const { ret.assign(row[col], len); } void RowValue::getBlob(Blob& ret) const { ret.assign(row[col], len); } Date RowValue::getDate() const { return Date::fromIso(getString()); } Time RowValue::getTime() const { return Time::fromIso(getString()); } Datetime RowValue::getDatetime() const { return Datetime::fromIso(getString()); } } } tntdb-1.4/src/mysql/statement.cpp000066400000000000000000000513301354703061500171430ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include log_define("tntdb.mysql.statement") namespace tntdb { namespace mysql { typedef std::multimap hostvarMapType; namespace { class SE : public StmtEvent { hostvarMapType& hostvarMap; unsigned idx; static const std::string hostvarInd; public: SE(hostvarMapType& hostvarMap_) : hostvarMap(hostvarMap_), idx(0) { } std::string onHostVar(const std::string& name); unsigned getCount() const { return idx; } }; std::string SE::onHostVar(const std::string& name) { log_debug("hostvar :" << name << ", idx=" << idx); hostvarMap.insert(hostvarMapType::value_type(name, idx++)); return hostvarInd; } const std::string SE::hostvarInd = "?"; } cxxtools::SmartPtr Statement::getRow() { if (rowPtr && rowPtr->refs() == 1) { rowPtr->clear(); return rowPtr; } getFields(); rowPtr = new BoundRow(field_count); for (unsigned n = 0; n < field_count; ++n) { if (fields[n].length > 0x10000) // do not allocate buffers > 64k - use mysql_stmt_fetch_column instead later fields[n].length = 0x10000; rowPtr->initOutBuffer(n, fields[n]); } return rowPtr; } cxxtools::SmartPtr Statement::fetchRow() { cxxtools::SmartPtr ptr = getRow(); log_debug("mysql_stmt_bind_result(" << stmt << ", " << ptr->getMysqlBind() << ')'); if (mysql_stmt_bind_result(stmt, ptr->getMysqlBind()) != 0) throw MysqlStmtError("mysql_stmt_bind_result", stmt); log_debug("mysql_stmt_fetch(" << stmt << ')'); int ret = mysql_stmt_fetch(stmt); if (ret == MYSQL_DATA_TRUNCATED) { // fetch column data where truncated for (unsigned n = 0; n < field_count; ++n) { if (*ptr->getMysqlBind()[n].length > ptr->getMysqlBind()[n].buffer_length) { // actual length was longer than buffer_length, so this column is truncated fields[n].length = *ptr->getMysqlBind()[n].length; ptr->initOutBuffer(n, fields[n]); log_debug("mysql_stmt_fetch_column(" << stmt << ", BIND, " << n << ", 0) with " << fields[n].length << " bytes"); if (mysql_stmt_fetch_column(stmt, ptr->getMysqlBind() + n, n, 0) != 0) throw MysqlStmtError("mysql_stmt_fetch_column", stmt); } } } else if (ret == MYSQL_NO_DATA) ptr = 0; else if (ret == 1) throw MysqlStmtError("mysql_stmt_fetch", stmt); return ptr.getPointer(); } Statement::Statement(Connection* conn_, MYSQL* mysql_, const std::string& query_) : conn(conn_), mysql(mysql_), stmt(0), fields(0), field_count(0) { // parse hostvars StmtParser parser; SE se(hostvarMap); parser.parse(query_, se); log_debug("sql=\"" << parser.getSql() << "\" invars " << se.getCount()); query = parser.getSql(); inVars.setSize(se.getCount()); } Statement::~Statement() { if (stmt) { log_debug("mysql_stmt_close(" << stmt << ')'); ::mysql_stmt_close(stmt); } } void Statement::clear() { log_debug("statement " << stmt << " clear()"); for (hostvarMapType::const_iterator it = hostvarMap.begin(); it != hostvarMap.end(); ++it) inVars.setNull(it->second); } void Statement::setNull(const std::string& col) { log_debug("statement " << stmt << " setNull(\"" << col << "\")"); bool found = false; for (hostvarMapType::const_iterator it = hostvarMap.find(col); it != hostvarMap.end() && it->first == col; ++it) { found = true; inVars.setNull(it->second); } if (!found) log_warn("hostvar \"" << col << "\" not found"); } void Statement::setBool(const std::string& col, bool data) { log_debug("statement " << stmt << " setBool(\"" << col << "\", " << data << ')'); bool found = false; for (hostvarMapType::const_iterator it = hostvarMap.find(col); it != hostvarMap.end() && it->first == col; ++it) { found = true; inVars.setBool(it->second, data); } if (!found) log_warn("hostvar \"" << col << "\" not found"); } void Statement::setShort(const std::string& col, short data) { log_debug("statement " << stmt << " setShort(\"" << col << "\", " << data << ')'); bool found = false; for (hostvarMapType::const_iterator it = hostvarMap.find(col); it != hostvarMap.end() && it->first == col; ++it) { found = true; inVars.setShort(it->second, data); } if (!found) log_warn("hostvar \"" << col << "\" not found"); } void Statement::setInt(const std::string& col, int data) { log_debug("statement " << stmt << " setInt(\"" << col << "\", " << data << ')'); bool found = false; for (hostvarMapType::const_iterator it = hostvarMap.find(col); it != hostvarMap.end() && it->first == col; ++it) { found = true; inVars.setInt(it->second, data); } if (!found) log_warn("hostvar \"" << col << "\" not found"); } void Statement::setLong(const std::string& col, long data) { log_debug("statement " << stmt << " setLong(\"" << col << "\", " << data << ')'); bool found = false; for (hostvarMapType::const_iterator it = hostvarMap.find(col); it != hostvarMap.end() && it->first == col; ++it) { found = true; inVars.setLong(it->second, data); } if (!found) log_warn("hostvar \"" << col << "\" not found"); } void Statement::setUnsignedShort(const std::string& col, unsigned short data) { log_debug("statement " << stmt << " setUnsignedShort(\"" << col << "\", " << data << ')'); bool found = false; for (hostvarMapType::const_iterator it = hostvarMap.find(col); it != hostvarMap.end() && it->first == col; ++it) { found = true; inVars.setUnsignedShort(it->second, data); } if (!found) log_warn("hostvar \"" << col << "\" not found"); } void Statement::setUnsigned(const std::string& col, unsigned data) { log_debug("statement " << stmt << " setUnsigned(\"" << col << "\", " << data << ')'); bool found = false; for (hostvarMapType::const_iterator it = hostvarMap.find(col); it != hostvarMap.end() && it->first == col; ++it) { found = true; inVars.setUnsigned(it->second, data); } if (!found) log_warn("hostvar \"" << col << "\" not found"); } void Statement::setUnsignedLong(const std::string& col, unsigned long data) { log_debug("statement " << stmt << " setUnsignedLong(\"" << col << "\", " << data << ')'); bool found = false; for (hostvarMapType::const_iterator it = hostvarMap.find(col); it != hostvarMap.end() && it->first == col; ++it) { found = true; inVars.setUnsignedLong(it->second, data); } if (!found) log_warn("hostvar \"" << col << "\" not found"); } void Statement::setInt32(const std::string& col, int32_t data) { log_debug("statement " << stmt << " setInt32(\"" << col << "\", " << data << ')'); bool found = false; for (hostvarMapType::const_iterator it = hostvarMap.find(col); it != hostvarMap.end() && it->first == col; ++it) { found = true; inVars.setInt32(it->second, data); } if (!found) log_warn("hostvar \"" << col << "\" not found"); } void Statement::setUnsigned32(const std::string& col, uint32_t data) { log_debug("statement " << stmt << " setUnsigned32(\"" << col << "\", " << data << ')'); bool found = false; for (hostvarMapType::const_iterator it = hostvarMap.find(col); it != hostvarMap.end() && it->first == col; ++it) { found = true; inVars.setUnsigned32(it->second, data); } if (!found) log_warn("hostvar \"" << col << "\" not found"); } void Statement::setInt64(const std::string& col, int64_t data) { log_debug("statement " << stmt << " setInt64(\"" << col << "\", " << data << ')'); bool found = false; for (hostvarMapType::const_iterator it = hostvarMap.find(col); it != hostvarMap.end() && it->first == col; ++it) { found = true; inVars.setInt64(it->second, data); } if (!found) log_warn("hostvar \"" << col << "\" not found"); } void Statement::setUnsigned64(const std::string& col, uint64_t data) { log_debug("statement " << stmt << " setUnsigned64(\"" << col << "\", " << data << ')'); bool found = false; for (hostvarMapType::const_iterator it = hostvarMap.find(col); it != hostvarMap.end() && it->first == col; ++it) { found = true; inVars.setUnsigned64(it->second, data); } if (!found) log_warn("hostvar \"" << col << "\" not found"); } void Statement::setDecimal(const std::string& col, const Decimal& data) { log_debug("statement " << stmt << " setDecimal(\"" << col << "\", " << data << ')'); bool found = false; for (hostvarMapType::const_iterator it = hostvarMap.find(col); it != hostvarMap.end() && it->first == col; ++it) { found = true; inVars.setDecimal(it->second, data); } if (!found) log_warn("hostvar \"" << col << "\" not found"); } void Statement::setFloat(const std::string& col, float data) { log_debug("statement " << stmt << " setFloat(\"" << col << "\", " << data << ')'); bool found = false; for (hostvarMapType::const_iterator it = hostvarMap.find(col); it != hostvarMap.end() && it->first == col; ++it) { found = true; inVars.setFloat(it->second, data); } if (!found) log_warn("hostvar \"" << col << "\" not found"); } void Statement::setDouble(const std::string& col, double data) { log_debug("statement " << stmt << " setDouble(\"" << col << "\", " << data << ')'); bool found = false; for (hostvarMapType::const_iterator it = hostvarMap.find(col); it != hostvarMap.end() && it->first == col; ++it) { found = true; inVars.setDouble(it->second, data); } if (!found) log_warn("hostvar \"" << col << "\" not found"); } void Statement::setChar(const std::string& col, char data) { log_debug("statement " << stmt << " setChar(\"" << col << "\", " << data << ')'); bool found = false; for (hostvarMapType::const_iterator it = hostvarMap.find(col); it != hostvarMap.end() && it->first == col; ++it) { found = true; inVars.setChar(it->second, data); } if (!found) log_warn("hostvar \"" << col << "\" not found"); } void Statement::setString(const std::string& col, const std::string& data) { log_debug("statement " << stmt << " setString(\"" << col << "\", \"" << data << "\")"); bool found = false; for (hostvarMapType::const_iterator it = hostvarMap.find(col); it != hostvarMap.end() && it->first == col; ++it) { found = true; inVars.setString(it->second, data); } if (!found) log_warn("hostvar \"" << col << "\" not found"); } void Statement::setBlob(const std::string& col, const Blob& data) { log_debug("statement " << stmt << " setBlob(\"" << col << "\", data {" << data.size() << "})"); bool found = false; for (hostvarMapType::const_iterator it = hostvarMap.find(col); it != hostvarMap.end() && it->first == col; ++it) { found = true; inVars.setBlob(it->second, data); } if (!found) log_warn("hostvar \"" << col << "\" not found"); } void Statement::setDate(const std::string& col, const Date& data) { log_debug("statement " << stmt << " setDate(\"" << col << "\", " << data.getIso() << ')'); bool found = false; for (hostvarMapType::const_iterator it = hostvarMap.find(col); it != hostvarMap.end() && it->first == col; ++it) { found = true; inVars.setDate(it->second, data); } if (!found) log_warn("hostvar \"" << col << "\" not found"); } void Statement::setTime(const std::string& col, const Time& data) { log_debug("statement " << stmt << " setTime(\"" << col << "\", " << data.getIso() << ')'); bool found = false; for (hostvarMapType::const_iterator it = hostvarMap.find(col); it != hostvarMap.end() && it->first == col; ++it) { found = true; inVars.setTime(it->second, data); } if (!found) log_warn("hostvar \"" << col << "\" not found"); } void Statement::setDatetime(const std::string& col, const Datetime& data) { log_debug("statement " << stmt << " setDatetime(\"" << col << "\", " << data.getIso() << ')'); bool found = false; for (hostvarMapType::const_iterator it = hostvarMap.find(col); it != hostvarMap.end() && it->first == col; ++it) { found = true; inVars.setDatetime(it->second, data); } if (!found) log_warn("hostvar \"" << col << "\" not found"); } Statement::size_type Statement::execute() { log_debug("execute statement " << stmt); if (hostvarMap.empty()) { return conn->execute(query); } else { // use statement-API stmt = getStmt(); execute(stmt, 16); return mysql_stmt_affected_rows(stmt); } } Result Statement::select() { log_debug("select"); if (hostvarMap.empty()) return conn->select(query); if (fields) getRow(); stmt = getStmt(); execute(stmt, 16); if (mysql_stmt_store_result(stmt) != 0) throw MysqlStmtError("mysql_stmt_store_result", stmt); RowContainer* result = new RowContainer(); cxxtools::SmartPtr sresult = result; cxxtools::SmartPtr ptr; while ((ptr = fetchRow()).getPointer() != 0) result->addRow(ptr.getPointer()); return Result(result); } Row Statement::selectRow() { log_debug("selectRow"); if (hostvarMap.empty()) return conn->selectRow(query); if (fields) getRow(); stmt = getStmt(); execute(stmt, 1); if (mysql_stmt_store_result(stmt) != 0) throw MysqlStmtError("mysql_stmt_store_result", stmt); cxxtools::SmartPtr ptr = fetchRow(); if (!ptr) throw NotFound(); return Row(ptr.getPointer()); } Value Statement::selectValue() { log_debug("selectValue"); Row t = selectRow(); if (t.empty()) throw NotFound(); return t.getValue(0); } ICursor* Statement::createCursor(unsigned fetchsize) { return new Cursor(this, fetchsize); } MYSQL_STMT* Statement::getStmt() { MYSQL_STMT* ret; if (stmt) { ret = stmt; stmt = 0; return ret; } // initialize statement log_debug("mysql_stmt_init(" << mysql << ')'); ret = ::mysql_stmt_init(mysql); if (ret == 0) throw MysqlError(mysql); log_debug("mysql_stmt_init(" << mysql << ") => " << ret); log_debug("mysql_stmt_prepare(" << ret << ", \"" << query << "\")"); if (mysql_stmt_prepare(ret, query.data(), query.size()) != 0) { // MysqlStmtError fetches the last error from MYSQL_STMT, so we need // to instantiate this before mysql_stmt_close MysqlStmtError e("mysql_stmt_prepare", ret); log_debug("mysql_stmt_close(" << ret << ')'); ::mysql_stmt_close(ret); throw e; } /* // read always with cursor log_debug("mysql_stmt_attr_set(" << ret << ", STMT_ATTR_CURSOR_TYPE)"); unsigned long cursorType = CURSOR_TYPE_READ_ONLY; if (mysql_stmt_attr_set(ret, STMT_ATTR_CURSOR_TYPE, &cursorType) != 0) { log_debug("error"); MysqlStmtError e("mysql_stmt_attr_set", ret); log_debug("mysql_stmt_close(" << ret << ')'); ::mysql_stmt_close(ret); throw e; } */ // check parametercount log_debug("mysql_stmt_param_count(" << ret << ')'); unsigned param_count = mysql_stmt_param_count(ret); if (param_count != inVars.getSize()) { log_debug("mysql_stmt_close(" << ret << ')'); ::mysql_stmt_close(ret); std::ostringstream msg; msg << "invalid parametercount in query; " << inVars.getSize() << " expected " << param_count << " found by MYSQL"; throw std::runtime_error(msg.str()); } log_debug("statement initialized " << ret); return ret; } void Statement::execute(MYSQL_STMT* stmt, unsigned fetchsize) { // fetch multiple rows at once log_debug("mysql_stmt_attr_set(STMT_ATTR_PREFETCH_ROWS, " << fetchsize << ")"); unsigned long count = fetchsize; if (mysql_stmt_attr_set(stmt, STMT_ATTR_PREFETCH_ROWS, &count) != 0) throw MysqlStmtError("mysql_stmt_attr_set", stmt); // bind parameters log_debug("mysql_stmt_bind_param(" << stmt << ')'); if (mysql_stmt_bind_param(stmt, inVars.getMysqlBind()) != 0) throw MysqlStmtError("mysql_stmt_bind_param", stmt); log_debug("mysql_stmt_execute(" << stmt << ')'); if (mysql_stmt_execute(stmt) != 0) throw MysqlStmtError("mysql_stmt_execute", stmt); } void Statement::putback(MYSQL_STMT* stmt_) { if (stmt) { // we have a statement already - free the offered statement log_debug("mysql_stmt_close(" << stmt_ << ')'); ::mysql_stmt_close(stmt_); } else { // store for reuse stmt = stmt_; } } MYSQL_FIELD* Statement::getFields() { if (fields == 0) { stmt = getStmt(); log_debug("mysql_stmt_result_metadata(" << stmt << ')'); MYSQL_RES* metadata = mysql_stmt_result_metadata(stmt); if (!metadata) throw Error("no metadata avaliable"); log_debug("mysql_stmt_result_metadata(" << stmt << ") => " << metadata); log_debug("mysql_fetch_fields(" << metadata << ')'); fields = mysql_fetch_fields(metadata); log_debug("mysql_num_fields(" << metadata << ')'); field_count = mysql_num_fields(metadata); log_debug("mysql_free_result(" << metadata << ") (metadata)"); ::mysql_free_result(metadata); } return fields; } unsigned Statement::getFieldCount() { getFields(); return field_count; } } } tntdb-1.4/src/oracle/000077500000000000000000000000001354703061500145315ustar00rootroot00000000000000tntdb-1.4/src/oracle/Makefile.am000066400000000000000000000011711354703061500165650ustar00rootroot00000000000000AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include sources = \ blob.cpp \ connection.cpp \ connectionmanager.cpp \ cursor.cpp \ datetime.cpp \ error.cpp \ multirow.cpp \ multivalue.cpp \ number.cpp \ result.cpp \ row.cpp \ singlerow.cpp \ singlevalue.cpp \ statement.cpp \ string.cpp \ value.cpp if MAKE_ORACLE driver_LTLIBRARIES = tntdb@abi_current@-oracle.la tntdb@abi_current@_oracle_la_SOURCES = $(sources) tntdb@abi_current@_oracle_la_LDFLAGS = -module -version-info @sonumber@ @SHARED_LIB_FLAG@ tntdb@abi_current@_oracle_la_LIBADD = $(top_builddir)/src/libtntdb.la @ORACLE_OCI_LDFLAGS@ endif tntdb-1.4/src/oracle/blob.cpp000066400000000000000000000100451354703061500161530ustar00rootroot00000000000000/* * Copyright (C) 2008 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include log_define("tntdb.oracle.blob") namespace tntdb { namespace oracle { // oci-wrappers void Blob::ociDescriptorAlloc() { log_debug("OCIDescriptorAlloc(OCI_DTYPE_LOB)"); sword ret = OCIDescriptorAlloc(conn->getEnvHandle(), reinterpret_cast(&lob), OCI_DTYPE_LOB, 0, 0); conn->checkError(ret, "OCIDescriptorAlloc(OCI_DTYPE_LOB)"); } void Blob::ociDescriptorFree() { log_debug("OCIDescriptorFree(" << lob << ", OCI_DTYPE_LOB)"); OCIDescriptorFree(lob, OCI_DTYPE_LOB); } // ctors, dtors, ... // Blob::Blob(Connection* conn_, OCILobLocator* lob_, bool release_) : conn(conn_), lob(lob_), release(release_) { } Blob::Blob(Connection* conn_, const char* data, ub4 count) : conn(conn_), lob(0), release(true) { log_debug("create oracle::Blob from data; size=" << count); ociDescriptorAlloc(); log_debug("OCILobWrite"); sword ret = OCILobWrite(conn->getSvcCtxHandle(), conn->getErrorHandle(), lob, &count, 0, const_cast(data), count, OCI_ONE_PIECE, 0, 0, 0, 0); conn->checkError(ret, "OCILobWrite"); } void Blob::setData(Connection* conn_, const char* data, ub4 count) { conn = conn_; if (lob == 0) ociDescriptorAlloc(); log_debug("OCILobWrite"); sword ret = OCILobWrite(conn->getSvcCtxHandle(), conn->getErrorHandle(), lob, &count, 0, const_cast(data), count, OCI_ONE_PIECE, 0, 0, 0, 0); conn->checkError(ret, "OCILobWrite"); } void Blob::getData(tntdb::Blob& blob) const { log_debug("OCILobGetLength"); ub4 len; sword ret = OCILobGetLength(conn->getSvcCtxHandle(), conn->getErrorHandle(), lob, &len); conn->checkError(ret, "OCILobGetLength"); log_debug("len=" << len); log_debug("OCILobOpen"); ret = OCILobOpen(conn->getSvcCtxHandle(), conn->getErrorHandle(), lob, OCI_LOB_READONLY); conn->checkError(ret, "OCILobOpen"); char* buffer = blob.reserve(len, true); memset(buffer, '\0', len); ub4 amt = len; log_debug("OCILobRead"); ret = OCILobRead(conn->getSvcCtxHandle(), conn->getErrorHandle(), lob, &amt, 1, buffer, len, 0, 0, 0, SQLCS_IMPLICIT); conn->checkError(ret, "OCILobRead"); log_debug("OCILobClose"); ret = OCILobClose(conn->getSvcCtxHandle(), conn->getErrorHandle(), lob); conn->checkError(ret, "OCILobClose"); } OCILobLocator*& Blob::getHandle(Connection* conn_) { conn = conn_; if (lob == 0) ociDescriptorAlloc(); return lob; } } } tntdb-1.4/src/oracle/connection.cpp000066400000000000000000000320101354703061500173700ustar00rootroot00000000000000/* * Copyright (C) 2007 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include log_define("tntdb.oracle.connection") #ifndef HAVE_SIGHANDLER_T typedef void (*sighandler_t)(int); #endif namespace tntdb { namespace oracle { namespace error { log_define("tntdb.oracle.error") void checkError(OCIError* errhp, sword ret, const char* function) { switch (ret) { case OCI_SUCCESS: break; case OCI_SUCCESS_WITH_INFO: log_warn(function << ": OCI_SUCCESS_WITH_INFO"); break; case OCI_NEED_DATA: log_warn(function << ": OCI_NEED_DATA"); throw Error(errhp, function); case OCI_NO_DATA: log_debug(function << ": OCI_NO_DATA"); throw NotFound(); case OCI_ERROR: throw Error(errhp, function); case OCI_INVALID_HANDLE: log_error("OCI_INVALID_HANDLE"); throw InvalidHandle(function); case OCI_STILL_EXECUTING: log_error("OCI_STILL_EXECUTING"); throw StillExecuting(function); case OCI_CONTINUE: log_error("OCI_CONTINUE"); throw ErrorContinue(function); } } } void Connection::checkError(sword ret, const char* function) const { error::checkError(getErrorHandle(), ret, function); } namespace { class SighandlerSaver { int signum; sighandler_t sighandler; public: explicit SighandlerSaver(int signum_) : signum(signum_) { sighandler = signal(signum, SIG_DFL); } ~SighandlerSaver() { signal(signum, sighandler); } }; } void Connection::logon(const std::string& dblink, const std::string& user, const std::string& password) { log_debug("logon \"" << dblink << "\" user=\"" << user << '"'); // workaround for OCI problem: OCI redirects SIGINT, which causes Ctrl-C to fail SighandlerSaver sighandlerSaver(SIGINT); pid = ::getpid(); sword ret; log_finer("create oracle environment"); ret = OCIEnvCreate(&envhp, OCI_OBJECT|OCI_THREADED|OCI_NO_MUTEX, 0, 0, 0, 0, 0, 0); if (ret != OCI_SUCCESS) throw Error("cannot create environment handle"); log_finer("environment handle => " << envhp); log_finer("allocate error handle"); ret = OCIHandleAlloc(envhp, (void**)&errhp, OCI_HTYPE_ERROR, 0, 0); if (ret != OCI_SUCCESS) throw Error("cannot create error handle"); log_finer("error handle => " << errhp); log_finer("allocate server handle"); ret = OCIHandleAlloc(envhp, (void**)&srvhp, OCI_HTYPE_SERVER, 0, 0); checkError(ret, "OCIHandleAlloc(OCI_HTYPE_SERVER)"); log_finer("server handle => " << srvhp); log_finer("allocate service handle"); ret = OCIHandleAlloc(envhp, (void**)&svchp, OCI_HTYPE_SVCCTX, 0, 0); checkError(ret, "OCIHandleAlloc(OCI_HTYPE_SVCCTX)"); log_finer("service handle => " << svchp); log_finer("attach to server"); ret = OCIServerAttach(srvhp, errhp, reinterpret_cast(dblink.data()), dblink.size(), 0); checkError(ret, "OCIServerAttach"); /* set attribute server context in the service context */ ret = OCIAttrSet(svchp, OCI_HTYPE_SVCCTX, srvhp, 0, OCI_ATTR_SERVER, errhp); checkError(ret, "OCIAttrSet(OCI_ATTR_SERVER)"); log_finer("allocate session handle"); ret = OCIHandleAlloc((dvoid*)envhp, (dvoid**)&usrhp, OCI_HTYPE_SESSION, 0, (dvoid**)0); checkError(ret, "OCIHandleAlloc(OCI_HTYPE_SESSION)"); /* set username attribute in user session handle */ log_finer("set username attribute in session handle"); ret = OCIAttrSet(usrhp, OCI_HTYPE_SESSION, reinterpret_cast(const_cast(user.data())), user.size(), OCI_ATTR_USERNAME, errhp); checkError(ret, "OCIAttrSet(OCI_ATTR_USERNAME)"); /* set password attribute in user session handle */ ret = OCIAttrSet(usrhp, OCI_HTYPE_SESSION, reinterpret_cast(const_cast(password.data())), password.size(), OCI_ATTR_PASSWORD, errhp); checkError(ret, "OCIAttrSet(OCI_ATTR_PASSWORD)"); /* start session */ log_finer("start session"); ret = OCISessionBegin(svchp, errhp, usrhp, OCI_CRED_RDBMS, OCI_DEFAULT); checkError(ret, "OCISessionBegin"); /* set user session attrubte in the service context handle */ ret = OCIAttrSet(svchp, OCI_HTYPE_SVCCTX, usrhp, 0, OCI_ATTR_SESSION, errhp); checkError(ret, "OCIAttrSet(OCI_ATTR_SESSION)"); } namespace { std::string extractAttribute(std::string& value, const std::string& key) { std::string::size_type p0 = value.find(key); if (p0 == std::string::npos) return std::string(); if (p0 > 0 && value.at(p0 - 1) != ';') return std::string(); std::string::size_type p1 = value.find(';', p0); if (p1 == std::string::npos) p1 = value.size(); std::string::size_type n = p1 - p0; std::string ret(value, p0 + key.size(), n - key.size()); if (p0 > 0) value.erase(p0 - 1, n + 1); else value.erase(p0, n); return ret; } } Connection::Connection(const std::string& url, const std::string& username, const std::string& password) : envhp(0), srvhp(0), errhp(0), usrhp(0), svchp(0), transactionActive(0) { std::string conninfo(url); std::string au = extractAttribute(conninfo, "user="); std::string ap = extractAttribute(conninfo, "passwd="); log_warn_if(!ap.empty(), "password should not be given in dburl"); log_warn_if(!au.empty() && !username.empty(), "username given in url and parameter"); log_warn_if(!ap.empty() && !password.empty(), "password given in url and parameter"); if (au.empty() && ap.empty()) logon(conninfo, username, password); else logon(conninfo, au, ap); } Connection::~Connection() { if (envhp) { sword ret; clearStatementCache(); try { log_finer("OCISessionEnd"); ret = OCISessionEnd(svchp, errhp, usrhp, OCI_DEFAULT); checkError(ret, "OCISessionEnd"); } catch (const std::exception& e) { log_error(e.what()); } try { log_finer("OCIServerDetach"); ret = OCIServerDetach(srvhp, errhp, OCI_DEFAULT); checkError(ret, "OCIServerDetach"); } catch (const std::exception& e) { log_error(e.what()); } log_finer("OCIHandleFree(" << envhp << ')'); ret = OCIHandleFree(envhp, OCI_HTYPE_ENV); if (ret == OCI_SUCCESS) log_finer("handle released"); else log_error("OCIHandleFree failed"); } } void Connection::beginTransaction() { //log_debug("OCITransStart(" << svchp << ", " << errhp << ')'); //checkError(OCITransStart(svchp, errhp, 10, OCI_TRANS_NEW), "OCITransStart"); ++transactionActive; } void Connection::commitTransaction() { if (transactionActive == 0 || --transactionActive == 0) { log_debug("OCITransCommit(" << srvhp << ", " << errhp << ')'); checkError(OCITransCommit(svchp, errhp, OCI_DEFAULT), "OCITransCommit"); } } void Connection::rollbackTransaction() { if (transactionActive == 0 || --transactionActive == 0) { log_debug("OCITransRollback(" << srvhp << ", " << errhp << ')'); checkError(OCITransRollback(svchp, errhp, OCI_DEFAULT), "OCITransRollback"); } } Connection::size_type Connection::execute(const std::string& query) { return prepare(query).execute(); } tntdb::Result Connection::select(const std::string& query) { return prepare(query).select(); } Row Connection::selectRow(const std::string& query) { return prepare(query).selectRow(); } Value Connection::selectValue(const std::string& query) { return prepare(query).selectValue(); } tntdb::Statement Connection::prepare(const std::string& query) { return tntdb::Statement(new Statement(this, query)); } tntdb::Statement Connection::prepareWithLimit(const std::string& query, const std::string& limit, const std::string& offset) { std::string q; if (limit.empty()) { if (offset.empty()) { q = query; } else { // no limit, just offset q = "select * from (select a.*, rownum tntdbrownum from("; q += query; q += ")a) where tntdbrownum > :"; q += offset; } } else if (offset.empty()) { // just limit, no offset q = "select * from (select a.*, rownum tntdbrownum from("; q += query; q += ")a) where tntdbrownum <= :"; q += limit; } else { // limit and offset set q = "select * from (select a.*, rownum tntdbrownum from("; q += query; q += ")a) where tntdbrownum > :"; q += offset; q += " and tntdbrownum <= :"; q += offset; q += " + :"; q += limit; } return prepare(q); } void Connection::clearStatementCache() { IStmtCacheConnection::clearStatementCache(); seqStmt.clear(); } bool Connection::ping() { try { if (pid != getpid()) { // database connection is not valid any more after a fork log_warn("pid has changed; current pid=" << getpid() << " connection pid=" << pid << ", release environment handle"); clearStatementCache(); seqStmt.clear(); sword ret = OCIHandleFree(envhp, OCI_HTYPE_ENV); if (ret != OCI_SUCCESS) log_error("OCIHandleFree(" << envhp << " OCI_HTYPE_ENV) failed"); envhp = 0; return false; } // OCIPing crashed on oracle 10.2.0.4.0 #if OCI_MAJOR_VERSION >= 11 checkError(OCIPing(svchp, errhp, OCI_DEFAULT), "OCIPing"); #else char version[64]; checkError(OCIServerVersion(svchp, errhp, reinterpret_cast(version), sizeof(version), OCI_HTYPE_SVCCTX)); log_debug("oracle version " << version); #endif return true; } catch (const Error&) { return false; } } long Connection::lastInsertId(const std::string& name) { tntdb::Statement stmt; SeqStmtType::iterator s = seqStmt.find(name); if (s == seqStmt.end()) { // check for valid sequence name for (std::string::const_iterator it = name.begin(); it != name.end(); ++it) if (! ((*it >= 'a' && *it <= 'z') || (*it >= 'A' && *it <= 'Z') || (*it >= '0' && *it <= '9') || *it == '_')) throw Error("invalid sequence name \"" + name + '"'); stmt = prepare( "select " + name + ".currval from dual"); seqStmt[name] = stmt; } else stmt = s->second; long ret; stmt.selectValue().get(ret); return ret; } void Connection::lockTable(const std::string& tablename, bool exclusive) { std::string sql = "LOCK TABLE "; sql += tablename; sql += exclusive ? " IN EXCLUSIVE MODE" : " IN SHARE MODE"; execute(sql); } } } tntdb-1.4/src/oracle/connectionmanager.cpp000066400000000000000000000034641354703061500207360ustar00rootroot00000000000000/* * Copyright (C) 2007 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include log_define("tntdb.oracle.connectionmanager") namespace tntdb { namespace oracle { tntdb::Connection ConnectionManager::connect(const std::string& url, const std::string& username, const std::string& password) { return tntdb::Connection(new Connection(url, username, password)); } } } TNTDB_CONNECTIONMANAGER_DEFINE(oracle) tntdb-1.4/src/oracle/cursor.cpp000066400000000000000000000074311354703061500165570ustar00rootroot00000000000000/* * Copyright (C) 2007 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include log_define("tntdb.oracle.cursor") namespace tntdb { namespace oracle { Cursor::Cursor(Statement* stmt_, unsigned fetchsize_) : stmt(stmt_), fetchsize(fetchsize_), srow(0), rowcount(0) { log_debug("execute statement " << stmt->getHandle()); sword ret = OCIStmtExecute(stmt->getConnection()->getSvcCtxHandle(), stmt->getHandle(), stmt->getErrorHandle(), 0, 0, 0, 0, OCI_DEFAULT); stmt->checkError(ret, "OCIStmtExecute"); MultiRow::Ptr mr = new MultiRow(stmt.getPointer(), fetchsize); srow = new SingleRow(mr, 0); row = tntdb::Row(srow); stmtp = stmt->getHandle(); stmt->stmtp = 0; } Cursor::~Cursor() { if (stmtp) { if (stmt->stmtp) { log_debug("release statement handle " << stmtp); sword ret = OCIHandleFree(stmtp, OCI_HTYPE_STMT); if (ret != OCI_SUCCESS) log_error("OCIHandleFree(" << stmtp << " OCI_HTYPE_STMT) failed"); } else { stmt->stmtp = stmtp; } } } tntdb::Row Cursor::fetch() { if (rowcount > 0 && srow->row() < rowcount - 1) { log_finer("increase row counter to " << (srow->row() + 1)); srow->row(srow->row()+1); } else if (rowcount > 0 && rowcount < fetchsize) { log_finer("last fetch returned " << rowcount << " rows but " << fetchsize << " was expected - finish cursor"); row = tntdb::Row(); srow = 0; } else if (rowcount == 0 || rowcount >= srow->row()) { log_debug("OCIStmtFetch(" << stmtp << ')'); sword ret = OCIStmtFetch(stmtp, stmt->getErrorHandle(), fetchsize, OCI_FETCH_NEXT, OCI_DEFAULT); if (ret != OCI_NO_DATA && ret != OCI_SUCCESS) stmt->checkError(ret, "OCIStmtFetch"); // get number of rows fetched ret = OCIAttrGet(stmtp, OCI_HTYPE_STMT, &rowcount, 0, OCI_ATTR_ROWS_FETCHED, stmt->getErrorHandle()); stmt->checkError(ret, "OCIAttrGet(OCI_ATTR_ROWS_FETCHED)"); log_debug(rowcount << " rows fetched"); if (rowcount == 0) { row = tntdb::Row(); srow = 0; } else { srow->row(0); } } return row; } } } tntdb-1.4/src/oracle/datetime.cpp000066400000000000000000000167361354703061500170460ustar00rootroot00000000000000/* * Copyright (C) 2007 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include log_define("tntdb.oracle.datetime") namespace tntdb { namespace oracle { // oci-wrappers void Datetime::ociDescriptorAlloc() { log_debug("OCIDescriptorAlloc(OCI_DTYPE_TIMESTAMP)"); sword ret = OCIDescriptorAlloc(conn->getEnvHandle(), reinterpret_cast(&datetime), OCI_DTYPE_TIMESTAMP, 0, 0); conn->checkError(ret, "OCIDescriptorAlloc(OCI_DTYPE_TIMESTAMP)"); } void Datetime::ociDescriptorFree() { log_debug("OCIDescriptorFree(" << datetime << ", OCI_DTYPE_TIMESTAMP)"); OCIDescriptorFree(datetime, OCI_DTYPE_TIMESTAMP); } void Datetime::ociConstruct(sb2 year, ub1 month, ub1 day, ub1 hour, ub1 min, ub1 sec, ub4 fsec) { log_debug("OCIDateTimeConstruct(" << conn->getEnvHandle() << ')'); sword ret = OCIDateTimeConstruct(conn->getEnvHandle(), conn->getErrorHandle(), datetime, year, month, day, hour, min, sec, fsec * 1000000, 0, 0); conn->checkError(ret, "OCIDateTimeConstruct"); } void Datetime::ociAssign(OCIDateTime* src) { log_debug("OCIDateTimeAssign"); sword ret = OCIDateTimeAssign(conn->getEnvHandle(), conn->getErrorHandle(), src, datetime); conn->checkError(ret, "OCIDateTimeAssign"); } void Datetime::ociGetDate(sb2 &year, ub1 &month, ub1 &day) const { log_debug("OCIDateTimeGetDate(" << datetime << ')'); sword ret = OCIDateTimeGetDate(conn->getEnvHandle(), conn->getErrorHandle(), datetime, &year, &month, &day); conn->checkError(ret, "OCIDateTimeGetDate"); } void Datetime::ociGetTime(ub1 &hour, ub1 &min, ub1 &sec, ub4 &fsec) const { log_debug("OCIDateTimeGetTime(" << datetime << ')'); sword ret = OCIDateTimeGetTime(conn->getEnvHandle(), conn->getErrorHandle(), datetime, &hour, &min, &sec, &fsec); conn->checkError(ret, "OCIDateTimeGetTime"); } // ctors, dtors, ... // Datetime::Datetime(Connection* conn_, OCIDateTime* datetime_, bool release_) : conn(conn_), datetime(datetime_), release(release_) { } Datetime::Datetime(Connection* conn_, const tntdb::Datetime& s) : conn(conn_), datetime(0), release(true) { log_debug("create oracle::Datetime from tntdb::Datetime"); ociDescriptorAlloc(); ociConstruct(s.getYear(), s.getMonth(), s.getDay(), s.getHour(), s.getMinute(), s.getSecond(), s.getMillis()); } Datetime::Datetime(Connection* conn_, const tntdb::Date& s) : conn(conn_), datetime(0), release(true) { log_debug("create oracle::Datetime from tntdb::Date"); ociDescriptorAlloc(); ociConstruct(s.getYear(), s.getMonth(), s.getDay(), 0, 0, 0, 0); } Datetime::Datetime(Connection* conn_, const tntdb::Time& s) : conn(conn_), datetime(0), release(true) { log_debug("create oracle::Datetime from tntdb::Time"); ociDescriptorAlloc(); ociConstruct(1, 1, 1, s.getHour(), s.getMinute(), s.getSecond(), s.getMillis()); } Datetime::Datetime(const Datetime& src) : conn(src.conn), datetime(0), release(true) { log_debug("copy oracle::Datetime"); if (src.datetime) { ociDescriptorAlloc(); ociAssign(src.datetime); } } Datetime& Datetime::operator= (const Datetime& src) { log_debug("assign oracle::Datetime"); conn = src.conn; if (src.datetime) { if (datetime == 0 || !release) { // we have no handle or don't own it - create new one log_debug("allocate new descriptor"); ociDescriptorAlloc(); release = true; } ociAssign(src.datetime); } else if (datetime) { if (release) { // free log_debug("release old descriptor"); ociDescriptorFree(); } datetime = 0; } return *this; } void Datetime::assign(Connection* conn_, const tntdb::Datetime& s) { log_debug("assign tntdb::Datetime"); conn = conn_; if (datetime == 0 || !release) { // we have no handle or don't own it - create new one log_debug("allocate new descriptor"); ociDescriptorAlloc(); release = true; } ociConstruct(s.getYear(), s.getMonth(), s.getDay(), s.getHour(), s.getMinute(), s.getSecond(), s.getMillis()); } void Datetime::assign(Connection* conn_, const tntdb::Date& s) { log_debug("assign tntdb::Date"); conn = conn_; if (datetime == 0 || !release) { // we have no handle or don't own it - create new one log_debug("allocate new descriptor"); ociDescriptorAlloc(); release = true; } ociConstruct(s.getYear(), s.getMonth(), s.getDay(), 0, 0, 0, 0); } void Datetime::assign(Connection* conn_, const tntdb::Time& s) { log_debug("assign tntdb::Time"); conn = conn_; if (datetime == 0 || !release) { // we have no handle or don't own it - create new one log_debug("allocate new descriptor"); ociDescriptorAlloc(); release = true; } ociConstruct(1, 1, 1, s.getHour(), s.getMinute(), s.getSecond(), s.getMillis()); } // getters OCIDateTime*& Datetime::getReference(Connection* conn_) { if (datetime == 0) { conn = conn_; release = true; ociDescriptorAlloc(); } return datetime; } tntdb::Date Datetime::getDate() const { sb2 year; ub1 month, day; ociGetDate(year, month, day); return tntdb::Date(year, month, day); } tntdb::Datetime Datetime::getDatetime() const { sb2 year; ub1 month, day, hour, min, sec; ub4 fsec; ociGetDate(year, month, day); ociGetTime(hour, min, sec, fsec); return tntdb::Datetime(year, month, day, hour, min, sec, fsec / 1000000); } tntdb::Time Datetime::getTime() const { ub1 hour, min, sec; ub4 fsec; ociGetTime(hour, min, sec, fsec); return tntdb::Time(hour, min, sec, fsec / 1000000); } } } tntdb-1.4/src/oracle/error.cpp000066400000000000000000000047411354703061500163740ustar00rootroot00000000000000/* * Copyright (C) 2007 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include log_define("tntdb.oracle.error") namespace tntdb { namespace oracle { namespace { std::string errorMessage(OCIError* errhp, const char* function = 0) { int errcode; char errbuf[512]; OCIErrorGet((dvoid*)errhp, (ub4)1, (text*)NULL, &errcode, (unsigned char*)errbuf, (ub4)sizeof(errbuf), OCI_HTYPE_ERROR); std::ostringstream msg; msg << "oracle error " << errcode; if (function) msg << " in " << function; msg << ": " << errbuf; return msg.str(); } std::string errorMessage(const std::string& str, const char* function = 0) { std::string msg = str; if (function) { msg += " in function "; msg += function; } return msg; } } Error::Error(OCIError* errhp, const char* function) : tntdb::Error(errorMessage(errhp, function)) { } Error::Error(const std::string& msg, const char* function) : tntdb::Error(errorMessage(msg, function)) { } } } tntdb-1.4/src/oracle/multirow.cpp000066400000000000000000000066031354703061500171240ustar00rootroot00000000000000/* * Copyright (C) 2012 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include log_define("tntdb.oracle.multirow") namespace tntdb { namespace oracle { MultiRow::MultiRow(Statement* stmt, unsigned rowcount) { ub4 columncount; sword ret = OCIAttrGet(stmt->getHandle(), OCI_HTYPE_STMT, &columncount, 0, OCI_ATTR_PARAM_COUNT, stmt->getErrorHandle()); stmt->checkError(ret, "OCIAttrGet(OCI_ATTR_PARAM_COUNT)"); log_debug("define " << columncount << " parameters"); _columns.resize(columncount); for (ub4 pos = 0; pos < columncount; ++pos) _columns[pos] = new MultiValue(stmt, pos, rowcount); } MultiRow::MultiRow(Statement* stmt, unsigned rowcount, unsigned columncount) { log_debug("define " << columncount << " parameters"); _columns.resize(columncount); for (ub4 pos = 0; pos < columncount; ++pos) _columns[pos] = new MultiValue(stmt, pos, rowcount); } MultiValue::Ptr MultiRow::getValuesByNumber(unsigned field_num) const { log_debug("getValuesByNumber(" << field_num << ')'); return _columns.at(field_num); } MultiValue::Ptr MultiRow::getValuesByName(const std::string& field_name) const { log_debug("getValuesByName(" << field_name << ')'); return getValuesByNumber(getColIndexByName(field_name)); } MultiRow::Columns::size_type MultiRow::getColIndexByName(const std::string& field_name) const { std::string field_name_upper; field_name_upper.reserve(field_name.size()); for (std::string::const_iterator it = field_name.begin(); it != field_name.end(); ++it) field_name_upper += std::toupper(*it); Columns::size_type i; for (i = 0; i < _columns.size(); ++i) if (_columns[i]->getColumnName() == field_name_upper) break; if (i == _columns.size()) throw FieldNotFound(field_name); return i; } std::string MultiRow::getColumnName(unsigned field_num) const { return _columns.at(field_num)->getColumnName(); } } } tntdb-1.4/src/oracle/multivalue.cpp000066400000000000000000000617271354703061500174410ustar00rootroot00000000000000/* * Copyright (C) 2012 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include log_define("tntdb.oracle.multivalue") namespace tntdb { namespace oracle { namespace { template T getValue(const std::string& s, const char* tname) { std::istringstream in(s); T ret; in >> ret; if (!in) { std::ostringstream msg; msg << "can't convert \"" << s << "\" to " << tname; throw TypeError(msg.str()); } return ret; } template T getValueFloat(I from, I to, const char* tname) { // This is a stupid workaround for converting decimal comma into decimal point // It should be actually done in OCI std::string o; o.reserve(to - from); std::replace_copy(from, to, std::back_inserter(o), ',', '.'); return getValue(o, tname); } template std::string toString(T v) { std::ostringstream ret; ret << v; return ret.str(); } template <> std::string toString(float v) { std::ostringstream ret; ret.precision(24); ret << v; return ret.str(); } template <> std::string toString(double v) { std::ostringstream ret; ret.precision(24); ret << v; return ret.str(); } template <> std::string toString(Decimal v) { std::ostringstream ret; ret.precision(24); ret << v; return ret.str(); } template IntType round(double d) { if (d > std::numeric_limits::max() + .5 || d < std::numeric_limits::min() - .5) { log_warn("overflow when trying to read integer from float " << d); throw std::overflow_error("overflow when trying to read integer from float"); } return static_cast(d >= 0 ? d + .5 : d - .5); } } MultiValue::MultiValue(Statement* stmt, ub4 pos, unsigned n) : _defp(0), _conn(stmt->getConnection()), _type(0), _len(0), _nullind(0), _n(n), _data(0) { sword ret; /* get parameter-info */ OCIParam* paramp = 0; log_debug("OCIParamGet(" << static_cast(stmt->getHandle()) << ')'); ret = OCIParamGet(stmt->getHandle(), OCI_HTYPE_STMT, stmt->getErrorHandle(), reinterpret_cast(¶mp), pos + 1); stmt->checkError(ret, "OCIParamGet"); init(stmt, paramp, pos); OCIDescriptorFree(paramp, OCI_DTYPE_PARAM); } MultiValue::MultiValue(Statement* stmt, OCIParam* paramp, ub4 pos, unsigned n) : _defp(0), _conn(stmt->getConnection()), _type(0), _len(0), _nullind(0), _n(n), _data(0) { init(stmt, paramp, pos); } void MultiValue::init(Statement* stmt, OCIParam* paramp, ub4 pos) { sword ret; _len = new ub2[_n]; _nullind = new ub2[_n]; /* retrieve column name */ ub4 col_name_len = 0; text* col_name = 0; ret = OCIAttrGet(paramp, OCI_DTYPE_PARAM, &col_name, &col_name_len, OCI_ATTR_NAME, stmt->getErrorHandle()); stmt->checkError(ret, "OCIAttrGet(OCI_ATTR_NAME)"); _colName.assign(reinterpret_cast(col_name), col_name_len); /* retrieve the data type attribute */ ret = OCIAttrGet(paramp, OCI_DTYPE_PARAM, &_type, 0, OCI_ATTR_DATA_TYPE, stmt->getErrorHandle()); stmt->checkError(ret, "OCIAttrGet(OCI_ATTR_DATA_TYPE)"); ret = OCIAttrGet(paramp, OCI_DTYPE_PARAM, &_collen, 0, OCI_ATTR_DATA_SIZE, stmt->getErrorHandle()); stmt->checkError(ret, "OCIAttrGet(OCI_ATTR_DATA_SIZE)"); log_debug("column name=\"" << _colName << "\" type=" << _type << " size=" << _collen); /* define outputvariable */ switch (_type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: { log_debug("OCIDefineByPos(SQLT_TIMESTAMP)"); _data = new char[_n * sizeof(OCIDateTime*)]; OCIDateTime** p = reinterpret_cast(_data); log_debug("OCIDescriptorAlloc(OCI_DTYPE_TIMESTAMP) (" << _n << " times)"); for (unsigned n = 0; n < _n; ++n) { ret = OCIDescriptorAlloc(stmt->getConnection()->getEnvHandle(), reinterpret_cast(&p[n]), OCI_DTYPE_TIMESTAMP, 0, 0); stmt->checkError(ret, "OCIDescriptorAlloc(OCI_DTYPE_TIMESTAMP)"); } ret = OCIDefineByPos(stmt->getHandle(), &_defp, stmt->getErrorHandle(), pos + 1, _data, sizeof(OCIDateTime*), SQLT_TIMESTAMP, _nullind, _len, 0, OCI_DEFAULT); } break; case SQLT_INT: log_debug("OCIDefineByPos(SQLT_INT)"); _data = new char[_n * sizeof(long)]; ret = OCIDefineByPos(stmt->getHandle(), &_defp, stmt->getErrorHandle(), pos + 1, _data, sizeof(long), SQLT_INT, _nullind, _len, 0, OCI_DEFAULT); break; case SQLT_UIN: log_debug("OCIDefineByPos(SQLT_UIN)"); _data = new char[_n * sizeof(unsigned long)]; ret = OCIDefineByPos(stmt->getHandle(), &_defp, stmt->getErrorHandle(), pos + 1, _data, sizeof(unsigned long), SQLT_UIN, _nullind, _len, 0, OCI_DEFAULT); break; case SQLT_FLT: log_debug("OCIDefineByPos(SQLT_FLT)"); _data = new char[_n * sizeof(double)]; ret = OCIDefineByPos(stmt->getHandle(), &_defp, stmt->getErrorHandle(), pos + 1, _data, sizeof(double), SQLT_FLT, _nullind, _len, 0, OCI_DEFAULT); break; case SQLT_NUM: case SQLT_VNU: log_debug("OCIDefineByPos(SQLT_VNU)"); _data = new char[_n * OCI_NUMBER_SIZE]; std::fill(_data, _data + _n * OCI_NUMBER_SIZE, 0); ret = OCIDefineByPos(stmt->getHandle(), &_defp, stmt->getErrorHandle(), pos + 1, _data, OCI_NUMBER_SIZE, SQLT_VNU, _nullind, _len, 0, OCI_DEFAULT); break; case SQLT_BLOB: { log_debug("OCIDefineByPos(SQLT_LOB)"); _data = new char[_n * sizeof(OCILobLocator*)]; OCIDateTime** p = reinterpret_cast(_data); log_debug("OCIDescriptorAlloc(OCI_DTYPE_LOB) (" << _n << " times)"); for (unsigned n = 0; n < _n; ++n) { ret = OCIDescriptorAlloc(stmt->getConnection()->getEnvHandle(), reinterpret_cast(&p[n]), OCI_DTYPE_LOB, 0, 0); stmt->checkError(ret, "OCIDescriptorAlloc(OCI_DTYPE_LOB)"); } ret = OCIDefineByPos(stmt->getHandle(), &_defp, stmt->getErrorHandle(), pos + 1, _data, sizeof(OCILobLocator*), SQLT_BLOB, _nullind, _len, 0, OCI_DEFAULT); } break; case SQLT_BIN: log_debug("OCIDefineByPos(SQLT_BIN)"); _data = new char[(_collen + 16) * _n]; ret = OCIDefineByPos(stmt->getHandle(), &_defp, stmt->getErrorHandle(), pos + 1, _data, (_collen + 16), SQLT_BIN, _nullind, _len, 0, OCI_DEFAULT); break; default: log_debug("OCIDefineByPos(SQLT_AFC)"); _data = new char[(_collen + 16) * _n]; ret = OCIDefineByPos(stmt->getHandle(), &_defp, stmt->getErrorHandle(), pos + 1, _data, (_collen + 16), SQLT_AFC, _nullind, _len, 0, OCI_DEFAULT); break; } stmt->checkError(ret, "OCIDefineByPos"); } MultiValue::~MultiValue() { if (_defp) OCIHandleFree(_defp, OCI_HTYPE_DEFINE); delete [] _nullind; delete [] _len; if (_data) { switch(_type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: { OCIDateTime** p = reinterpret_cast(_data); log_debug("OCIDescriptorFree(desc, OCI_DTYPE_TIMESTAMP) (" << _n << " times)"); for (unsigned n = 0; n < _n; ++n) OCIDescriptorFree(p[n], OCI_DTYPE_TIMESTAMP); } break; case SQLT_BLOB: { OCILobLocator** p = reinterpret_cast(_data); log_debug("OCIDescriptorFree(desc, OCI_DTYPE_LOB) (" << _n << " times)"); for (unsigned n = 0; n < _n; ++n) OCIDescriptorFree(p[n], OCI_DTYPE_LOB); } break; default: break; } delete[] _data; } } bool MultiValue::isNull(unsigned n) const { log_debug("isNull(" << n << ')'); return _nullind[n] != 0; } bool MultiValue::getBool(unsigned n) const { log_debug("getBool(" << n << "), type=" << _type); if (_nullind[n] != 0) throw NullValue(); switch (_type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: throw TypeError(); case SQLT_INT: return longValue(n) != 0; case SQLT_UIN: return unsignedValue(n) != 0; case SQLT_FLT: return doubleValue(n) != 0; case SQLT_NUM: case SQLT_VNU: { int value; log_finer("OCINumberToInt"); sword ret = OCINumberToInt(_conn->getErrorHandle(), &number(n), sizeof(int), OCI_NUMBER_SIGNED, &value); _conn->checkError(ret, "OCINumberToInt"); return value != 0; } default: return data(n)[0] == 't' || data(n)[0] == 'T' || data(n)[0] == 'y' || data(n)[0] == 'Y' || data(n)[0] == '1'; } } short MultiValue::getShort(unsigned n) const { log_debug("getShort(" << n << "), type=" << _type); if (_nullind[n] != 0) throw NullValue(); switch (_type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: throw TypeError(); case SQLT_INT: case SQLT_UIN: return static_cast(longValue(n)); case SQLT_FLT: return round(doubleValue(n)); case SQLT_NUM: case SQLT_VNU: { short value; log_finer("OCINumberToInt"); sword ret = OCINumberToInt(_conn->getErrorHandle(), &number(n), sizeof(short), OCI_NUMBER_SIGNED, &value); _conn->checkError(ret, "OCINumberToInt"); return value; } default: return getValue(std::string(data(n), _len[n]), "short"); } } int MultiValue::getInt(unsigned n) const { log_debug("getInt(" << n << "), type=" << _type); if (_nullind[n] != 0) throw NullValue(); switch (_type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: throw TypeError(); case SQLT_INT: case SQLT_UIN: return static_cast(longValue(n)); case SQLT_FLT: return round(doubleValue(n)); case SQLT_NUM: case SQLT_VNU: { int value; log_finer("OCINumberToInt"); sword ret = OCINumberToInt(_conn->getErrorHandle(), &number(n), sizeof(int), OCI_NUMBER_SIGNED, &value); _conn->checkError(ret, "OCINumberToInt"); return value; } default: return getValue(std::string(data(n), _len[n]), "int"); } } long MultiValue::getLong(unsigned n) const { log_debug("getLong(" << n << "), type=" << _type); if (_nullind[n] != 0) throw NullValue(); switch (_type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: throw TypeError(); case SQLT_INT: case SQLT_UIN: return static_cast(longValue(n)); case SQLT_FLT: return round(doubleValue(n)); case SQLT_NUM: case SQLT_VNU: { long value; log_finer("OCINumberToInt"); sword ret = OCINumberToInt(_conn->getErrorHandle(), &number(n), sizeof(long), OCI_NUMBER_SIGNED, &value); _conn->checkError(ret, "OCINumberToInt"); return value; } default: return getValue(std::string(data(n), _len[n]), "long"); } } int32_t MultiValue::getInt32(unsigned n) const { log_debug("getInt32(" << n << "), type=" << _type); return getInt(n); } unsigned short MultiValue::getUnsignedShort(unsigned n) const { log_debug("getUnsignedShort(" << n << "), type=" << _type); if (_nullind[n] != 0) throw NullValue(); switch (_type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: throw TypeError(); case SQLT_INT: case SQLT_UIN: return static_cast(longValue(n)); case SQLT_FLT: return round(doubleValue(n)); case SQLT_NUM: case SQLT_VNU: { unsigned short value; log_finer("OCINumberToInt"); sword ret = OCINumberToInt(_conn->getErrorHandle(), &number(n), sizeof(unsigned short), OCI_NUMBER_UNSIGNED, &value); _conn->checkError(ret, "OCINumberToInt"); return value; } default: return getValue(std::string(data(n), _len[n]), "unsigned short"); } } unsigned MultiValue::getUnsigned(unsigned n) const { log_debug("getUnsigned(" << n << "), type=" << _type); if (_nullind[n] != 0) throw NullValue(); switch (_type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: throw TypeError(); case SQLT_INT: case SQLT_UIN: return static_cast(longValue(n)); case SQLT_FLT: return round(doubleValue(n)); case SQLT_NUM: case SQLT_VNU: { unsigned value; log_finer("OCINumberToInt"); sword ret = OCINumberToInt(_conn->getErrorHandle(), &number(n), sizeof(unsigned), OCI_NUMBER_UNSIGNED, &value); _conn->checkError(ret, "OCINumberToInt"); return value; } default: return getValue(std::string(data(n), _len[n]), "long"); } } unsigned long MultiValue::getUnsignedLong(unsigned n) const { log_debug("getUnsignedLong(" << n << "), type=" << _type); if (_nullind[n] != 0) throw NullValue(); switch (_type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: throw TypeError(); case SQLT_INT: case SQLT_UIN: return static_cast(longValue(n)); case SQLT_FLT: return round(doubleValue(n)); case SQLT_NUM: case SQLT_VNU: { unsigned long value; log_finer("OCINumberToInt"); sword ret = OCINumberToInt(_conn->getErrorHandle(), &number(n), sizeof(unsigned long), OCI_NUMBER_UNSIGNED, &value); _conn->checkError(ret, "OCINumberToInt"); return value; } default: return getValue(std::string(data(n), _len[n]), "unsigned long"); } } uint32_t MultiValue::getUnsigned32(unsigned n) const { log_debug("getUnsigned32(" << n << "), type=" << _type); return getUnsigned(n); } int64_t MultiValue::getInt64(unsigned n) const { log_debug("getInt64(" << n << "), type=" << _type); if (_nullind[n] != 0) throw NullValue(); switch (_type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: throw TypeError(); case SQLT_INT: case SQLT_UIN: return static_cast(longValue(n)); case SQLT_FLT: return round(doubleValue(n)); case SQLT_NUM: case SQLT_VNU: { int64_t value; log_finer("OCINumberToInt"); sword ret = OCINumberToInt(_conn->getErrorHandle(), &number(n), sizeof(int64_t), OCI_NUMBER_SIGNED, &value); _conn->checkError(ret, "OCINumberToInt"); return value; } default: return getValue(std::string(data(n), _len[n]), "int64_t"); } } uint64_t MultiValue::getUnsigned64(unsigned n) const { log_debug("getUnsigned64(" << n << "), type=" << _type); if (_nullind[n] != 0) throw NullValue(); switch (_type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: throw TypeError(); case SQLT_INT: case SQLT_UIN: return static_cast(longValue(n)); case SQLT_FLT: return round(doubleValue(n)); case SQLT_NUM: case SQLT_VNU: { uint64_t value; log_finer("OCINumberToInt"); sword ret = OCINumberToInt(_conn->getErrorHandle(), &number(n), sizeof(uint64_t), OCI_NUMBER_UNSIGNED, &value); _conn->checkError(ret, "OCINumberToInt"); return value; } default: return getValue(std::string(data(n), _len[n]), "uint64_t"); } } Decimal MultiValue::getDecimal(unsigned n) const { log_debug("getDecimal(" << n << "), type=" << _type); if (_nullind[n] != 0) throw NullValue(); switch (_type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: throw TypeError(); case SQLT_INT: case SQLT_UIN: return Decimal(longValue(n), 0); case SQLT_FLT: return Decimal(doubleValue(n)); case SQLT_NUM: case SQLT_VNU: return decimal(n); default: return getValue(std::string(data(n), _len[n]), "Decimal"); } } float MultiValue::getFloat(unsigned n) const { log_debug("getFloat(" << n << "), type=" << _type); if (_nullind[n] != 0) throw NullValue(); switch (_type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: throw TypeError(); case SQLT_INT: case SQLT_UIN: return static_cast(longValue(n)); case SQLT_FLT: return round(doubleValue(n)); case SQLT_NUM: case SQLT_VNU: { float value; log_finer("OCINumberToReal"); sword ret = OCINumberToReal(_conn->getErrorHandle(), &number(n), sizeof(float), &value); _conn->checkError(ret, "OCINumberToReal"); return value; } default: return getValueFloat(data(n), data(n) + _len[n], "float"); } } double MultiValue::getDouble(unsigned n) const { log_debug("getDouble(" << n << "), type=" << _type); if (_nullind[n] != 0) throw NullValue(); switch (_type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: throw TypeError(); case SQLT_INT: case SQLT_UIN: return static_cast(longValue(n)); case SQLT_FLT: return static_cast(doubleValue(n)); case SQLT_NUM: case SQLT_VNU: { double value; log_finer("OCINumberToReal"); sword ret = OCINumberToReal(_conn->getErrorHandle(), &number(n), sizeof(double), &value); _conn->checkError(ret, "OCINumberToReal"); return value; } default: return getValueFloat(data(n), data(n) + _len[n], "double"); } } char MultiValue::getChar(unsigned n) const { log_debug("getChar(" << n << "), type=" << _type); if (_nullind[n] != 0) throw NullValue(); switch (_type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: case SQLT_INT: case SQLT_UIN: case SQLT_FLT: case SQLT_NUM: case SQLT_VNU: throw TypeError(); default: return data(n)[0]; } } void MultiValue::getString(unsigned n, std::string& ret) const { log_debug("getString(" << n << "), type=" << _type); if (_type != SQLT_AFC && _type != SQLT_CHR && _nullind[n] != 0) throw NullValue(); switch (_type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: ret = getDatetime(n).getIso(); break; case SQLT_INT: case SQLT_UIN: ret = toString(longValue(n)); break; case SQLT_FLT: ret = toString(doubleValue(n)); break; case SQLT_NUM: case SQLT_VNU: ret = decimal(n).toString(); break; default: ret.assign(&data(n)[0], _len[n] > 0 ? _len[n] : 0); } } void MultiValue::getBlob(unsigned n, tntdb::Blob& ret) const { log_debug("getBlob(" << n << "), type=" << _type); if (_nullind[n] != 0) throw NullValue(); switch (_type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: case SQLT_INT: case SQLT_UIN: case SQLT_FLT: case SQLT_NUM: case SQLT_VNU: throw TypeError(); case SQLT_BLOB: Blob(_conn, blob(n)).getData(ret); break; default: ret.assign(data(n), _len[n] > 0 ? _len[n] - 1 : 0); } } Date MultiValue::getDate(unsigned n) const { log_debug("getDate(" << n << "), type=" << _type); if (_nullind[n] != 0) throw NullValue(); switch (_type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: return Datetime(_conn, datetime(n)).getDate(); default: throw TypeError(); } } Time MultiValue::getTime(unsigned n) const { log_debug("getTime(" << n << "), type=" << _type); if (_nullind[n] != 0) throw NullValue(); switch (_type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: return Datetime(_conn, datetime(n)).getTime(); default: throw TypeError(); } } tntdb::Datetime MultiValue::getDatetime(unsigned n) const { log_debug("Datetime (" << n << "), type=" << _type); if (_nullind[n] != 0) throw NullValue(); switch (_type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: return Datetime(_conn, datetime(n)).getDatetime(); default: throw TypeError(); } } } } // vim:sw=2:et tntdb-1.4/src/oracle/number.cpp000066400000000000000000000077741354703061500165440ustar00rootroot00000000000000/* * Copyright (C) 2007 Tommi Maekitalo, Mark Wright * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include log_define("tntdb.oracle.number") namespace tntdb { namespace oracle { Number::Number() { std::memset(ociNumber.OCINumberPart, 0, OCI_NUMBER_SIZE); } void Number::setLong(long data, OCIError* errhp) { sword convRet = OCINumberFromInt(errhp, &data, sizeof(data), OCI_NUMBER_SIGNED, &ociNumber); error::checkError(errhp, convRet, "OCINumberFromInt"); } void Number::setUnsignedLong(unsigned long data, OCIError* errhp) { sword convRet = OCINumberFromInt(errhp, &data, sizeof(data), OCI_NUMBER_UNSIGNED, &ociNumber); error::checkError(errhp, convRet, "OCINumberFromInt"); } void Number::setInt64(int64_t data, OCIError* errhp) { sword convRet = OCINumberFromInt(errhp, &data, sizeof(data), OCI_NUMBER_SIGNED, &ociNumber); error::checkError(errhp, convRet, "OCINumberFromInt"); } void Number::setUnsigned64(uint64_t data, OCIError* errhp) { sword convRet = OCINumberFromInt(errhp, &data, sizeof(data), OCI_NUMBER_UNSIGNED, &ociNumber); error::checkError(errhp, convRet, "OCINumberFromInt"); } void Number::setDecimal(const Decimal& decimal, OCIError* errhp) { std::string s = decimal.toStringSci(); static const text fmt[] = "9.99999999999999999999999999999999999999EEEE"; log_debug("OCINumberFromText(\"" << s << "\")"); sword convRet = OCINumberFromText( errhp, reinterpret_cast(s.data()), s.size(), reinterpret_cast(fmt), sizeof(fmt) - 1, reinterpret_cast(""), 0, &ociNumber); error::checkError(errhp, convRet, "OCINumberFromText"); } Number::Number(const Decimal &decimal, OCIError* errhp) { setDecimal(decimal, errhp); } Decimal Number::getDecimal(const OCINumber* handle, OCIError* errhp) { char buffer[64]; ub4 bufsize = sizeof(buffer); log_debug("OCINumberToText(" << static_cast(handle) << ", fmt, fmtsize, \"\", 0, " << bufsize << ", " << static_cast(buffer) << ')'); static const text fmt[] = "9.99999999999999999999999999999999999999EEEE"; sword convRet = OCINumberToText(errhp, const_cast(handle), fmt, sizeof(fmt) - 1, reinterpret_cast(""), 0, &bufsize, reinterpret_cast(buffer)); error::checkError(errhp, convRet, "OCINumberToText"); log_debug("OCINumberToText => \"" << buffer << '"'); return Decimal(std::string(buffer)); } } } tntdb-1.4/src/oracle/result.cpp000066400000000000000000000106251354703061500165570ustar00rootroot00000000000000/* * Copyright (C) 2007 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include log_define("tntdb.oracle.result") namespace tntdb { namespace oracle { Result::Result(Statement* stmt) { sword ret; log_debug("execute select-statement " << stmt->getHandle()); ret = OCIStmtExecute(stmt->getConnection()->getSvcCtxHandle(), stmt->getHandle(), stmt->getErrorHandle(), 0, 0, 0, 0, OCI_DEFAULT); stmt->checkError(ret, "OCIStmtExecute"); log_debug("select-statement " << stmt->getHandle() << " executed"); // get columncount ret = OCIAttrGet(stmt->getHandle(), OCI_HTYPE_STMT, &columncount, 0, OCI_ATTR_PARAM_COUNT, stmt->getErrorHandle()); stmt->checkError(ret, "OCIAttrGet(OCI_ATTR_PARAM_COUNT)"); log_debug("define row"); tntdb::Row row(new oracle::Row(stmt, columncount)); log_debug("fetch results"); while ((ret = OCIStmtFetch(stmt->getHandle(), stmt->getErrorHandle(), 1, OCI_FETCH_NEXT, OCI_DEFAULT)) == OCI_SUCCESS) { rows.push_back(row); row = tntdb::Row(new oracle::Row(stmt, columncount)); } if (ret != OCI_NO_DATA) stmt->checkError(ret, "OCIStmtFetch"); } Result::Result(Statement* stmt, unsigned fetchsize) { sword ret; log_debug("execute select-statement " << stmt->getHandle()); ret = OCIStmtExecute(stmt->getConnection()->getSvcCtxHandle(), stmt->getHandle(), stmt->getErrorHandle(), 0, 0, 0, 0, OCI_DEFAULT); stmt->checkError(ret, "OCIStmtExecute"); log_debug("select-statement " << stmt->getHandle() << " executed"); // get columncount ret = OCIAttrGet(stmt->getHandle(), OCI_HTYPE_STMT, &columncount, 0, OCI_ATTR_PARAM_COUNT, stmt->getErrorHandle()); stmt->checkError(ret, "OCIAttrGet(OCI_ATTR_PARAM_COUNT)"); log_debug("define multirow"); MultiRow::Ptr mr = new MultiRow(stmt, fetchsize, columncount); log_debug("fetch results"); while ((ret = OCIStmtFetch(stmt->getHandle(), stmt->getErrorHandle(), fetchsize, OCI_FETCH_NEXT, OCI_DEFAULT)) != OCI_ERROR) { // get number of rows fetched ub4 rowsFetched; sword ret = OCIAttrGet(stmt->getHandle(), OCI_HTYPE_STMT, &rowsFetched, 0, OCI_ATTR_ROWS_FETCHED, stmt->getErrorHandle()); stmt->checkError(ret, "OCIAttrGet(OCI_ATTR_ROWS_FETCHED)"); for (unsigned n = 0; n < rowsFetched; ++n) { rows.push_back(tntdb::Row(new SingleRow(mr, n))); } if (rowsFetched < fetchsize) return; mr = new MultiRow(stmt, fetchsize, columncount); } if (ret != OCI_NO_DATA && ret != OCI_SUCCESS) stmt->checkError(ret, "OCIStmtFetch"); } tntdb::Row Result::getRow(size_type tup_num) const { return rows.at(tup_num); } Result::size_type Result::size() const { return rows.size(); } Result::size_type Result::getFieldCount() const { return columncount; } } } tntdb-1.4/src/oracle/row.cpp000066400000000000000000000063631354703061500160540ustar00rootroot00000000000000/* * Copyright (C) 2007 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include log_define("tntdb.oracle.row") namespace tntdb { namespace oracle { Row::Row(Statement* stmt) { ub4 columncount; sword ret = OCIAttrGet(stmt->getHandle(), OCI_HTYPE_STMT, &columncount, 0, OCI_ATTR_PARAM_COUNT, stmt->getErrorHandle()); stmt->checkError(ret, "OCIAttrGet(OCI_ATTR_PARAM_COUNT)"); log_debug("define " << columncount << " parameters"); values.reserve(columncount); for (ub4 pos = 0; pos < columncount; ++pos) values.push_back(tntdb::Value(new tntdb::oracle::Value(stmt, pos))); } Row::Row(Statement* stmt, unsigned columncount) { log_debug("define " << columncount << " parameters"); values.reserve(columncount); for (ub4 pos = 0; pos < columncount; ++pos) values.push_back(tntdb::Value(new tntdb::oracle::Value(stmt, pos))); } Row::size_type Row::size() const { return values.size(); } tntdb::Value Row::getValueByNumber(size_type field_num) const { return values.at(field_num); } tntdb::Value Row::getValueByName(const std::string& field_name) const { std::string field_name_upper; field_name_upper.reserve(field_name.size()); for (std::string::const_iterator it = field_name.begin(); it != field_name.end(); ++it) field_name_upper += std::toupper(*it); Values::const_iterator it; for (it = values.begin(); it != values.end(); ++it) if (static_cast(it->getImpl())->getColumnName() == field_name_upper) break; if (it == values.end()) throw FieldNotFound(field_name); return *it; } std::string Row::getColumnName(size_type field_num) const { return static_cast(values[field_num].getImpl())->getColumnName(); } } } tntdb-1.4/src/oracle/singlerow.cpp000066400000000000000000000050071354703061500172500ustar00rootroot00000000000000/* * Copyright (C) 2012 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include log_define("tntdb.oracle.singlerow") namespace tntdb { namespace oracle { SingleRow::SingleRow(MultiRow::Ptr mr, unsigned row) : _mr(mr), _row(row) { _values.resize(mr->size()); } void SingleRow::row(unsigned r) { if (r != _row) { for (unsigned n = 0; n < _values.size(); ++n) { if (_values[n]) _values[n]->row(r); } _row = r; } } SingleRow::size_type SingleRow::size() const { return _mr->size(); } tntdb::Value SingleRow::getValueByNumber(size_type field_num) const { Values& v = const_cast(_values); if (!v[field_num]) { v[field_num] = new SingleValue(_mr->getValuesByNumber(field_num), _row); } return tntdb::Value(v[field_num].getPointer()); } tntdb::Value SingleRow::getValueByName(const std::string& field_name) const { return getValueByNumber(_mr->getColIndexByName(field_name)); } std::string SingleRow::getColumnName(size_type field_num) const { return _mr->getColumnName(field_num); } } } tntdb-1.4/src/oracle/singlevalue.cpp000066400000000000000000000066051354703061500175620ustar00rootroot00000000000000/* * Copyright (C) 2012 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include log_define("tntdb.oracle.singlevalue") namespace tntdb { namespace oracle { bool SingleValue::isNull() const { return _mv->isNull(_row); } bool SingleValue::getBool() const { return _mv->getBool(_row); } short SingleValue::getShort() const { return _mv->getShort(_row); } int SingleValue::getInt() const { return _mv->getInt(_row); } long SingleValue::getLong() const { return _mv->getLong(_row); } unsigned short SingleValue::getUnsignedShort() const { return _mv->getUnsignedShort(_row); } unsigned SingleValue::getUnsigned() const { return _mv->getUnsigned(_row); } unsigned long SingleValue::getUnsignedLong() const { return _mv->getUnsignedLong(_row); } int32_t SingleValue::getInt32() const { return _mv->getInt32(_row); } uint32_t SingleValue::getUnsigned32() const { return _mv->getUnsigned32(_row); } int64_t SingleValue::getInt64() const { return _mv->getInt64(_row); } uint64_t SingleValue::getUnsigned64() const { return _mv->getUnsigned64(_row); } Decimal SingleValue::getDecimal() const { return _mv->getDecimal(_row); } float SingleValue::getFloat() const { return _mv->getFloat(_row); } double SingleValue::getDouble() const { return _mv->getDouble(_row); } char SingleValue::getChar() const { return _mv->getChar(_row); } void SingleValue::getString(std::string& ret) const { return _mv->getString(_row, ret); } void SingleValue::getBlob(tntdb::Blob& ret) const { return _mv->getBlob(_row, ret); } Date SingleValue::getDate() const { return _mv->getDate(_row); } Time SingleValue::getTime() const { return _mv->getTime(_row); } tntdb::Datetime SingleValue::getDatetime() const { return _mv->getDatetime(_row); } } } tntdb-1.4/src/oracle/statement.cpp000066400000000000000000000542311354703061500172460ustar00rootroot00000000000000/* * Copyright (C) 2007 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include log_define("tntdb.oracle.statement") namespace tntdb { namespace oracle { Statement::Bind* Statement::getBindPtr(const std::string& col) { BindMapType::iterator it = bindMap.find(col); if (it == bindMap.end()) it = bindMap.insert(BindMapType::value_type(col, new Bind())).first; return it->second.getPointer(); } Statement::Statement(Connection* conn_, const std::string& query_) : conn(conn_), query(query_), stmtp(0) { getHandle(); } Statement::~Statement() { if (stmtp) { log_debug("release statement handle " << stmtp); sword ret = OCIHandleFree(stmtp, OCI_HTYPE_STMT); if (ret != OCI_SUCCESS) log_error("OCIHandleFree(" << stmtp << " OCI_HTYPE_STMT) failed"); } } // methods of IStatement void Statement::clear() { for (BindMapType::iterator it = bindMap.begin(); it != bindMap.end(); ++it) { it->second->setNull(); log_debug("OCIBindByName, clear(\"" << it->first << "\")"); sword ret = OCIBindByName(getHandle(), &it->second->ptr, conn->getErrorHandle(), 0, 0, 0, 0, SQLT_INT, &it->second->indicator, 0, 0, 0, 0, OCI_DEFAULT); checkError(ret, "OCIBindByName"); } } void Statement::setNull(const std::string& col) { log_debug("OCIStmt(" << getHandle() << ").setNull(\"" << col << "\")"); Bind &b = getBind(col); b.setNull(); if (b.boundPtr != &b.data[0] || b.boundType != SQLT_CHR || b.boundLength != 0) { b.boundPtr = 0; b.boundType = 0; b.boundLength = 0; log_debug("OCIBindByName, setNull(\"" << col << "\")"); sword ret = OCIBindByName(getHandle(), &b.ptr, conn->getErrorHandle(), reinterpret_cast(col.data()), col.size(), 0, 0, SQLT_CHR, &b.indicator, 0, 0, 0, 0, OCI_DEFAULT); checkError(ret, "OCIBindByName"); b.boundPtr = &b.data[0]; b.boundType = SQLT_CHR; } } void Statement::setBool(const std::string& col, bool data) { log_debug("OCIStmt(" << getHandle() << ").setBool(\"" << col << "\", " << data << ')'); Bind &b = getBind(col); b.setData(reinterpret_cast(&data), sizeof(bool)); if (b.boundPtr != &b.data[0] || b.boundType != SQLT_INT || b.boundLength != sizeof(bool)) { b.boundPtr = 0; b.boundType = 0; b.boundLength = 0; log_debug("OCIBindByName, setBool(\"" << col << "\", " << data << ')'); sword ret = OCIBindByName(getHandle(), &b.ptr, conn->getErrorHandle(), reinterpret_cast(col.data()), col.size(), &b.data[0], sizeof(bool), SQLT_INT, 0, 0, 0, 0, 0, OCI_DEFAULT); checkError(ret, "OCIBindByName"); b.boundPtr = &b.data[0]; b.boundType = SQLT_INT; b.boundLength = sizeof(bool); } } void Statement::setShort(const std::string& col, short data) { log_debug("OCIStmt(" << getHandle() << ").setShort(\"" << col << "\", " << data << ')'); Bind &b = getBind(col); b.setData(reinterpret_cast(&data), sizeof(int)); if (b.boundPtr != &b.data[0] || b.boundType != SQLT_INT || b.boundLength != sizeof(short)) { b.boundPtr = 0; b.boundType = 0; b.boundLength = 0; log_debug("OCIBindByName, setInt(\"" << col << "\", " << data << ')'); sword ret = OCIBindByName(getHandle(), &b.ptr, conn->getErrorHandle(), reinterpret_cast(col.data()), col.size(), &b.data[0], sizeof(short), SQLT_INT, 0, 0, 0, 0, 0, OCI_DEFAULT); checkError(ret, "OCIBindByName"); b.boundPtr = &b.data[0]; b.boundType = SQLT_INT; b.boundLength = sizeof(short); } } void Statement::setInt(const std::string& col, int data) { log_debug("OCIStmt(" << getHandle() << ").setInt(\"" << col << "\", " << data << ')'); Bind &b = getBind(col); b.setData(reinterpret_cast(&data), sizeof(int)); if (b.boundPtr != &b.data[0] || b.boundType != SQLT_INT || b.boundLength != sizeof(int)) { b.boundPtr = 0; b.boundType = 0; b.boundLength = 0; log_debug("OCIBindByName, setInt(\"" << col << "\", " << data << ')'); sword ret = OCIBindByName(getHandle(), &b.ptr, conn->getErrorHandle(), reinterpret_cast(col.data()), col.size(), &b.data[0], sizeof(int), SQLT_INT, 0, 0, 0, 0, 0, OCI_DEFAULT); checkError(ret, "OCIBindByName"); b.boundPtr = &b.data[0]; b.boundType = SQLT_INT; b.boundLength = sizeof(int); } } void Statement::setLong(const std::string& col, long data) { log_debug("OCIStmt(" << getHandle() << ").setLong(\"" << col << "\", " << data << ')'); Bind &b = getBind(col); b.number.setLong(data, conn->getErrorHandle()); if (b.boundPtr != &b.data[0] || b.boundType != SQLT_VNU) { b.boundPtr = 0; b.boundType = 0; b.boundLength = 0; log_debug("OCIBindByName, setLong(\"" << col << "\", " << data << ')'); sword ret = OCIBindByName(getHandle(), &b.ptr, conn->getErrorHandle(), reinterpret_cast(col.data()), col.size(), b.number.getHandle(), OCI_NUMBER_SIZE, SQLT_VNU, 0, 0, 0, 0, 0, OCI_DEFAULT); checkError(ret, "OCIBindByName"); b.boundPtr = &b.data[0]; b.boundType = SQLT_VNU; } } void Statement::setUnsignedShort(const std::string& col, unsigned short data) { log_debug("OCIStmt(" << getHandle() << ").setUnsignedShort(\"" << col << "\", " << data << ')'); Bind &b = getBind(col); b.setData(reinterpret_cast(&data), sizeof(unsigned short)); if (b.boundPtr != &b.data[0] || b.boundType != SQLT_UIN || b.boundLength != sizeof(unsigned short)) { b.boundPtr = 0; b.boundType = 0; b.boundLength = 0; log_debug("OCIBindByName, setUnsigned(\"" << col << "\", " << data << ')'); sword ret = OCIBindByName(getHandle(), &b.ptr, conn->getErrorHandle(), reinterpret_cast(col.data()), col.size(), &b.data[0], sizeof(unsigned short), SQLT_UIN, 0, 0, 0, 0, 0, OCI_DEFAULT); checkError(ret, "OCIBindByName"); b.boundPtr = &b.data[0]; b.boundType = SQLT_UIN; b.boundLength = sizeof(unsigned short); } } void Statement::setUnsigned(const std::string& col, unsigned data) { log_debug("OCIStmt(" << getHandle() << ").setUnsigned(\"" << col << "\", " << data << ')'); Bind &b = getBind(col); b.setData(reinterpret_cast(&data), sizeof(unsigned)); if (b.boundPtr != &b.data[0] || b.boundType != SQLT_UIN || b.boundLength != sizeof(unsigned)) { b.boundPtr = 0; b.boundType = 0; b.boundLength = 0; log_debug("OCIBindByName, setUnsigned(\"" << col << "\", " << data << ')'); sword ret = OCIBindByName(getHandle(), &b.ptr, conn->getErrorHandle(), reinterpret_cast(col.data()), col.size(), &b.data[0], sizeof(unsigned), SQLT_UIN, 0, 0, 0, 0, 0, OCI_DEFAULT); checkError(ret, "OCIBindByName"); b.boundPtr = &b.data[0]; b.boundType = SQLT_UIN; b.boundLength = sizeof(unsigned); } } void Statement::setUnsignedLong(const std::string& col, unsigned long data) { log_debug("OCIStmt(" << getHandle() << ").setUnsignedLong(\"" << col << "\", " << data << ')'); Bind &b = getBind(col); b.number.setUnsignedLong(data, conn->getErrorHandle()); if (b.boundPtr != &b.data[0] || b.boundType != SQLT_VNU) { b.boundPtr = 0; b.boundType = 0; b.boundLength = 0; log_debug("OCIBindByName, setUnsignedLong(\"" << col << "\", " << data << ')'); sword ret = OCIBindByName(getHandle(), &b.ptr, conn->getErrorHandle(), reinterpret_cast(col.data()), col.size(), b.number.getHandle(), OCI_NUMBER_SIZE, SQLT_VNU, 0, 0, 0, 0, 0, OCI_DEFAULT); checkError(ret, "OCIBindByName"); b.boundPtr = &b.data[0]; b.boundType = SQLT_VNU; } } void Statement::setInt32(const std::string& col, int32_t data) { log_debug("OCIStmt(" << getHandle() << ").setInt32(\"" << col << "\", " << data << ')'); return setInt(col, data); } void Statement::setUnsigned32(const std::string& col, uint32_t data) { log_debug("OCIStmt(" << getHandle() << ").setUnsigned32(\"" << col << "\", " << data << ')'); return setUnsigned(col, data); } void Statement::setInt64(const std::string& col, int64_t data) { log_debug("OCIStmt(" << getHandle() << ").setInt64(\"" << col << "\", " << data << ')'); Bind &b = getBind(col); b.number.setInt64(data, conn->getErrorHandle()); if (b.boundPtr != &b.data[0] || b.boundType != SQLT_VNU) { b.boundPtr = 0; b.boundType = 0; b.boundLength = 0; log_debug("OCIBindByName, setUnsignedLong(\"" << col << "\", " << data << ')'); sword ret = OCIBindByName(getHandle(), &b.ptr, conn->getErrorHandle(), reinterpret_cast(col.data()), col.size(), b.number.getHandle(), OCI_NUMBER_SIZE, SQLT_VNU, 0, 0, 0, 0, 0, OCI_DEFAULT); checkError(ret, "OCIBindByName"); b.boundPtr = &b.data[0]; b.boundType = SQLT_VNU; } } void Statement::setUnsigned64(const std::string& col, uint64_t data) { log_debug("OCIStmt(" << getHandle() << ").setUnsigned64(\"" << col << "\", " << data << ')'); Bind &b = getBind(col); b.number.setUnsigned64(data, conn->getErrorHandle()); if (b.boundPtr != &b.data[0] || b.boundType != SQLT_VNU) { b.boundPtr = 0; b.boundType = 0; b.boundLength = 0; log_debug("OCIBindByName, setUnsignedLong(\"" << col << "\", " << data << ')'); sword ret = OCIBindByName(getHandle(), &b.ptr, conn->getErrorHandle(), reinterpret_cast(col.data()), col.size(), (void *)b.number.getHandle(), OCI_NUMBER_SIZE, SQLT_VNU, 0, 0, 0, 0, 0, OCI_DEFAULT); checkError(ret, "OCIBindByName"); b.boundPtr = &b.data[0]; b.boundType = SQLT_VNU; } } void Statement::setDecimal(const std::string& col, const Decimal& decimal) { log_debug("OCIStmt(" << getHandle() << ").setDecimal(\"" << col << "\", " << decimal << ')'); Bind &b = getBind(col); b.number.setDecimal(decimal, conn->getErrorHandle()); if (b.boundPtr != &b.data[0] || b.boundType != SQLT_VNU) { b.boundPtr = 0; b.boundType = 0; b.boundLength = 0; log_debug("OCIBindByName, setDecimal(\"" << col << "\", " << decimal << ')'); sword ret = OCIBindByName(getHandle(), &b.ptr, conn->getErrorHandle(), reinterpret_cast(col.data()), col.size(), b.number.getHandle(), OCI_NUMBER_SIZE, SQLT_VNU, 0, 0, 0, 0, 0, OCI_DEFAULT); checkError(ret, "OCIBindByName"); b.boundPtr = &b.data[0]; b.boundType = SQLT_VNU; } } void Statement::setFloat(const std::string& col, float data) { log_debug("OCIStmt(" << getHandle() << ").setFloat(\"" << col << "\", " << data << ')'); Bind &b = getBind(col); b.setData(reinterpret_cast(&data), sizeof(float)); if (b.boundPtr != &b.data[0] || b.boundType != SQLT_FLT || b.boundLength != sizeof(float)) { b.boundPtr = 0; b.boundType = 0; b.boundLength = 0; log_debug("OCIBindByName, setFloat(\"" << col << "\", " << data << ')'); sword ret = OCIBindByName(getHandle(), &b.ptr, conn->getErrorHandle(), reinterpret_cast(col.data()), col.size(), &b.data[0], sizeof(float), SQLT_FLT, 0, 0, 0, 0, 0, OCI_DEFAULT); checkError(ret, "OCIBindByName"); b.boundPtr = &b.data[0]; b.boundType = SQLT_FLT; b.boundLength = sizeof(float); } } void Statement::setDouble(const std::string& col, double data) { log_debug("OCIStmt(" << getHandle() << ").setDouble(\"" << col << "\", " << data << ')'); Bind &b = getBind(col); b.setData(reinterpret_cast(&data), sizeof(double)); if (b.boundPtr != &b.data[0] || b.boundType != SQLT_FLT || b.boundLength != sizeof(double)) { b.boundPtr = 0; b.boundType = 0; b.boundLength = 0; log_debug("OCIBindByName, setDouble(\"" << col << "\", " << data << ')'); sword ret = OCIBindByName(getHandle(), &b.ptr, conn->getErrorHandle(), reinterpret_cast(col.data()), col.size(), &b.data[0], sizeof(double), SQLT_FLT, 0, 0, 0, 0, 0, OCI_DEFAULT); checkError(ret, "OCIBindByName"); b.boundPtr = &b.data[0]; b.boundType = SQLT_FLT; b.boundLength = sizeof(double); } } void Statement::setChar(const std::string& col, char data) { log_debug("OCIStmt(" << getHandle() << ").setChar(\"" << col << "\", '" << data << "')"); Bind &b = getBind(col); b.setData(&data, 1); if (b.boundPtr != &b.data[0] || b.boundType != SQLT_AFC || b.boundLength != 1) { b.boundPtr = 0; b.boundType = 0; b.boundLength = 0; log_debug("OCIBindByName, setChar(\"" << col << "\", " << data << ')'); sword ret = OCIBindByName(getHandle(), &b.ptr, conn->getErrorHandle(), reinterpret_cast(col.data()), col.size(), &b.data[0], 1, SQLT_AFC, 0, 0, 0, 0, 0, OCI_DEFAULT); checkError(ret, "OCIBindByName"); b.boundPtr = &b.data[0]; b.boundType = SQLT_AFC; b.boundLength = 1; } } void Statement::setString(const std::string& col, const std::string& data) { log_debug("OCIStmt(" << getHandle() << ").setString(\"" << col << "\", \"" << data << "\")"); Bind &b = getBind(col); b.setData(data); if (b.boundPtr != &b.data[0] || b.boundType != SQLT_AFC || b.boundLength != data.size()) { b.boundPtr = 0; b.boundType = 0; b.boundLength = 0; log_debug("OCIBindByName, setString(\"" << col << "\", \"" << data << "\")"); sword ret = OCIBindByName(getHandle(), &b.ptr, conn->getErrorHandle(), reinterpret_cast(col.data()), col.size(), &b.data[0], data.size(), SQLT_AFC, 0, 0, 0, 0, 0, OCI_DEFAULT); checkError(ret, "OCIBindByName"); b.boundPtr = &b.data[0]; b.boundType = SQLT_AFC; b.boundLength = data.size(); } } void Statement::setBlob(const std::string& col, const tntdb::Blob& data) { log_debug("OCIStmt(" << getHandle() << ").setBlob(\"" << col << "\", data(" << data.size() << "))"); Bind &b = getBind(col); b.setData(data.data(), data.size()); if (b.boundPtr != &b.data[0] || b.boundType != SQLT_BIN || b.boundLength != data.size()) { b.boundPtr = 0; b.boundType = 0; b.boundLength = 0; log_debug("OCIBindByName, setBlob(\"" << col << "\", data{" << data.size() << "})"); sword ret = OCIBindByName(getHandle(), &b.ptr, conn->getErrorHandle(), reinterpret_cast(col.data()), col.size(), &b.data[0], data.size(), SQLT_BIN, 0, 0, 0, 0, 0, OCI_DEFAULT); checkError(ret, "OCIBindByName"); b.boundPtr = &b.data[0]; b.boundType = SQLT_BIN; b.boundLength = data.size(); } } void Statement::setDate(const std::string& col, const Date& data) { log_debug("OCIStmt(" << getHandle() << ").setDate(\"" << col << "\", \"" << data.getIso() << "\")"); Bind &b = getBind(col); b.datetime.assign(conn, data); if (b.boundPtr != &b.data[0] || b.boundType != SQLT_TIMESTAMP) { b.boundPtr = 0; b.boundType = 0; b.boundLength = 0; log_debug("OCIBindByName, setDate(\"" << col << "\", " << data.getIso() << ')'); sword ret = OCIBindByName(getHandle(), &b.ptr, conn->getErrorHandle(), reinterpret_cast(col.data()), col.size(), &b.datetime.getHandle(), sizeof(OCIDateTime**), SQLT_TIMESTAMP, 0, 0, 0, 0, 0, OCI_DEFAULT); checkError(ret, "OCIBindByName"); b.boundPtr = &b.data[0]; b.boundType = SQLT_TIMESTAMP; } } void Statement::setTime(const std::string& col, const Time& data) { log_debug("OCIStmt(" << getHandle() << ").setTime(\"" << col << "\", \"" << data.getIso() << "\")"); Bind &b = getBind(col); b.datetime.assign(conn, data); if (b.boundPtr != &b.data[0] || b.boundType != SQLT_TIMESTAMP) { b.boundPtr = 0; b.boundType = 0; b.boundLength = 0; log_debug("OCIBindByName, setTime(\"" << col << "\", " << data.getIso() << ')'); sword ret = OCIBindByName(getHandle(), &b.ptr, conn->getErrorHandle(), reinterpret_cast(col.data()), col.size(), &b.datetime.getHandle(), sizeof(OCIDateTime**), SQLT_TIMESTAMP, 0, 0, 0, 0, 0, OCI_DEFAULT); checkError(ret, "OCIBindByName"); b.boundPtr = &b.data[0]; b.boundType = SQLT_TIMESTAMP; } } void Statement::setDatetime(const std::string& col, const tntdb::Datetime& data) { log_debug("OCIStmt(" << getHandle() << ").setDatetime(\"" << col << "\", \"" << data.getIso() << "\")"); Bind &b = getBind(col); b.datetime.assign(conn, data); if (b.boundPtr != &b.data[0] || b.boundType != SQLT_TIMESTAMP) { b.boundPtr = 0; b.boundType = 0; b.boundLength = 0; log_debug("OCIBindByName, setDatetime(\"" << col << "\", " << data.getIso() << ')'); sword ret = OCIBindByName(getHandle(), &b.ptr, conn->getErrorHandle(), reinterpret_cast(col.data()), col.size(), &b.datetime.getHandle(), sizeof(OCIDateTime**), SQLT_TIMESTAMP, 0, 0, 0, 0, 0, OCI_DEFAULT); checkError(ret, "OCIBindByName"); b.boundPtr = &b.data[0]; b.boundType = SQLT_TIMESTAMP; } } Statement::size_type Statement::execute() { log_debug("execute statement " << getHandle() << " mode=" << (conn->isTransactionActive() ? "OCI_DEFAULT" : "OCI_COMMIT_ON_SUCCESS")); sword ret = OCIStmtExecute(conn->getSvcCtxHandle(), getHandle(), conn->getErrorHandle(), 1, 0, 0, 0, conn->isTransactionActive() ? OCI_DEFAULT : OCI_COMMIT_ON_SUCCESS); checkError(ret, "OCIStmtExecute"); ub4 rowcnt = 0; ret = OCIAttrGet(getHandle(), OCI_HTYPE_STMT, &rowcnt, 0, OCI_ATTR_ROW_COUNT, conn->getErrorHandle()); checkError(ret, "OCIAttrGet"); return rowcnt; } tntdb::Result Statement::select() { return tntdb::Result(new Result(this, 64)); } tntdb::Row Statement::selectRow() { sword ret = OCIStmtExecute(getConnection()->getSvcCtxHandle(), getHandle(), getErrorHandle(), 0, 0, 0, 0, OCI_DEFAULT); checkError(ret, "OCIStmtExecute"); tntdb::Row row(new oracle::Row(this)); ret = OCIStmtFetch(getHandle(), getErrorHandle(), 1, OCI_FETCH_NEXT, OCI_DEFAULT); checkError(ret, "OCIStmtFetch"); return row; } tntdb::Value Statement::selectValue() { sword ret = OCIStmtExecute(getConnection()->getSvcCtxHandle(), getHandle(), getErrorHandle(), 0, 0, 0, 0, OCI_DEFAULT); checkError(ret, "OCIStmtExecute"); tntdb::Value value(new oracle::Value(this, 0)); ret = OCIStmtFetch(getHandle(), getErrorHandle(), 1, OCI_FETCH_NEXT, OCI_DEFAULT); checkError(ret, "OCIStmtFetch"); return value; } ICursor* Statement::createCursor(unsigned fetchsize) { return new Cursor(this, fetchsize); } OCIStmt* Statement::getHandle() { if (stmtp == 0) { log_debug("prepare statement \"" << query << '"'); sword ret = OCIHandleAlloc(conn->getEnvHandle(), (void**)&stmtp, OCI_HTYPE_STMT, 0, 0); checkError(ret, "OCIHandleAlloc(OCI_HTYPE_STMT)"); ret = OCIStmtPrepare(stmtp, conn->getErrorHandle(), reinterpret_cast(query.data()), query.size(), OCI_NTV_SYNTAX, OCI_DEFAULT); checkError(ret, "OCIStmtPrepare"); log_debug("statement handle " << stmtp); } return stmtp; } } } tntdb-1.4/src/oracle/string.cpp000066400000000000000000000042551354703061500165510ustar00rootroot00000000000000/* * Copyright (C) 2018 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include log_define("tntdb.oracle.string") namespace tntdb { namespace oracle { void String::assign(Connection* conn, const std::string& s) { sword ret = OCIStringAssignText(conn->getEnvHandle(), conn->getErrorHandle(), reinterpret_cast(s.data()), s.size(), &handle); conn->checkError(ret, "OCIStringAssignText"); } const char* String::data() const { if (handle == 0) return 0; return reinterpret_cast(OCIStringPtr(conn->getEnvHandle(), handle)); } ub4 String::size() const { if (handle == 0) return 0; return OCIStringSize(conn->getEnvHandle(), handle); } } } tntdb-1.4/src/oracle/value.cpp000066400000000000000000000441141354703061500163550ustar00rootroot00000000000000/* * Copyright (C) 2007 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include log_define("tntdb.oracle.value") namespace tntdb { namespace oracle { namespace { template T getValue(const std::string& s, const char* tname) { std::istringstream in(s); T ret; in >> ret; if (!in) { std::ostringstream msg; msg << "can't convert \"" << s << "\" to " << tname; throw TypeError(msg.str()); } return ret; } template T getValueFloat(I from, I to, const char* tname) { // This is a stupid workaround for converting decimal comma into decimal point // It should be actually done in OCI std::string o; o.reserve(to - from); std::replace_copy(from, to, std::back_inserter(o), ',', '.'); return getValue(o, tname); } template std::string toString(T v) { std::ostringstream ret; ret << v; return ret.str(); } template <> std::string toString(float v) { std::ostringstream ret; ret.precision(24); ret << v; return ret.str(); } template <> std::string toString(double v) { std::ostringstream ret; ret.precision(24); ret << v; return ret.str(); } template <> std::string toString(Decimal v) { std::ostringstream ret; ret.precision(24); ret << v; return ret.str(); } template IntType round(double d) { if (d > std::numeric_limits::max() + .5 || d < std::numeric_limits::min() - .5) { log_warn("overflow when trying to read integer from float " << d); throw std::overflow_error("overflow when trying to read integer from float"); } return static_cast(d >= 0 ? d + .5 : d - .5); } } Value::Value(Statement* stmt, ub4 pos) { sword ret; /* get parameter-info */ log_debug("OCIParamGet(" << static_cast(stmt->getHandle()) << ')'); ret = OCIParamGet(stmt->getHandle(), OCI_HTYPE_STMT, stmt->getErrorHandle(), reinterpret_cast(¶mp), pos + 1); stmt->checkError(ret, "OCIParamGet"); init(stmt, paramp, pos); OCIDescriptorFree(paramp, OCI_DTYPE_PARAM); paramp = 0; } Value::Value(Statement* stmt, OCIParam* paramp, ub4 pos) { init(stmt, paramp, pos); } void Value::init(Statement* stmt, OCIParam* paramp, ub4 pos) { sword ret; errhp = stmt->getErrorHandle(); /* retrieve column name */ ub4 col_name_len = 0; text* col_name = 0; ret = OCIAttrGet(paramp, OCI_DTYPE_PARAM, &col_name, &col_name_len, OCI_ATTR_NAME, stmt->getErrorHandle()); stmt->checkError(ret, "OCIAttrGet(OCI_ATTR_NAME)"); colName.assign(reinterpret_cast(col_name), col_name_len); /* retrieve the data type attribute */ ret = OCIAttrGet(paramp, OCI_DTYPE_PARAM, &type, 0, OCI_ATTR_DATA_TYPE, stmt->getErrorHandle()); stmt->checkError(ret, "OCIAttrGet(OCI_ATTR_DATA_TYPE)"); ret = OCIAttrGet(paramp, OCI_DTYPE_PARAM, &len, 0, OCI_ATTR_DATA_SIZE, stmt->getErrorHandle()); stmt->checkError(ret, "OCIAttrGet(OCI_ATTR_DATA_SIZE)"); log_debug("column name=\"" << colName << "\" type=" << type << " size=" << len); /* define outputvariable */ switch (type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: log_debug("OCIDefineByPos(SQLT_TIMESTAMP)"); ret = OCIDefineByPos(stmt->getHandle(), &defp, stmt->getErrorHandle(), pos + 1, &datetime.getReference(stmt->getConnection()), sizeof(OCIDateTime*), SQLT_TIMESTAMP, &nullind, &len, 0, OCI_DEFAULT); break; case SQLT_INT: log_debug("OCIDefineByPos(SQLT_INT)"); ret = OCIDefineByPos(stmt->getHandle(), &defp, stmt->getErrorHandle(), pos + 1, &longValue, sizeof(longValue), SQLT_INT, &nullind, &len, 0, OCI_DEFAULT); break; case SQLT_UIN: log_debug("OCIDefineByPos(SQLT_UIN)"); ret = OCIDefineByPos(stmt->getHandle(), &defp, stmt->getErrorHandle(), pos + 1, &uint32Value, sizeof(uint32Value), SQLT_UIN, &nullind, &len, 0, OCI_DEFAULT); break; case SQLT_FLT: log_debug("OCIDefineByPos(SQLT_FLT)"); ret = OCIDefineByPos(stmt->getHandle(), &defp, stmt->getErrorHandle(), pos + 1, &doubleValue, sizeof(doubleValue), SQLT_FLT, &nullind, &len, 0, OCI_DEFAULT); break; case SQLT_NUM: case SQLT_VNU: log_debug("OCIDefineByPos(SQLT_VNU)"); ret = OCIDefineByPos(stmt->getHandle(), &defp, stmt->getErrorHandle(), pos + 1, number.getHandle(), OCI_NUMBER_SIZE, SQLT_VNU, &nullind, &len, 0, OCI_DEFAULT); break; case SQLT_BLOB: log_debug("OCIDefineByPos(SQLT_LOB)"); ret = OCIDefineByPos(stmt->getHandle(), &defp, stmt->getErrorHandle(), pos + 1, &blob.getHandle(stmt->getConnection()), 0, SQLT_BLOB, &nullind, &len, 0, OCI_DEFAULT); break; default: log_debug("OCIDefineByPos(SQLT_AFC)"); data.resize(len + 16); ret = OCIDefineByPos(stmt->getHandle(), &defp, stmt->getErrorHandle(), pos + 1, &data[0], len + 16, SQLT_AFC, &nullind, &len, 0, OCI_DEFAULT); break; } stmt->checkError(ret, "OCIDefineByPos"); } Value::~Value() { if (defp) OCIHandleFree(defp, OCI_HTYPE_DEFINE); if (paramp) OCIDescriptorFree(paramp, OCI_DTYPE_PARAM); } bool Value::isNull() const { return nullind != 0; } bool Value::getBool() const { if (isNull()) throw NullValue(); switch (type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: throw TypeError(); case SQLT_INT: return longValue != 0; case SQLT_UIN: return uint32Value != 0; case SQLT_FLT: return doubleValue != 0; case SQLT_NUM: case SQLT_VNU: return !number.getDecimal(errhp).isZero(); default: return data[0] == 't' || data[0] == 'T' || data[0] == 'y' || data[0] == 'Y' || data[0] == '1'; } } short Value::getShort() const { if (isNull()) throw NullValue(); switch (type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: throw TypeError(); case SQLT_INT: case SQLT_UIN: return static_cast(longValue); case SQLT_FLT: return round(doubleValue); case SQLT_NUM: case SQLT_VNU: return number.getDecimal(errhp).getInteger(); default: return getValue(std::string(&data[0], len), "int"); } } int Value::getInt() const { if (isNull()) throw NullValue(); switch (type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: throw TypeError(); case SQLT_INT: case SQLT_UIN: return static_cast(longValue); case SQLT_FLT: return round(doubleValue); case SQLT_NUM: case SQLT_VNU: return number.getDecimal(errhp).getInteger(); default: return getValue(std::string(&data[0], len), "int"); } } long Value::getLong() const { if (isNull()) throw NullValue(); switch (type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: throw TypeError(); case SQLT_INT: case SQLT_UIN: return static_cast(longValue); case SQLT_FLT: return round(doubleValue); case SQLT_NUM: case SQLT_VNU: return number.getDecimal(errhp).getInteger(); default: return getValue(std::string(&data[0], len), "long"); } } int32_t Value::getInt32() const { return getInt(); } unsigned short Value::getUnsignedShort() const { if (isNull()) throw NullValue(); switch (type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: throw TypeError(); case SQLT_INT: case SQLT_UIN: return static_cast(longValue); case SQLT_FLT: return round(doubleValue); case SQLT_NUM: case SQLT_VNU: return number.getDecimal(errhp).getInteger(); default: return getValue(std::string(&data[0], len), "unsigned"); } } unsigned Value::getUnsigned() const { if (isNull()) throw NullValue(); switch (type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: throw TypeError(); case SQLT_INT: case SQLT_UIN: return static_cast(longValue); case SQLT_FLT: return round(doubleValue); case SQLT_NUM: case SQLT_VNU: return number.getDecimal(errhp).getInteger(); default: return getValue(std::string(&data[0], len), "unsigned"); } } unsigned long Value::getUnsignedLong() const { if (isNull()) throw NullValue(); switch (type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: throw TypeError(); case SQLT_INT: case SQLT_UIN: return static_cast(longValue); case SQLT_FLT: return round(doubleValue); case SQLT_NUM: case SQLT_VNU: return number.getDecimal(errhp).getInteger(); default: return getValue(std::string(&data[0], len), "unsigned long"); } } uint32_t Value::getUnsigned32() const { return getUnsigned(); } int64_t Value::getInt64() const { if (isNull()) throw NullValue(); switch (type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: throw TypeError(); case SQLT_INT: case SQLT_UIN: return static_cast(longValue); case SQLT_FLT: return round(doubleValue); case SQLT_NUM: case SQLT_VNU: return number.getDecimal(errhp).getInteger(); default: return getValue(std::string(&data[0], len), "int64_t"); } } uint64_t Value::getUnsigned64() const { if (isNull()) throw NullValue(); switch (type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: throw TypeError(); case SQLT_INT: case SQLT_UIN: return static_cast(longValue); case SQLT_FLT: return round(doubleValue); case SQLT_NUM: case SQLT_VNU: return number.getDecimal(errhp).getInteger(); default: return getValue(std::string(&data[0], len), "uint64_t"); } } Decimal Value::getDecimal() const { if (isNull()) throw NullValue(); switch (type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: throw TypeError(); case SQLT_INT: case SQLT_UIN: return Decimal(longValue, 0); case SQLT_FLT: return Decimal(doubleValue); case SQLT_NUM: case SQLT_VNU: return number.getDecimal(errhp); default: return Decimal(std::string(&data[0], len)); } } float Value::getFloat() const { if (isNull()) throw NullValue(); switch (type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: throw TypeError(); case SQLT_INT: case SQLT_UIN: return static_cast(longValue); case SQLT_FLT: return round(doubleValue); case SQLT_NUM: case SQLT_VNU: return number.getDecimal(errhp).getDouble(); default: return getValueFloat(data.begin(), data.begin() + len, "float"); } } double Value::getDouble() const { if (isNull()) throw NullValue(); switch (type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: throw TypeError(); case SQLT_INT: case SQLT_UIN: return static_cast(longValue); case SQLT_FLT: return static_cast(doubleValue); case SQLT_NUM: case SQLT_VNU: return number.getDecimal(errhp).getDouble(); default: return getValueFloat(data.begin(), data.begin() + len, "double"); } } char Value::getChar() const { if (isNull()) throw NullValue(); switch (type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: case SQLT_INT: case SQLT_UIN: case SQLT_FLT: case SQLT_NUM: case SQLT_VNU: throw TypeError(); default: return data[0]; } } void Value::getString(std::string& ret) const { log_debug("Value::getString with type=" << type << " name=" << colName << " size=" << len); if (type != SQLT_AFC && type != SQLT_CHR && isNull()) throw NullValue(); switch (type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: ret = datetime.getDatetime().getIso(); break; case SQLT_INT: case SQLT_UIN: ret = toString(longValue); break; case SQLT_FLT: ret = toString(doubleValue); break; case SQLT_NUM: case SQLT_VNU: ret = number.getDecimal(errhp).toString(); break; default: ret.assign(&data[0], len > 0 ? len : 0); } } void Value::getBlob(tntdb::Blob& ret) const { log_debug("get blob from type " << type); if (isNull()) throw NullValue(); switch (type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: case SQLT_INT: case SQLT_UIN: case SQLT_FLT: case SQLT_NUM: case SQLT_VNU: throw TypeError(); case SQLT_BLOB: blob.getData(ret); break; default: ret.assign(&data[0], len > 0 ? len - 1 : 0); } } Date Value::getDate() const { if (isNull()) throw NullValue(); switch (type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: return datetime.getDate(); default: throw TypeError(); } } Time Value::getTime() const { if (isNull()) throw NullValue(); switch (type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: return datetime.getTime(); default: throw TypeError(); } } tntdb::Datetime Value::getDatetime() const { if (isNull()) throw NullValue(); switch (type) { case SQLT_DAT: case SQLT_TIMESTAMP: case SQLT_TIMESTAMP_TZ: case SQLT_TIMESTAMP_LTZ: return datetime.getDatetime(); default: throw TypeError(); } } } } tntdb-1.4/src/poolconnection.cpp000066400000000000000000000105711354703061500170250ustar00rootroot00000000000000/* * Copyright (C) 2006 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include log_define("tntdb.poolconnection") namespace tntdb { PoolConnection::PoolConnection(ConnectionPool::PoolObjectType connection_) : connection(connection_), inTransaction(false), drop(false) { log_debug("PoolConnection " << this << " for connection " << connection->getImpl()); } PoolConnection::~PoolConnection() { // don't put the connection back to the free pool, when there is a // pending transaction if (inTransaction || drop) { log_debug("don't reuse connection " << connection->getImpl()); connection.release(); } else log_debug("reuse connection " << connection->getImpl()); } void PoolConnection::beginTransaction() { connection->beginTransaction(); inTransaction = true; } void PoolConnection::commitTransaction() { connection->commitTransaction(); inTransaction = false; } void PoolConnection::rollbackTransaction() { connection->rollbackTransaction(); inTransaction = false; // When a rollback has been done, this may be a indication, that something // weird has happened, so we do not reuse that connection. drop = true; } PoolConnection::size_type PoolConnection::execute(const std::string& query) { return connection->execute(query); } Result PoolConnection::select(const std::string& query) { return connection->select(query); } Row PoolConnection::selectRow(const std::string& query) { return connection->selectRow(query); } Value PoolConnection::selectValue(const std::string& query) { return connection->selectValue(query); } Statement PoolConnection::prepareWithLimit(const std::string& query, const std::string& limit, const std::string& offset) { return connection->prepareWithLimit(query, limit, offset); } Statement PoolConnection::prepare(const std::string& query) { return connection->prepare(query); } Statement PoolConnection::prepareCached(const std::string& query, const std::string& key) { return connection->prepareCached(query, key); } Statement PoolConnection::prepareCachedWithLimit(const std::string& query, const std::string& limit, const std::string& offset, const std::string& key) { return connection->prepareCachedWithLimit(query, limit, offset, key); } void PoolConnection::clearStatementCache() { return connection->clearStatementCache(); } bool PoolConnection::clearStatementCache(const std::string& key) { return connection->clearStatementCache(key); } bool PoolConnection::ping() { bool ok = connection->ping(); if (!ok) drop = true; return ok; } long PoolConnection::lastInsertId(const std::string& name) { return connection->lastInsertId(name); } void PoolConnection::lockTable(const std::string& tablename, bool exclusive) { connection->getImpl()->lockTable(tablename, exclusive); } } tntdb-1.4/src/postgresql/000077500000000000000000000000001354703061500154675ustar00rootroot00000000000000tntdb-1.4/src/postgresql/Makefile.am000066400000000000000000000010101354703061500175130ustar00rootroot00000000000000AM_CPPFLAGS = @PG_CPPFLAGS@ -I$(top_srcdir)/include -I$(top_builddir)/include sources = connection.cpp connectionmanager.cpp cursor.cpp error.cpp result.cpp resultrow.cpp resultvalue.cpp statement.cpp if MAKE_POSTGRESQL driver_LTLIBRARIES = tntdb@abi_current@-postgresql.la tntdb@abi_current@_postgresql_la_SOURCES = $(sources) tntdb@abi_current@_postgresql_la_LDFLAGS = -module -version-info @sonumber@ @PG_LDFLAGS@ @SHARED_LIB_FLAG@ tntdb@abi_current@_postgresql_la_LIBADD = $(top_builddir)/src/libtntdb.la endif tntdb-1.4/src/postgresql/connection.cpp000066400000000000000000000176601354703061500203440ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include log_define("tntdb.postgresql.connection") namespace tntdb { namespace postgresql { Connection::Connection(const std::string& url_, const std::string& username, const std::string& password) : transactionActive(0), stmtCounter(0) { log_debug("PQconnectdb(\"" << url_ << "\")"); conn = PQconnectdb(url(url_, username, password).c_str()); if (conn == 0) throw std::bad_alloc(); if (PQstatus(conn) == CONNECTION_BAD ) throw PgConnError("PQconnectdb", conn); log_debug("connected to postgresql backend process " << PQbackendPID(conn)); } Connection::~Connection() { if (conn) { clearStatementCache(); currvalStmt = tntdb::Statement(); lastvalStmt = tntdb::Statement(); log_debug("PQfinish(" << conn << ")"); PQfinish(conn); } } void Connection::beginTransaction() { if (transactionActive == 0) execute("BEGIN"); ++transactionActive; } void Connection::commitTransaction() { if (transactionActive == 0 || --transactionActive == 0) { execute("COMMIT"); deallocateStatements(); } } void Connection::rollbackTransaction() { if (transactionActive == 0 || --transactionActive == 0) { execute("ROLLBACK"); deallocateStatements(); } } Connection::size_type Connection::execute(const std::string& query) { log_debug("execute(\"" << query << "\")"); log_debug("PQexec(" << conn << ", \"" << query << "\")"); PGresult* result = PQexec(conn, query.c_str()); if (isError(result)) { log_error(PQresultErrorMessage(result)); throw PgSqlError(query, "PQexec", result, true); } std::string t = PQcmdTuples(result); Connection::size_type ret = t.empty() ? 0 : cxxtools::convert(t); log_debug("PQclear(" << result << ')'); PQclear(result); return ret; } tntdb::Result Connection::select(const std::string& query) { log_debug("select(\"" << query << "\")"); log_debug("PQexec(" << conn << ", \"" << query << "\")"); PGresult* result = PQexec(conn, query.c_str()); if (isError(result)) { log_error(PQresultErrorMessage(result)); throw PgSqlError(query, "PQexec", result, true); } return tntdb::Result(new Result(tntdb::Connection(this), result)); } Row Connection::selectRow(const std::string& query) { log_debug("selectRow(\"" << query << "\")"); tntdb::Result result = select(query); if (result.empty()) throw NotFound(); return result.getRow(0); } Value Connection::selectValue(const std::string& query) { log_debug("selectValue(\"" << query << "\")"); Row t = selectRow(query); if (t.empty()) throw NotFound(); return t.getValue(0); } tntdb::Statement Connection::prepare(const std::string& query) { log_debug("prepare(\"" << query << "\")"); return tntdb::Statement(new Statement(this, query)); } tntdb::Statement Connection::prepareWithLimit(const std::string& query, const std::string& limit, const std::string& offset) { std::string q = query; if (!limit.empty()) { q += " limit :"; q += limit; } if (!offset.empty()) { q += " offset :"; q += offset; } return prepare(q); } bool Connection::ping() { log_debug("ping()"); if (PQsendQuery(conn, "select 1") == 0) { log_debug("failed to send statement \"select 1\" to database in Connection::ping()"); return false; } while (true) { struct pollfd fd; fd.fd = PQsocket(conn); fd.events = POLLIN; log_debug("wait for input on fd " << fd.fd); if (::poll(&fd, 1, 10000) != 1) { log_debug("no data received in Connection::ping()"); return false; } log_debug("consumeInput"); if (PQconsumeInput(conn) == 0) { log_debug("PQconsumeInput failed in Connection::ping()"); return false; } log_debug("check PQisBusy"); while (PQisBusy(conn) == 0) { log_debug("PQgetResult"); PGresult* result = PQgetResult(conn); log_debug("PQgetResult => " << static_cast(result)); if (result == 0) return true; log_debug("PQfree"); PQclear(result); } } } long Connection::lastInsertId(const std::string& name) { long ret = 0; if (name.empty()) { if (!lastvalStmt) lastvalStmt = prepare("select lastval()"); lastvalStmt .selectValue() .get(ret); } else { if (!currvalStmt) currvalStmt = prepare("select currval(:name)"); currvalStmt.set("name", name) .selectValue() .get(ret); } return ret; } void Connection::deallocateStatement(const std::string& stmtName) { // Delay deallocation since a postgresql fail to execute anything including // deallocate statements when a failed transaction is active. stmtsToDeallocate.push_back(stmtName); if (transactionActive == 0) deallocateStatements(); } void Connection::deallocateStatements() { for (std::vector::size_type n = 0; n < stmtsToDeallocate.size(); ++n) { std::string sql = "DEALLOCATE " + stmtsToDeallocate[n]; log_debug("PQexec(" << getPGConn() << ", \"" << sql << "\")"); PGresult* result = PQexec(getPGConn(), sql.c_str()); if (isError(result)) log_error("error deallocating statement: " << PQresultErrorMessage(result)); log_debug("PQclear(" << result << ')'); PQclear(result); } stmtsToDeallocate.clear(); } void Connection::lockTable(const std::string& tablename, bool exclusive) { std::string query = "LOCK TABLE "; query += tablename; query += exclusive ? " IN ACCESS EXCLUSIVE MODE" : " IN SHARE MODE"; tntdb::Statement lockStmt = prepare(query); lockStmt.execute(); } } } tntdb-1.4/src/postgresql/connectionmanager.cpp000066400000000000000000000034061354703061500216700ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include namespace tntdb { namespace postgresql { tntdb::Connection ConnectionManager::connect(const std::string& url, const std::string& username, const std::string& password) { return tntdb::Connection(new Connection(url, username, password)); } } } TNTDB_CONNECTIONMANAGER_DEFINE(postgresql) tntdb-1.4/src/postgresql/cursor.cpp000066400000000000000000000071011354703061500175070ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include log_define("tntdb.postgresql.cursor") namespace tntdb { namespace postgresql { Cursor::Cursor(Statement* statement, unsigned fetchSize_) : tntdbStmt(statement), stmt(statement), fetchSize(fetchSize_) { } Cursor::~Cursor() { if (!cursorName.empty()) { std::string sql = "CLOSE " + cursorName; log_debug("PQexec(" << getPGConn() << ", \"" << sql << "\")"); PGresult* result = PQexec(getPGConn(), sql.c_str()); if (isError(result)) log_error("error closing cursor: " << PQresultErrorMessage(result)); log_debug("PQclear(" << result << ')'); PQclear(result); } } Row Cursor::fetch() { if (cursorName.empty()) { // create cursorname std::ostringstream s; s << "tntdbcur" << this; std::string sql = "DECLARE " + s.str() + " CURSOR WITH HOLD FOR " + stmt->getQuery(); // declare cursor log_debug("PQexecParams(" << getPGConn() << ", \"" << sql << "\", " << stmt->getNParams() << ", 0, paramValues, paramLengths, 0, 0)"); PGresult* result = PQexecParams(getPGConn(), sql.c_str(), stmt->getNParams(), 0, stmt->getParamValues(), stmt->getParamLengths(), stmt->getParamFormats(), 0); if (isError(result)) { log_error(PQresultErrorMessage(result)); throw PgSqlError(sql, "PQexecParams", result, true); } log_debug("PQclear(" << result << ')'); PQclear(result); cursorName = s.str(); } if (!currentResult || currentRow >= currentResult.size()) { log_debug("fetch cursor"); std::ostringstream sql; sql << "FETCH " << fetchSize << " FROM " + cursorName; currentResult = stmt->getConnection()->select(sql.str()); log_debug(currentResult.size() << " rows fetched"); currentRow = 0; if (currentResult.empty()) return Row(); } return currentResult[currentRow++]; } } } tntdb-1.4/src/postgresql/error.cpp000066400000000000000000000103041354703061500173220ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include log_define("tntdb.postgresql.error") namespace tntdb { namespace postgresql { namespace { std::string errorMessage(const char* function, PGconn* conn) { std::ostringstream msg; msg << "Postgresql-Error in " << function << ": " << PQerrorMessage(conn); return msg.str(); } std::string errorMessage(PGconn* conn) { std::ostringstream msg; msg << "Postgresql-Error: " << PQerrorMessage(conn); return msg.str(); } std::string errorMessage(const char* function, const PGresult* res) { std::ostringstream msg; const char* sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE); const char* primary = PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY); const char* detail = PQresultErrorField(res, PG_DIAG_MESSAGE_DETAIL); const char* position = PQresultErrorField(res, PG_DIAG_STATEMENT_POSITION); msg << "Postgresql-Error " << sqlstate; if (primary) msg << ": " << primary; if (detail) msg << "; " << detail; if (position) msg << " at " << position; if (function) msg << " in " << function; return msg.str(); } std::string errorMessage(const PGresult* res) { return errorMessage(0, res); } } PgConnError::PgConnError(PGconn* conn) : Error(errorMessage(conn)) { } PgConnError::PgConnError(const char* function, PGconn* conn) : Error(errorMessage(function, conn)) { } PgConnError::PgConnError(PGresult* result, bool free) : Error(errorMessage(result)) { if (result && free) { log_debug("PQclear(" << result << ')'); PQclear(result); } } PgConnError::PgConnError(const char* function, PGresult* result, bool free) : Error(errorMessage(function, result)) { if (result && free) { log_debug("PQclear(" << result << ')'); PQclear(result); } } PgSqlError::PgSqlError(const std::string& sql, PGconn* conn) : SqlError(sql, errorMessage(conn)) { } PgSqlError::PgSqlError(const std::string& sql, const char* function, PGconn* conn) : SqlError(sql, errorMessage(function, conn)) { } PgSqlError::PgSqlError(const std::string& sql, PGresult* result, bool free) : SqlError(sql, errorMessage(result)) { if (result && free) { log_debug("PQclear(" << result << ')'); PQclear(result); } } PgSqlError::PgSqlError(const std::string& sql, const char* function, PGresult* result, bool free) : SqlError(sql, errorMessage(function, result)) { if (result && free) { log_debug("PQclear(" << result << ')'); PQclear(result); } } } } tntdb-1.4/src/postgresql/result.cpp000066400000000000000000000043671354703061500175230ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include log_define("tntdb.postgresql.result") namespace tntdb { namespace postgresql { Result::Result(const tntdb::Connection& c, PGresult* r) : conn(c), result(r) { log_debug("postgresql-result " << r); } Result::~Result() { if (result) { log_debug("PQclear(" << result << ')'); ::PQclear(result); } } Row Result::getRow(size_type tup_num) const { return Row(new ResultRow(const_cast(this), tup_num)); } Result::size_type Result::size() const { log_finest("PQntuples(" << result << ')'); return ::PQntuples(result); } Result::size_type Result::getFieldCount() const { log_debug("PQnfields(" << result << ')'); return ::PQnfields(result); } } } tntdb-1.4/src/postgresql/resultrow.cpp000066400000000000000000000050521354703061500202430ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include namespace tntdb { namespace postgresql { ResultRow::ResultRow(Result* result_, size_type rownumber_) : tntdbResult(result_), result(result_), rownumber(rownumber_) { } unsigned ResultRow::size() const { return result->getFieldCount(); } Value ResultRow::getValueByNumber(size_type field_num) const { return Value(new ResultValue(const_cast(this), field_num)); } Value ResultRow::getValueByName(const std::string& field_name) const { unsigned fc = result->getFieldCount(); unsigned n; for (n = 0; n < fc; ++n) if (field_name == PQfname(getPGresult(), n)) break; if (n == fc) throw FieldNotFound(field_name); return getValueByNumber(n); } std::string ResultRow::getColumnName(size_type field_num) const { return PQfname(getPGresult(), field_num); } PGresult* ResultRow::getPGresult() const { return result->getPGresult(); } } } tntdb-1.4/src/postgresql/resultvalue.cpp000066400000000000000000000171441354703061500205550ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include log_define("tntdb.postgresql.resultvalue") namespace tntdb { namespace postgresql { bool ResultValue::isNull() const { return PQgetisnull(getPGresult(), row->getRowNumber(), tup_num) != 0; } bool ResultValue::getBool() const { char* value = PQgetvalue(getPGresult(), row->getRowNumber(), tup_num); return value[0] == 't' || value[0] == 'T' || value[0] == 'y' || value[0] == 'Y' || value[0] == '1'; } short ResultValue::getShort() const { return cxxtools::convert(getString()); } int ResultValue::getInt() const { return cxxtools::convert(getString()); } long ResultValue::getLong() const { return cxxtools::convert(getString()); } unsigned short ResultValue::getUnsignedShort() const { return cxxtools::convert(getString()); } unsigned ResultValue::getUnsigned() const { return cxxtools::convert(getString()); } unsigned long ResultValue::getUnsignedLong() const { return cxxtools::convert(getString()); } int32_t ResultValue::getInt32() const { return cxxtools::convert(getString()); } uint32_t ResultValue::getUnsigned32() const { return cxxtools::convert(getString()); } int64_t ResultValue::getInt64() const { return cxxtools::convert(getString()); } uint64_t ResultValue::getUnsigned64() const { return cxxtools::convert(getString()); } Decimal ResultValue::getDecimal() const { return Decimal(getString()); } float ResultValue::getFloat() const { return cxxtools::convert(getString()); } double ResultValue::getDouble() const { return cxxtools::convert(getString()); } char ResultValue::getChar() const { char* value = PQgetvalue(getPGresult(), row->getRowNumber(), tup_num); return *value; } void ResultValue::getString(std::string& ret) const { if (PQgetisnull(getPGresult(), row->getRowNumber(), tup_num)) throw NullValue(); char* value = PQgetvalue(getPGresult(), row->getRowNumber(), tup_num); int len = PQgetlength(getPGresult(), row->getRowNumber(), tup_num); ret.assign(value, len); } void ResultValue::getBlob(Blob& ret) const { char* value = PQgetvalue(getPGresult(), row->getRowNumber(), tup_num); int len = PQgetlength(getPGresult(), row->getRowNumber(), tup_num); log_debug("PQgetlength returns " << len); size_t to_len; unsigned char* data = PQunescapeBytea(reinterpret_cast(value), &to_len); ret.assign(reinterpret_cast(data), to_len); PQfreemem(data); } Date ResultValue::getDate() const { std::string value = PQgetvalue(getPGresult(), row->getRowNumber(), tup_num); if (value.find('-') != std::string::npos) { // ISO 8601/SQL standard char ch; unsigned short year, month, day; std::istringstream in(value); in >> year >> ch >> month >> ch >> day; if (in) return Date(year, month, day); } else if (value.find('/') != std::string::npos) { // tradition style char ch; unsigned short year, month, day; std::istringstream in(value); in >> month >> ch >> day >> ch >> year; if (in) return Date(year, month, day); } else if (value.find('.') != std::string::npos) { // german/regional style char ch; unsigned short year, month, day; std::istringstream in(value); in >> day >> ch >> month >> ch >> year; if (in) return Date(year, month, day); } std::ostringstream msg; msg << "can't convert \"" << value << "\" to Date"; throw TypeError(msg.str()); } Time ResultValue::getTime() const { std::string value = PQgetvalue(getPGresult(), row->getRowNumber(), tup_num); char ch; unsigned short hour, min, sec, msec; float fsec; std::istringstream in(value); in >> hour >> ch >> min >> ch >> fsec; if (in) { fsec += .0005; sec = static_cast(fsec); msec = static_cast((fsec - sec) * 1000); return Time(hour, min, sec, msec); } std::ostringstream msg; msg << "can't convert \"" << value << "\" to Time"; throw TypeError(msg.str()); } Datetime ResultValue::getDatetime() const { std::string value = PQgetvalue(getPGresult(), row->getRowNumber(), tup_num); log_debug("datetime value=" << value); if (value.find('-') != std::string::npos) { // ISO 8601/SQL standard char ch; unsigned short year, month, day, hour, min, sec, msec; float fsec; std::istringstream in(value); in >> year >> ch >> month >> ch >> day >> hour >> ch >> min >> ch >> fsec; if (in) { fsec += .0005; sec = static_cast(fsec); msec = static_cast((fsec - sec) * 1000); return Datetime(year, month, day, hour, min, sec, msec); } } else if (value.find('/') != std::string::npos) { // traditional style char ch; unsigned short year, month, day, hour, min, sec; std::istringstream in(value); in >> month >> ch >> day >> ch >> year >> hour >> ch >> min >> ch >> sec; if (in) return Datetime(year, month, day, hour, min, sec); } else if (value.find('.') != std::string::npos) { // german/regional style char ch; unsigned short year, month, day, hour, min, sec; std::istringstream in(value); in >> day >> ch >> month >> ch >> year >> hour >> ch >> min >> ch >> sec; if (in) return Datetime(year, month, day, hour, min, sec); } std::ostringstream msg; msg << "can't convert \"" << value << "\" to Datetime"; throw TypeError(msg.str()); } } } tntdb-1.4/src/postgresql/statement.cpp000066400000000000000000000353031354703061500202030ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" log_define("tntdb.postgresql.statement") #ifdef HAVE_PQPREPARE # define SET_TYPE(pos, type) #else # define SET_TYPE(pos, type) setType(pos, type) #endif namespace tntdb { namespace postgresql { typedef std::map hostvarMapType; namespace { class SE : public StmtEvent { hostvarMapType& hostvarMap; unsigned idx; public: SE(hostvarMapType& hm) : hostvarMap(hm), idx(0) { } std::string onHostVar(const std::string& name); unsigned getMaxIdx() const { return idx; } }; std::string SE::onHostVar(const std::string& name) { unsigned n; hostvarMapType::const_iterator it = hostvarMap.find(name); if (it == hostvarMap.end()) { n = idx++; hostvarMap[name] = n; } else n = it->second; log_debug("hostvar :" << name << " => $" << (n + 1)); std::ostringstream r; r << '$' << (n + 1); return r.str(); } } Statement::Statement(Connection* conn_, const std::string& query_) : conn(conn_) { // parse hostvars StmtParser parser; SE se(hostvarMap); parser.parse(query_, se); values.resize(se.getMaxIdx()); query = parser.getSql(); paramValues.resize(se.getMaxIdx()); paramLengths.resize(se.getMaxIdx()); paramFormats.resize(se.getMaxIdx()); } Statement::~Statement() { if (!stmtName.empty()) conn->deallocateStatement(stmtName); } void Statement::doPrepare() { // create statementname std::ostringstream s; s << "tntdbstmt" << conn->getNextStmtNumber(); // prepare statement #ifdef HAVE_PQPREPARE log_debug("PQprepare(" << getPGConn() << ", \"" << s.str() << "\", \"" << query << "\", 0, 0)"); PGresult* result = PQprepare(getPGConn(), s.str().c_str(), query.c_str(), 0, 0); if (isError(result)) { log_error(PQresultErrorMessage(result)); throw PgSqlError(query, "PQprepare", result, true); } #else std::ostringstream sql; sql << "PREPARE " << s.str(); for (valuesType::const_iterator it = values.begin(); it != values.end(); ++it) sql << (it == values.begin() ? " (" : ", " ) << it->getType(); if (!values.empty()) sql << ')'; sql << " AS " << query; log_debug("PQexec(" << getPGConn() << ", \"" << sql.str() << "\")"); PGresult* result = PQexec(getPGConn(), sql.str().c_str()); if (isError(result)) { log_error(PQresultErrorMessage(result)); throw PgSqlError(sql.str(), "PQexec", result, true); } #endif stmtName = s.str(); log_debug("PQclear(" << result << ')'); PQclear(result); } PGresult* Statement::execPrepared() { if (stmtName.empty()) doPrepare(); log_debug("PQexecPrepared(" << getPGConn() << ", \"" << stmtName << "\", " << values.size() << ", paramValues, paramLengths, paramFormats, 0)"); PGresult* result = PQexecPrepared(getPGConn(), stmtName.c_str(), getNParams(), getParamValues(), getParamLengths(), getParamFormats(), 0); if (isError(result)) { log_error(PQresultErrorMessage(result)); throw PgSqlError(query, "PQexecPrepared", result, true); } return result; } template void Statement::setValue(const std::string& col, T data) { hostvarMapType::const_iterator it = hostvarMap.find(col); if (it == hostvarMap.end()) log_warn("hostvariable :" << col << " not found"); else { std::string v = cxxtools::convert(data); values[it->second].setValue(v); paramFormats[it->second] = 0; } } template <> void Statement::setValue(const std::string& col, float data) { hostvarMapType::const_iterator it = hostvarMap.find(col); if (it == hostvarMap.end()) log_warn("hostvariable :" << col << " not found"); else { std::ostringstream v; v.precision(24); v << data; values[it->second].setValue(v.str()); paramFormats[it->second] = 0; } } template <> void Statement::setValue(const std::string& col, double data) { hostvarMapType::const_iterator it = hostvarMap.find(col); if (it == hostvarMap.end()) log_warn("hostvariable :" << col << " not found"); else { std::ostringstream v; v.precision(24); v << data; values[it->second].setValue(v.str()); paramFormats[it->second] = 0; } } template <> void Statement::setValue(const std::string& col, Decimal data) { hostvarMapType::const_iterator it = hostvarMap.find(col); if (it == hostvarMap.end()) log_warn("hostvariable :" << col << " not found"); else { std::ostringstream v; v.precision(24); v << data; values[it->second].setValue(v.str()); paramFormats[it->second] = 0; } } template void Statement::setStringValue(const std::string& col, T data, bool binary) { hostvarMapType::const_iterator it = hostvarMap.find(col); if (it == hostvarMap.end()) log_warn("hostvariable :" << col << " not found"); else { values[it->second].setValue(data); paramFormats[it->second] = binary; } } template void Statement::setIsoValue(const std::string& col, T data) { hostvarMapType::const_iterator it = hostvarMap.find(col); if (it == hostvarMap.end()) log_warn("hostvariable :" << col << " not found"); else { values[it->second].setValue(data.getIso()); paramFormats[it->second] = 0; } } #ifndef HAVE_PQPREPARE void Statement::setType(const std::string& col, const std::string& type) { hostvarMapType::const_iterator it = hostvarMap.find(col); if (it != hostvarMap.end()) values[it->second].setType(type); } #endif void Statement::clear() { log_debug("clear()"); for (valuesType::iterator it = values.begin(); it != values.end(); ++it) it->setNull(); } void Statement::setNull(const std::string& col) { log_debug("setNull(\"" << col << "\")"); hostvarMapType::const_iterator it = hostvarMap.find(col); if (it == hostvarMap.end()) log_warn("hostvariable :" << col << " not found"); else { values[it->second].setNull(); paramFormats[it->second] = 0; } } void Statement::setBool(const std::string& col, bool data) { log_debug("setBool(\"" << col << "\", " << data << ')'); hostvarMapType::const_iterator it = hostvarMap.find(col); if (it == hostvarMap.end()) log_warn("hostvariable :" << col << " not found"); else { values[it->second].setValue(data ? "1" : "0"); paramFormats[it->second] = 0; } SET_TYPE(col, "bool"); } void Statement::setShort(const std::string& col, short data) { log_debug("setShort(\"" << col << "\", " << data << ')'); setValue(col, data); SET_TYPE(col, "short"); } void Statement::setInt(const std::string& col, int data) { log_debug("setInt(\"" << col << "\", " << data << ')'); setValue(col, data); SET_TYPE(col, "int"); } void Statement::setLong(const std::string& col, long data) { log_debug("setLong(\"" << col << "\", " << data << ')'); setValue(col, data); SET_TYPE(col, "long"); } void Statement::setUnsignedShort(const std::string& col, unsigned short data) { log_debug("setUnsignedShort(\"" << col << "\", " << data << ')'); setValue(col, data); SET_TYPE(col, "unsigned short"); } void Statement::setUnsigned(const std::string& col, unsigned data) { log_debug("setUnsigned(\"" << col << "\", " << data << ')'); setValue(col, data); SET_TYPE(col, "unsigned"); } void Statement::setUnsignedLong(const std::string& col, unsigned long data) { log_debug("setUnsignedLong(\"" << col << "\", " << data << ')'); setValue(col, data); SET_TYPE(col, "unsigned long"); } void Statement::setInt32(const std::string& col, int32_t data) { log_debug("setInt32(\"" << col << "\", " << data << ')'); setValue(col, data); SET_TYPE(col, "int"); } void Statement::setUnsigned32(const std::string& col, uint32_t data) { log_debug("setUnsigned32(\"" << col << "\", " << data << ')'); setValue(col, data); SET_TYPE(col, "int"); } void Statement::setInt64(const std::string& col, int64_t data) { log_debug("setInt64(\"" << col << "\", " << data << ')'); setValue(col, data); SET_TYPE(col, "bigint"); } void Statement::setUnsigned64(const std::string& col, uint64_t data) { log_debug("setUnsigned64(\"" << col << "\", " << data << ')'); setValue(col, data); SET_TYPE(col, "bigint"); } void Statement::setDecimal(const std::string& col, const Decimal& data) { log_debug("setDecimal(\"" << col << "\", " << data << ')'); setValue(col, data); SET_TYPE(col, "numeric"); } void Statement::setFloat(const std::string& col, float data) { log_debug("setFloat(\"" << col << "\", " << data << ')'); if (data != data) setValue(col, "NaN"); else if (data == std::numeric_limits::infinity()) setValue(col, "Infinity"); else if (data == -std::numeric_limits::infinity()) setValue(col, "-Infinity"); else setValue(col, data); SET_TYPE(col, "numeric"); } void Statement::setDouble(const std::string& col, double data) { log_debug("setDouble(\"" << col << "\", " << data << ')'); if (data != data) setValue(col, "NaN"); else if (data == std::numeric_limits::infinity()) setValue(col, "Infinity"); else if (data == -std::numeric_limits::infinity()) setValue(col, "-Infinity"); else setValue(col, data); SET_TYPE(col, "numeric"); } void Statement::setChar(const std::string& col, char data) { log_debug("setChar(\"" << col << "\", '" << data << "')"); setStringValue(col, std::string(1, data)); SET_TYPE(col, "text"); } void Statement::setString(const std::string& col, const std::string& data) { log_debug("setString(\"" << col << "\", \"" << data << "\")"); setStringValue(col, data); SET_TYPE(col, "text"); } void Statement::setBlob(const std::string& col, const Blob& data) { log_debug("setBlob(\"" << col << "\", Blob)"); setStringValue(col, std::string(data.data(), data.size()), true); SET_TYPE(col, "blob"); } void Statement::setDate(const std::string& col, const Date& data) { log_debug("setDate(\"" << col << "\", " << data.getIso() << ')'); setIsoValue(col, data); SET_TYPE(col, "date"); } void Statement::setTime(const std::string& col, const Time& data) { log_debug("setTime(\"" << col << "\", " << data.getIso() << ')'); setIsoValue(col, data); SET_TYPE(col, "time"); } void Statement::setDatetime(const std::string& col, const Datetime& data) { log_debug("setDatetime(\"" << col << "\", " << data.getIso() << ')'); setIsoValue(col, data); SET_TYPE(col, "datetime"); } Statement::size_type Statement::execute() { log_debug("execute()"); PGresult* result = execPrepared(); std::istringstream tuples(PQcmdTuples(result)); unsigned ret = 0; tuples >> ret; log_debug("PQclear(" << result << ')'); PQclear(result); return ret; } tntdb::Result Statement::select() { log_debug("select()"); PGresult* result = execPrepared(); return tntdb::Result(new Result(tntdb::Connection(conn), result)); } tntdb::Row Statement::selectRow() { tntdb::Result result = select(); if (result.size() <= 0) throw NotFound(); return result[0]; } tntdb::Value Statement::selectValue() { tntdb::Result result = select(); if (result.size() <= 0) throw NotFound(); return result[0][0]; } ICursor* Statement::createCursor(unsigned fetchsize) { return new Cursor(this, fetchsize); } const char* const* Statement::getParamValues() { for (unsigned n = 0; n < values.size(); ++n) paramValues[n] = values[n].getValue(); return ¶mValues[0]; } const int* Statement::getParamLengths() { for (unsigned n = 0; n < values.size(); ++n) paramLengths[n] = values[n].getLength(); return ¶mLengths[0]; } PGconn* Statement::getPGConn() { return conn->getPGConn(); } } } tntdb-1.4/src/replicate/000077500000000000000000000000001354703061500152345ustar00rootroot00000000000000tntdb-1.4/src/replicate/Makefile.am000066400000000000000000000006521354703061500172730ustar00rootroot00000000000000AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include sources = connection.cpp connectionmanager.cpp statement.cpp if MAKE_REPLICATE driver_LTLIBRARIES = tntdb@abi_current@-replicate.la tntdb@abi_current@_replicate_la_SOURCES = $(sources) tntdb@abi_current@_replicate_la_LDFLAGS = -module -version-info @sonumber@ @SHARED_LIB_FLAG@ tntdb@abi_current@_replicate_la_LIBADD = $(top_builddir)/src/libtntdb.la endif tntdb-1.4/src/replicate/connection.cpp000066400000000000000000000121321354703061500200760ustar00rootroot00000000000000/* * Copyright (C) 2011 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include log_define("tntdb.replicate.connection") namespace tntdb { namespace replicate { Connection::Connection(const std::string& url, const std::string& username, const std::string& password) { const char* conninfo = url.c_str(); const char* b = conninfo; const char* e = conninfo; std::vector urls; while (*e) { if (*e == '|') { urls.push_back(std::string(b, e)); b = e+1; } ++e; } urls.push_back(std::string(b, e)); std::string primaryUrl = urls[0]; std::sort(urls.begin(), urls.end()); for (std::vector::const_iterator it = urls.begin(); it != urls.end(); ++it) { log_debug("connect to " << *it); connections.push_back(connect(*it, username, password)); if (!primaryConnection && *it == primaryUrl) { log_debug("primary connection " << *it); primaryConnection = connections.back(); } } log_debug(connections.size() << " connections"); } Connection::~Connection() { clearStatementCache(); } void Connection::beginTransaction() { for (Connections::iterator it = connections.begin(); it != connections.end(); ++it) it->beginTransaction(); } void Connection::commitTransaction() { for (Connections::iterator it = connections.begin(); it != connections.end(); ++it) it->commitTransaction(); } void Connection::rollbackTransaction() { for (Connections::iterator it = connections.begin(); it != connections.end(); ++it) it->rollbackTransaction(); } Connection::size_type Connection::execute(const std::string& query) { tntdb::Connection c(this); Transaction transaction(c); size_type ret = connections[0].execute(query); for (Connections::size_type n = 1; n < connections.size(); ++n) { try { connections[n].execute(query); } catch (const tntdb::Error& e) { std::ostringstream msg; msg << "replication failed on " << (n + 1) << ". connection: " << e.what(); throw tntdb::Error(msg.str()); } } transaction.commit(); return ret; } tntdb::Result Connection::select(const std::string& query) { return connections.begin()->select(query); } tntdb::Row Connection::selectRow(const std::string& query) { return connections.begin()->selectRow(query); } tntdb::Value Connection::selectValue(const std::string& query) { return connections.begin()->selectValue(query); } tntdb::Statement Connection::prepare(const std::string& query) { return tntdb::Statement(new Statement(this, query)); } tntdb::Statement Connection::prepareWithLimit(const std::string& query, const std::string& limit, const std::string& offset) { return tntdb::Statement(new Statement(this, query, limit, offset)); } bool Connection::ping() { for (Connections::iterator it = connections.begin(); it != connections.end(); ++it) if (!it->ping()) return false; return true; } long Connection::lastInsertId(const std::string& name) { return connections.begin()->lastInsertId(name); } void Connection::lockTable(const std::string& tablename, bool exclusive) { connections.begin()->getImpl()->lockTable(tablename, exclusive); } } } tntdb-1.4/src/replicate/connectionmanager.cpp000066400000000000000000000033701354703061500214350ustar00rootroot00000000000000/* * Copyright (C) 2011 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include namespace tntdb { namespace replicate { tntdb::Connection ConnectionManager::connect(const std::string& url, const std::string& username, const std::string& password) { return tntdb::Connection(new Connection(url, username, password)); } } } TNTDB_CONNECTIONMANAGER_DEFINE(replicate) tntdb-1.4/src/replicate/statement.cpp000066400000000000000000000201451354703061500177460ustar00rootroot00000000000000/* * Copyright (C) 2011 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include log_define("tntdb.replicate.statement") namespace tntdb { namespace replicate { Statement::Statement(Connection* conn_, const std::string& query, const std::string& limit, const std::string& offset) : conn(conn_) { // check if it a select statement // a select statement need to be prepared only on the first connection // skip white space first const char* p = query.c_str(); while (*p && (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r')) ++p; if (strncasecmp(p, "select", 6) == 0) { log_debug("select statement detected - prepare on first connection only"); if (limit.empty() && offset.empty()) statements.push_back(conn->connections.begin()->prepare(query)); else statements.push_back(conn->connections.begin()->prepareWithLimit(query, limit, offset)); } else { log_debug("non-select statement detected - prepare on all " << conn->connections.size() << " connections"); for (Connection::Connections::iterator it = conn->connections.begin(); it != conn->connections.end(); ++it) statements.push_back(it->prepare(query)); } } void Statement::clear() { for (Statements::iterator it = statements.begin(); it != statements.end(); ++it) it->clear(); } void Statement::setNull(const std::string& col) { for (Statements::iterator it = statements.begin(); it != statements.end(); ++it) it->setNull(col); } void Statement::setBool(const std::string& col, bool data) { for (Statements::iterator it = statements.begin(); it != statements.end(); ++it) it->setBool(col, data); } void Statement::setShort(const std::string& col, short data) { for (Statements::iterator it = statements.begin(); it != statements.end(); ++it) it->setShort(col, data); } void Statement::setInt(const std::string& col, int data) { for (Statements::iterator it = statements.begin(); it != statements.end(); ++it) it->setInt(col, data); } void Statement::setLong(const std::string& col, long data) { for (Statements::iterator it = statements.begin(); it != statements.end(); ++it) it->setLong(col, data); } void Statement::setUnsignedShort(const std::string& col, unsigned short data) { for (Statements::iterator it = statements.begin(); it != statements.end(); ++it) it->setUnsignedShort(col, data); } void Statement::setUnsigned(const std::string& col, unsigned data) { for (Statements::iterator it = statements.begin(); it != statements.end(); ++it) it->setUnsigned(col, data); } void Statement::setUnsignedLong(const std::string& col, unsigned long data) { for (Statements::iterator it = statements.begin(); it != statements.end(); ++it) it->setUnsignedLong(col, data); } void Statement::setInt32(const std::string& col, int32_t data) { for (Statements::iterator it = statements.begin(); it != statements.end(); ++it) it->setInt32(col, data); } void Statement::setUnsigned32(const std::string& col, uint32_t data) { for (Statements::iterator it = statements.begin(); it != statements.end(); ++it) it->setUnsigned32(col, data); } void Statement::setInt64(const std::string& col, int64_t data) { for (Statements::iterator it = statements.begin(); it != statements.end(); ++it) it->setInt64(col, data); } void Statement::setUnsigned64(const std::string& col, uint64_t data) { for (Statements::iterator it = statements.begin(); it != statements.end(); ++it) it->setUnsigned64(col, data); } void Statement::setDecimal(const std::string& col, const Decimal& data) { for (Statements::iterator it = statements.begin(); it != statements.end(); ++it) it->setDecimal(col, data); } void Statement::setFloat(const std::string& col, float data) { for (Statements::iterator it = statements.begin(); it != statements.end(); ++it) it->setFloat(col, data); } void Statement::setDouble(const std::string& col, double data) { for (Statements::iterator it = statements.begin(); it != statements.end(); ++it) it->setDouble(col, data); } void Statement::setChar(const std::string& col, char data) { for (Statements::iterator it = statements.begin(); it != statements.end(); ++it) it->setChar(col, data); } void Statement::setString(const std::string& col, const std::string& data) { for (Statements::iterator it = statements.begin(); it != statements.end(); ++it) it->setString(col, data); } void Statement::setBlob(const std::string& col, const Blob& data) { for (Statements::iterator it = statements.begin(); it != statements.end(); ++it) it->setBlob(col, data); } void Statement::setDate(const std::string& col, const Date& data) { for (Statements::iterator it = statements.begin(); it != statements.end(); ++it) it->setDate(col, data); } void Statement::setTime(const std::string& col, const Time& data) { for (Statements::iterator it = statements.begin(); it != statements.end(); ++it) it->setTime(col, data); } void Statement::setDatetime(const std::string& col, const Datetime& data) { for (Statements::iterator it = statements.begin(); it != statements.end(); ++it) it->setDatetime(col, data); } Statement::size_type Statement::execute() { tntdb::Connection c(conn); Transaction transaction(c); Statement::size_type ret = statements[0].execute(); for (Statements::size_type n = 1; n < statements.size(); ++n) { try { statements[n].execute(); } catch (const tntdb::Error& e) { std::ostringstream msg; msg << "replication failed on " << (n + 1) << ". connection: " << e.what(); throw tntdb::Error(msg.str()); } } transaction.commit(); return ret; } tntdb::Result Statement::select() { return statements.begin()->select(); } tntdb::Row Statement::selectRow() { return statements.begin()->selectRow(); } tntdb::Value Statement::selectValue() { return statements.begin()->selectValue(); } ICursor* Statement::createCursor(unsigned fetchsize) { return statements.begin()->getImpl()->createCursor(fetchsize); } } } tntdb-1.4/src/result.cpp000066400000000000000000000040671354703061500153150ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include log_define("tntdb.result") namespace tntdb { Row Result::getRow(size_type tup_num) const { return result->getRow(tup_num); } Value Result::getValue(size_type tup_num, size_type field_num) const { return getRow(tup_num).getValue(field_num); } Row Result::operator[] (size_type row_num) const { return getRow(row_num); } Result::const_iterator Result::begin() const { log_debug("Result::begin()"); return const_iterator(*this, 0); } Result::const_iterator Result::end() const { size_type s = size(); log_debug("Result::end(), size=" << s); return const_iterator(*this, s); } } tntdb-1.4/src/resultimpl.cpp000066400000000000000000000032651354703061500161760ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include namespace tntdb { Row ResultImpl::getRow(size_type tup_num) const { return data[tup_num]; } ResultImpl::size_type ResultImpl::size() const { return data.size(); } ResultImpl::size_type ResultImpl::getFieldCount() const { return data.empty() ? 0 : data.begin()->size(); } } tntdb-1.4/src/row.cpp000066400000000000000000000031241354703061500145770ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include namespace tntdb { Row::const_iterator Row::begin() const { return const_iterator(*this, 0); } Row::const_iterator Row::end() const { return const_iterator(*this, size()); } } tntdb-1.4/src/rowimpl.cpp000066400000000000000000000040331354703061500154610ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include namespace tntdb { RowImpl::size_type RowImpl::size() const { return data.size(); } Value RowImpl::getValueByNumber(size_type field_num) const { return data[field_num].value; } Value RowImpl::getValueByName(const std::string& field_name) const { data_type::const_iterator it; for (it = data.begin(); it != data.end(); ++it) if (it->name == field_name) break; if (it == data.end()) throw FieldNotFound(field_name); return it->value; } std::string RowImpl::getColumnName(size_type field_num) const { return data[field_num].name; } } tntdb-1.4/src/serialization.cpp000066400000000000000000000103051354703061500166440ustar00rootroot00000000000000/* * Copyright (C) 2015 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include namespace tntdb { void operator<<= (cxxtools::SerializationInfo& si, const tntdb::Value& value) { si.setTypeName("dbValue"); std::string s; if (value.get(s)) si <<= value; else si.setNull(); } void operator<<= (cxxtools::SerializationInfo& si, const tntdb::Row& row) { si.setTypeName("dbRow"); for (unsigned n = 0; n < row.size(); ++n) { cxxtools::SerializationInfo& vsi = si.addMember(row.getName(n)); // leave the new member NULL if the value is null std::string value; if (row[n].get(value)) vsi <<= value; } } void operator<<= (cxxtools::SerializationInfo& si, const tntdb::Result& res) { si.setTypeName("dbResult"); si.setCategory(cxxtools::SerializationInfo::Array); for (auto cur: res) si.addMember() <<= cur; } void operator<<= (cxxtools::SerializationInfo& si, const tntdb::Statement& res) { si.setTypeName("dbResult"); si.setCategory(cxxtools::SerializationInfo::Array); for (auto cur: res) si.addMember() <<= cur; } void operator>>= (const cxxtools::SerializationInfo& si, Statement& stmt) { for (cxxtools::SerializationInfo::const_iterator it = si.begin(); it != si.end(); ++it) { if (it->isNull()) { stmt.setNull(it->name()); } else if (it->isString8()) { std::string value; it->getValue(value); stmt.set(it->name(), value); } else if (it->isChar()) { char value; it->getValue(value); stmt.set(it->name(), value); } else if (it->isBool()) { bool value; it->getValue(value); stmt.set(it->name(), value); } else if (it->isInt()) { long value; it->getValue(value); stmt.set(it->name(), value); } else if (it->isUInt()) { unsigned long value; it->getValue(value); stmt.set(it->name(), value); } else if (it->isFloat()) { double value; it->getValue(value); stmt.set(it->name(), value); } else { cxxtools::String value; it->getValue(value); stmt.set(it->name(), value); } } } } tntdb-1.4/src/sqlbuilder.cpp000066400000000000000000000062461354703061500161460ustar00rootroot00000000000000/* * Copyright (C) 2011 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include namespace tntdb { namespace { class HvarListReplacer : public StmtEvent { std::string varname; unsigned count; public: HvarListReplacer(const std::string& varname_, unsigned count_) : varname(varname_), count(count_) { } virtual std::string onHostVar(const std::string& name); }; std::string HvarListReplacer::onHostVar(const std::string& name) { if (name != varname) return '%' + name; if (count == 0) return " NULL "; std::string ret; ret.reserve(2 + (5 + varname.size()) * count); ret = ' '; for (unsigned n = 0; n < count; ++n) { if (n != 0) ret += ','; ret += ':'; ret += varname; ret += cxxtools::convert(n); } ret += ' '; return ret; } class SimpleReplacer : public StmtEvent { std::string varname; std::string value; public: SimpleReplacer(const std::string& varname_, const std::string& value_) : varname(varname_), value(value_) { } virtual std::string onHostVar(const std::string& name); }; std::string SimpleReplacer::onHostVar(const std::string& name) { return name == varname ? value : '%' + name; } } SqlBuilder& SqlBuilder::extendParam(const std::string& varname, unsigned count) { StmtParser p('%'); HvarListReplacer r(varname, count); p.parse(sql, r); sql = p.getSql(); return *this; } SqlBuilder& SqlBuilder::replace(const std::string& varname, const std::string& value) { StmtParser p('%'); SimpleReplacer r(varname, value); p.parse(sql, r); sql = p.getSql(); return *this; } } tntdb-1.4/src/sqlite/000077500000000000000000000000001354703061500145655ustar00rootroot00000000000000tntdb-1.4/src/sqlite/Makefile.am000066400000000000000000000007241354703061500166240ustar00rootroot00000000000000AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include sources = connection.cpp connectionmanager.cpp cursor.cpp error.cpp statement.cpp stmtvalue.cpp stmtrow.cpp if MAKE_SQLITE driver_LTLIBRARIES = tntdb@abi_current@-sqlite.la tntdb@abi_current@_sqlite_la_SOURCES = $(sources) tntdb@abi_current@_sqlite_la_LDFLAGS = -module -version-info @sonumber@ -lsqlite3 @SHARED_LIB_FLAG@ tntdb@abi_current@_sqlite_la_LIBADD = $(top_builddir)/src/libtntdb.la endif tntdb-1.4/src/sqlite/connection.cpp000066400000000000000000000123231354703061500174310ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include log_define("tntdb.sqlite.connection") namespace tntdb { namespace sqlite { Connection::Connection(const char* conninfo) : transactionActive(0) { log_debug("sqlite3_open(\"" << conninfo << "\")"); int errcode = ::sqlite3_open(conninfo, &db); if (db == 0) throw Execerror("sqlite3_open", db, errcode); log_debug("sqlite3 = " << db); log_debug("sqlite3_busy_timeout(\"" << db << "\", 60000)"); errcode = ::sqlite3_busy_timeout(db, 60000); if (errcode != SQLITE_OK) throw Execerror("sqlite3_busy_timeout", db, errcode); } Connection::~Connection() { if (db) { clearStatementCache(); log_debug("sqlite3_close(" << db << ")"); ::sqlite3_close(db); } } void Connection::beginTransaction() { if (transactionActive == 0) execute("BEGIN IMMEDIATE TRANSACTION"); ++transactionActive; } void Connection::commitTransaction() { if (transactionActive == 0 || --transactionActive == 0) { // Statement handles are invalidated at transaction end, therefore we // release all cached statements here. // The problem still remains since the application might preserve a // statement handle, which can't be released here. clearStatementCache(); execute("COMMIT TRANSACTION"); } } void Connection::rollbackTransaction() { if (transactionActive == 0 || --transactionActive == 0) { // Statement handles are invalidated at transaction end, therefore we // release all cached statements here. // The problem still remains since the application might preserve a // statement handle, which can't be released here. clearStatementCache(); execute("ROLLBACK TRANSACTION"); } } Connection::size_type Connection::execute(const std::string& query) { char* errmsg; log_debug("sqlite3_exec(" << db << ", \"" << query << "\", 0, 0, " << &errmsg << ')'); int ret = ::sqlite3_exec(db, query.c_str(), 0, 0, &errmsg); log_debug("sqlite3_exec ret=" << ret); if (ret != SQLITE_OK) throw Execerror("sqlite3_exec", ret, errmsg, true); return ::sqlite3_changes(db); } tntdb::Result Connection::select(const std::string& query) { return prepare(query).select(); } tntdb::Row Connection::selectRow(const std::string& query) { return prepare(query).selectRow(); } tntdb::Value Connection::selectValue(const std::string& query) { return prepare(query).selectValue(); } tntdb::Statement Connection::prepare(const std::string& query) { log_debug("prepare(\"" << query << "\")"); return tntdb::Statement(new Statement(this, query)); } tntdb::Statement Connection::prepareWithLimit(const std::string& query, const std::string& limit, const std::string& offset) { std::string q = query; if (!limit.empty()) { q += " limit :"; q += limit; } if (!offset.empty()) { q += " offset :"; q += offset; } return prepare(q); } bool Connection::ping() { return db != 0; } long Connection::lastInsertId(const std::string& name) { return static_cast(sqlite3_last_insert_rowid(db)); } void Connection::lockTable(const std::string& tablename, bool exclusive) { // nothing to do - the database is locked by the exclusive transaction // already } } } tntdb-1.4/src/sqlite/connectionmanager.cpp000066400000000000000000000033621354703061500207670ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include namespace tntdb { namespace sqlite { tntdb::Connection ConnectionManager::connect(const std::string& url, const std::string& /*username*/, const std::string& /*password*/) { return tntdb::Connection(new Connection(url.c_str())); } } } TNTDB_CONNECTIONMANAGER_DEFINE(sqlite) tntdb-1.4/src/sqlite/cursor.cpp000066400000000000000000000040541354703061500166110ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include log_define("tntdb.sqlite.cursor") namespace tntdb { namespace sqlite { Cursor::Cursor(Statement* statement_, sqlite3_stmt* stmt_) : statement(statement_), stmt(stmt_) { } Cursor::~Cursor() { statement->putback(stmt); } Row Cursor::fetch() { log_debug("sqlite3_step(" << stmt << ')'); int ret = ::sqlite3_step(stmt); if (ret == SQLITE_DONE) return Row(); else if (ret != SQLITE_ROW) throw Execerror("sqlite3_step", stmt, ret); return Row(new StmtRow(getStmt())); } } } tntdb-1.4/src/sqlite/error.cpp000066400000000000000000000044131354703061500164240ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include namespace tntdb { namespace sqlite { SqliteError::SqliteError(const char* function, char* errmsg, bool do_free) : Error(std::string(function) + ": " + (errmsg ? errmsg : "unknown error")) { if (errmsg && do_free) // I would like to use a autoconf here, but sqlite3_malloc/sqlite3_free did // exist prior version 3.5 but was not used, so a configure-check is difficult. // (at least I have no idea how to do it) #if SQLITE_VERSION_NUMBER >= 3005000 sqlite3_free(errmsg); #else std::free(errmsg); #endif } Execerror::Execerror(const char* function, sqlite3* db, int _errcode) : SqliteError(function, sqlite3_errmsg(db)), errcode(_errcode) { } Execerror::Execerror(const char* function, sqlite3_stmt* stmt, int _errcode) : SqliteError(function, sqlite3_errmsg(sqlite3_db_handle(stmt))), errcode(_errcode) { } } } tntdb-1.4/src/sqlite/nvstatement.cpp000066400000000000000000000074611354703061500176510ustar00rootroot00000000000000/* * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ //////////////////////////////////////////////////////////////////////// // sqlite/nvstatement.cpp // #include #include namespace tntdb { namespace sqlite { void Nvstatement::processHValue(std::string& ret, const std::string& name) const { values_type::const_iterator v = values.find(name); if (v != values.end()) { if (v->second.isNull()) { ret += "NULL"; } else { ret += '\''; const std::string& val = v->second.getString(); for (std::string::const_iterator it = val.begin(); it != val.end(); ++it) if (*it == '\'') ret += "''"; else ret += *it; ret += '\''; } } else { ret += ':'; ret += name; } } std::string Nvstatement::getSql() const { enum state_type { STATE_0, STATE_NAME0, STATE_NAME, STATE_ESC } state = STATE_0; std::string ret; std::string name; for (std::string::const_iterator it = sql.begin(); it != sql.end(); ++it) { char ch = *it; switch(state) { case STATE_0: if (ch == ':') state = STATE_NAME0; else if (ch == '\\') state = STATE_ESC; else ret += ch; break; case STATE_NAME0: if (std::isalpha(ch)) { name = ch; state = STATE_NAME; } else if (ch == ':') ret += ':'; else if (ch == '\\') { ret += ':'; state = STATE_ESC; } break; case STATE_NAME: if (std::isalnum(ch)) { name += ch; } else { processHValue(ret, name); if (ch == '\\') state = STATE_ESC; else { ret += ch; state = STATE_0; } } break; case STATE_ESC: ret += ch; state = STATE_0; break; } } switch(state) { case STATE_NAME0: ret += ':'; break; case STATE_NAME: processHValue(ret, name); break; default: ; } return ret; } } } tntdb-1.4/src/sqlite/statement.cpp000066400000000000000000000405011354703061500172750ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" log_define("tntdb.sqlite.statement") namespace tntdb { namespace sqlite { Statement::Statement(Connection* conn_, const std::string& query_) : stmt(0), stmtInUse(0), conn(conn_), query(query_), needReset(false) { } Statement::~Statement() { if (stmt) { log_debug("sqlite3_finalize(" << stmt << ')'); ::sqlite3_finalize(stmt); } if (stmtInUse && stmtInUse != stmt) { log_debug("sqlite3_finalize(" << stmtInUse << ')'); ::sqlite3_finalize(stmtInUse); } } sqlite3_stmt* Statement::getBindStmt() { if (stmt == 0) { // hostvars don't need to be parsed, because sqlite accepts the hostvar- // syntax of tntdb (:vvv) // prepare statement const char* tzTail; #ifdef HAVE_SQLITE3_PREPARE_V2 log_debug("sqlite3_prepare_v2(" << conn->getSqlite3() << ", \"" << query << "\", " << &stmt << ", " << &tzTail << ')'); int ret = ::sqlite3_prepare_v2(conn->getSqlite3(), query.data(), query.size(), &stmt, &tzTail); if (ret != SQLITE_OK) throw Execerror("sqlite3_prepare_v2", conn->getSqlite3(), ret); #else log_debug("sqlite3_prepare(" << conn->getSqlite3() << ", \"" << query << "\", " << &stmt << ", " << &tzTail << ')'); int ret = ::sqlite3_prepare(conn->getSqlite3(), query.data(), query.size(), &stmt, &tzTail); if (ret != SQLITE_OK) throw Execerror("sqlite3_prepare", conn->getSqlite3(), ret); #endif log_debug("sqlite3_stmt = " << stmt); if (stmtInUse) { // get bindings from stmtInUse log_debug("sqlite3_transfer_bindings(" << stmtInUse << ", " << stmt << ')'); ret = ::sqlite3_transfer_bindings(stmtInUse, stmt); if (ret != SQLITE_OK) { log_debug("sqlite3_finalize(" << stmt << ')'); ::sqlite3_finalize(stmt); stmt = 0; throw Execerror("sqlite3_finalize", stmtInUse, ret); } } } else if (needReset) reset(); return stmt; } void Statement::putback(sqlite3_stmt* stmt_) { if (stmt == 0) { stmt = stmt_; // thank you - we can use it if (stmtInUse == stmt_) stmtInUse = 0; // it is not in use any more needReset = true; } else { // we have already a new statement-handle - destroy the old one log_debug("sqlite3_finalize(" << stmt_ << ')'); ::sqlite3_finalize(stmt_); if (stmtInUse == stmt_) stmtInUse = 0; } } int Statement::getBindIndex(const std::string& col) { getBindStmt(); log_debug("sqlite3_bind_parameter_index(" << stmt << ", :" << col << ')'); int idx = ::sqlite3_bind_parameter_index(stmt, (':' + col).c_str()); if (idx == 0) log_warn("hostvariable :" << col << " not found"); return idx; } void Statement::reset() { if (stmt) { if (needReset) { log_debug("sqlite3_reset(" << stmt << ')'); int ret = ::sqlite3_reset(stmt); if (ret != SQLITE_OK) throw Execerror("sqlite3_reset", stmt, ret); needReset = false; } } else getBindStmt(); } void Statement::clear() { getBindStmt(); int count = ::sqlite3_bind_parameter_count(stmt); for (int i = 0; i < count; ++i) { int ret = ::sqlite3_bind_null(stmt, i + 1); if (ret != SQLITE_OK) throw Execerror("sqlite3_bind_null", stmt, ret); } } void Statement::setNull(const std::string& col) { int idx = getBindIndex(col); getBindStmt(); if (idx != 0) { reset(); log_debug("sqlite3_bind_null(" << stmt << ", " << idx << ')'); int ret = ::sqlite3_bind_null(stmt, idx); if (ret != SQLITE_OK) throw Execerror("sqlite3_bind_null", stmt, ret); } } void Statement::setBool(const std::string& col, bool data) { setInt(col, data ? 1 : 0); } void Statement::setShort(const std::string& col, short data) { setInt(col, data); } void Statement::setInt(const std::string& col, int data) { int idx = getBindIndex(col); getBindStmt(); if (idx != 0) { reset(); log_debug("sqlite3_bind_int(" << stmt << ", " << idx << ')'); int ret = ::sqlite3_bind_int(stmt, idx, data); if (ret != SQLITE_OK) throw Execerror("sqlite3_bind_int", stmt, ret); } } void Statement::setLong(const std::string& col, long data) { int idx = getBindIndex(col); getBindStmt(); if (idx != 0) { reset(); log_debug("sqlite3_bind_int64(" << stmt << ", " << idx << ')'); int ret = ::sqlite3_bind_int64(stmt, idx, data); if (ret != SQLITE_OK) throw Execerror("sqlite3_bind_int", stmt, ret); } } void Statement::setInt32(const std::string& col, int32_t data) { setInt(col, data); } void Statement::setUnsignedShort(const std::string& col, unsigned short data) { if (data > static_cast(std::numeric_limits::max())) { log_warn("possible loss of precision while converting unsigned short " << data << " to double"); setDouble(col, static_cast(data)); } else setInt(col, static_cast(data)); } void Statement::setUnsigned(const std::string& col, unsigned data) { if (data > static_cast(std::numeric_limits::max())) { log_warn("possible loss of precision while converting unsigned " << data << " to double"); setDouble(col, static_cast(data)); } else setInt(col, static_cast(data)); } void Statement::setUnsignedLong(const std::string& col, unsigned long data) { if (data > static_cast(std::numeric_limits::max())) { log_warn("possible loss of precision while converting long unsigned " << data << " to double"); setDouble(col, static_cast(data)); } else setLong(col, static_cast(data)); } void Statement::setUnsigned32(const std::string& col, uint32_t data) { setUnsigned(col, data); } void Statement::setInt64(const std::string& col, int64_t data) { int idx = getBindIndex(col); getBindStmt(); if (idx != 0) { reset(); log_debug("sqlite3_bind_int64(" << stmt << ", " << idx << ')'); int ret = ::sqlite3_bind_int64(stmt, idx, data); if (ret != SQLITE_OK) throw Execerror("sqlite3_bind_int64", stmt, ret); } } void Statement::setUnsigned64(const std::string& col, uint64_t data) { setInt64(col, (int64_t)data); } void Statement::setDecimal(const std::string& col, const Decimal& data) { // SQLite 3.4.1 does not support the SQL decimal or numeric types. // So double is used instead, but of course binary floating point can // not accurately store decimal floating point numbers. // Maybe we could try instead using: // int sqlite3_value_numeric_type(sqlite3_value*); // However I do not understand the SQLite 3.4.1 documentation // for this API. I am confused by how it only returns an int, // yet the API documentation talks about returning an int, double // or text string. double d = data.getDouble(); setDouble(col, d); } void Statement::setFloat(const std::string& col, float data) { setDouble(col, static_cast(data)); } void Statement::setDouble(const std::string& col, double data) { int idx = getBindIndex(col); getBindStmt(); if (idx != 0) { reset(); log_debug("sqlite3_bind_double(" << stmt << ", " << idx << ')'); int ret = ::sqlite3_bind_double(stmt, idx, data); if (ret != SQLITE_OK) throw Execerror("sqlite3_bind_double", stmt, ret); } } void Statement::setChar(const std::string& col, char data) { int idx = getBindIndex(col); getBindStmt(); if (idx != 0) { reset(); log_debug("sqlite3_bind_text(" << stmt << ", " << idx << ", " << data << ", 1, SQLITE_TRANSIENT)"); int ret = ::sqlite3_bind_text(stmt, idx, &data, 1, SQLITE_TRANSIENT); if (ret != SQLITE_OK) throw Execerror("sqlite3_bind_text", stmt, ret); } } void Statement::setString(const std::string& col, const std::string& data) { int idx = getBindIndex(col); getBindStmt(); if (idx != 0) { reset(); log_debug("sqlite3_bind_text(" << stmt << ", " << idx << ", " << data << ", " << data.size() << ", SQLITE_TRANSIENT)"); int ret = ::sqlite3_bind_text(stmt, idx, data.data(), data.size(), SQLITE_TRANSIENT); if (ret != SQLITE_OK) throw Execerror("sqlite3_bind_text", stmt, ret); } } void Statement::setBlob(const std::string& col, const Blob& data) { int idx = getBindIndex(col); getBindStmt(); if (idx != 0) { reset(); log_debug("sqlite3_bind_blob(" << stmt << ", " << idx << ", data, " << data.size() << ", SQLITE_TRANSIENT)"); int ret = ::sqlite3_bind_blob(stmt, idx, data.data(), data.size(), SQLITE_TRANSIENT); if (ret != SQLITE_OK) throw Execerror("sqlite3_bind_blob", stmt, ret); } } void Statement::setDate(const std::string& col, const Date& data) { setString(col, data.getIso()); } void Statement::setTime(const std::string& col, const Time& data) { setString(col, data.getIso()); } void Statement::setDatetime(const std::string& col, const Datetime& data) { setString(col, data.getIso()); } Statement::size_type Statement::execute() { reset(); needReset = true; log_debug("sqlite3_step(" << stmt << ')'); int ret = sqlite3_step(stmt); if (ret != SQLITE_DONE && ret != SQLITE_ROW) { log_debug("sqlite3_step failed with return code " << ret); throw Execerror("sqlite3_step", stmt, ret); } int n = ::sqlite3_changes(::sqlite3_db_handle(stmt)); reset(); return n; } Result Statement::select() { reset(); needReset = true; ResultImpl* r = new ResultImpl(); Result result(r); int ret; do { log_debug("sqlite3_step(" << stmt << ')'); ret = sqlite3_step(stmt); if (ret == SQLITE_ROW) { log_debug("sqlite3_column_count(" << stmt << ')'); int count = ::sqlite3_column_count(stmt); RowImpl* row = new RowImpl(); r->add(Row(row)); for (int i = 0; i < count; ++i) { log_debug("sqlite3_column_bytes(" << stmt << ", " << i << ')'); int n = sqlite3_column_bytes(stmt, i); const void* txt = 0; if (n > 0) { log_debug("sqlite3_column_blob(" << stmt << ", " << i << ')'); txt = sqlite3_column_blob(stmt, i); } Value v; if (txt) v = Value(new ValueImpl( std::string(static_cast(txt), n))); log_debug("sqlite3_column_name(" << stmt << ", " << i << ')'); const char* name = sqlite3_column_name(stmt, i); if (name == 0) throw std::bad_alloc(); row->add(name, v); } } else if (ret != SQLITE_DONE) { log_debug("sqlite3_step failed with return code " << ret); throw Execerror("sqlite3_step", stmt, ret); } } while (ret == SQLITE_ROW); return result; } Row Statement::selectRow() { reset(); needReset = true; log_debug("sqlite3_step(" << stmt << ')'); int ret = sqlite3_step(stmt); if (ret == SQLITE_DONE) throw NotFound(); else if (ret == SQLITE_ROW) { log_debug("sqlite3_column_count(" << stmt << ')'); int count = ::sqlite3_column_count(stmt); RowImpl* r = new RowImpl(); Row row(r); for (int i = 0; i < count; ++i) { log_debug("sqlite3_column_bytes(" << stmt << ", " << i << ')'); int n = sqlite3_column_bytes(stmt, i); const void* txt = 0; if (n > 0) { log_debug("sqlite3_column_blob(" << stmt << ", " << i << ')'); txt = sqlite3_column_blob(stmt, i); } Value v; if (txt) v = Value(new ValueImpl( std::string(static_cast(txt), n))); log_debug("sqlite3_column_name(" << stmt << ", " << i << ')'); const char* name = sqlite3_column_name(stmt, i); if (name == 0) throw std::bad_alloc(); r->add(name, v); } reset(); return row; } else { reset(); log_debug("sqlite3_step failed with return code " << ret); throw Execerror("sqlite3_step", stmt, ret); } } Value Statement::selectValue() { reset(); needReset = true; log_debug("sqlite3_step(" << stmt << ')'); int ret = sqlite3_step(stmt); if (ret == SQLITE_DONE) { log_debug("sqlite3_step returned SQLITE_DONE => NotFound"); throw NotFound(); } else if (ret == SQLITE_ROW) { log_debug("sqlite3_column_count(" << stmt << ')'); int count = ::sqlite3_column_count(stmt); if (count == 0) throw NotFound(); log_debug("sqlite3_column_bytes(" << stmt << ", 0)"); int n = sqlite3_column_bytes(stmt, 0); const void* txt = 0; if (n > 0) { log_debug("sqlite3_column_blob(" << stmt << ", 0)"); txt = sqlite3_column_blob(stmt, 0); } Value v; if (txt) v = Value(new ValueImpl( std::string(static_cast(txt), n))); reset(); return v; } else { reset(); log_debug("sqlite3_step failed with return code " << ret); throw Execerror("sqlite3_step", stmt, ret); } } ICursor* Statement::createCursor(unsigned fetchsize) { stmtInUse = getBindStmt(); stmt = 0; return new Cursor(this, stmtInUse); } } } tntdb-1.4/src/sqlite/stmtrow.cpp000066400000000000000000000040671354703061500170170ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include namespace tntdb { namespace sqlite { unsigned StmtRow::size() const { return static_cast(::sqlite3_column_count(stmt)); } Value StmtRow::getValueByNumber(size_type field_num) const { return Value(new StmtValue(stmt, field_num)); } Value StmtRow::getValueByName(const std::string& field_name) const { return Value(new StmtValue(stmt, field_name)); } std::string StmtRow::getColumnName(size_type field_num) const { const char* name = sqlite3_column_name(stmt, field_num); if (name == 0) throw std::bad_alloc(); return name; } } } tntdb-1.4/src/sqlite/stmtvalue.cpp000066400000000000000000000144571354703061500173300ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include log_define("tntdb.sqlite.stmtvalue") namespace tntdb { namespace sqlite { StmtValue::StmtValue(sqlite3_stmt* stmt_, const std::string& name_) : stmt(stmt_) { log_debug("sqlite3_column_count(" << stmt << ')'); int count = ::sqlite3_column_count(stmt); for (iCol = 0; iCol < count; ++iCol) { log_debug("sqlite3_column_name(" << stmt << ", " << iCol << ')'); const char* name = sqlite3_column_name(stmt, iCol); if (name == 0) throw std::bad_alloc(); if (name == name_) break; } if (iCol >= count) throw FieldNotFound(name_); } bool StmtValue::isNull() const { log_debug("sqlite3_column_type(" << getStmt() << ", " << iCol << ')'); return ::sqlite3_column_type(getStmt(), iCol) == SQLITE_NULL; } bool StmtValue::getBool() const { char ch = getChar(); return ch == 't' || ch == 'T' || ch == 'y' || ch == 'Y' || ch == '1'; } short StmtValue::getShort() const { return getInt(); } int StmtValue::getInt() const { log_debug("sqlite3_column_int(" << getStmt() << ", " << iCol << ')'); return ::sqlite3_column_int(getStmt(), iCol); } long StmtValue::getLong() const { return static_cast(getInt64()); } unsigned short StmtValue::getUnsignedShort() const { return static_cast(getUnsigned()); } unsigned StmtValue::getUnsigned() const { return static_cast(getInt64()); } unsigned long StmtValue::getUnsignedLong() const { return static_cast(getInt64()); } int32_t StmtValue::getInt32() const { return static_cast(getInt()); } uint32_t StmtValue::getUnsigned32() const { return static_cast(getInt64()); } int64_t StmtValue::getInt64() const { log_debug("sqlite3_column_int64(" << getStmt() << ", " << iCol << ')'); return ::sqlite3_column_int64(getStmt(), iCol); } uint64_t StmtValue::getUnsigned64() const { log_debug("possible loss of data in conversion from int64_t to uint64_t"); return static_cast(getInt64()); } Decimal StmtValue::getDecimal() const { // SQLite 3.4.1 does not support the SQL decimal or numeric types. // So double is used instead, but of course binary floating point can // not accurately store decimal floating point numbers. log_debug("sqlite3_column_double(" << getStmt() << ", " << iCol << ')'); return Decimal(::sqlite3_column_double(getStmt(), iCol)); } float StmtValue::getFloat() const { return static_cast(getDouble()); } double StmtValue::getDouble() const { log_debug("sqlite3_column_double(" << getStmt() << ", " << iCol << ')'); return ::sqlite3_column_double(getStmt(), iCol); } char StmtValue::getChar() const { log_debug("sqlite3_column_bytes(" << getStmt() << ", " << iCol << ')'); int bytes = ::sqlite3_column_bytes(getStmt(), iCol); if (bytes <= 0) throw NullValue(); log_debug("sqlite3_column_blob(" << getStmt() << ", " << iCol << ')'); const void* ret = ::sqlite3_column_blob(getStmt(), iCol); return *static_cast(ret); } void StmtValue::getString(std::string& ret) const { log_debug("sqlite3_column_bytes(" << getStmt() << ", " << iCol << ')'); int bytes = ::sqlite3_column_bytes(getStmt(), iCol); if (bytes <= 0) { log_debug("empty string value - clear string"); ret.clear(); } else { log_debug("sqlite3_column_blob(" << getStmt() << ", " << iCol << ')'); const void* data = ::sqlite3_column_blob(getStmt(), iCol); ret.assign(reinterpret_cast(data), bytes); } } void StmtValue::getBlob(Blob& ret) const { log_debug("sqlite3_column_bytes(" << getStmt() << ", " << iCol << ')'); int bytes = ::sqlite3_column_bytes(getStmt(), iCol); if (bytes <= 0) { log_debug("empty value - clear blob"); ret.assign(0, 0); } else { log_debug("sqlite3_column_blob(" << getStmt() << ", " << iCol << ')'); const void* data = ::sqlite3_column_blob(getStmt(), iCol); ret.assign(reinterpret_cast(data), bytes); } } Date StmtValue::getDate() const { std::string str = getString(); return Date::fromIso(str); } Time StmtValue::getTime() const { std::string str = getString(); return Time::fromIso(str); } Datetime StmtValue::getDatetime() const { std::string str = getString(); return Datetime::fromIso(str); } } } tntdb-1.4/src/statement.cpp000066400000000000000000000054001354703061500157730ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include log_define("tntdb.statement") namespace tntdb { Statement::size_type Statement::execute() { log_trace("Statement::execute()"); return _stmt->execute(); } Result Statement::select() { log_trace("Statement::select()"); return _stmt->select(); } Row Statement::selectRow() { log_trace("Statement::selectRow()"); return _stmt->selectRow(); } Value Statement::selectValue() { log_trace("Statement::selectValue()"); return _stmt->selectValue(); } Statement::const_iterator Statement::begin(unsigned fetchsize) const { log_trace("Statement::begin(" << fetchsize << ')'); return const_iterator(_stmt->createCursor(fetchsize)); } void Statement::maxNumDelay(size_type n) { _stmt->maxNumDelay(n); } Statement::size_type Statement::numDelayed() const { return _stmt->numDelayed(); } Statement::size_type Statement::flush() { return _stmt->flush(); } void IStatement::setUString(const std::string& col, const cxxtools::String& data) { setString(col, cxxtools::Utf8Codec::encode(data)); } void IStatement::maxNumDelay(unsigned /*n*/) { } unsigned IStatement::numDelayed() const { return 0; } Statement::size_type IStatement::flush() { return 0; } } tntdb-1.4/src/statement_iterator.cpp000066400000000000000000000041711354703061500177100ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include log_define("tntdb.statement.iterator") namespace tntdb { Statement::const_iterator::const_iterator(ICursor* cursor_) : cursor(cursor_) { if (cursor_) { log_finer("initial fetch"); current = cursor_->fetch(); if (!current) { cursor = 0; log_finer("no row fetched"); } } } Statement::const_iterator& Statement::const_iterator::operator++() { log_finest("fetch next row"); current = cursor->fetch(); if (!current) { log_debug("no more rows"); cursor = 0; } return *this; } Statement::const_iterator Statement::const_iterator::operator++(int) { Statement::const_iterator tmp = *this; operator++(); return tmp; } } tntdb-1.4/src/stmtparser.cpp000066400000000000000000000100541354703061500161740ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include log_define("tntdb.stmtparser") namespace tntdb { void StmtParser::parse(const std::string& sqlIn, StmtEvent& event) { { enum state_type { STATE_0, STATE_NAME0, STATE_NAME, STATE_STRING, STATE_STRING_ESC, STATE_ESC } state = STATE_0; std::string name; sql.clear(); char end_token = '\0'; log_debug("parse sql \"" << sqlIn << "\""); for (std::string::const_iterator it = sqlIn.begin(); it != sqlIn.end(); ++it) { char ch = *it; switch(state) { case STATE_0: if (ch == praefixChar) state = STATE_NAME0; else if (ch == '\\') state = STATE_ESC; else { sql += ch; if (ch == '\'' || ch == '"' || ch == '`') { state = STATE_STRING; end_token = ch; } } break; case STATE_NAME0: if (std::isalpha(ch)) { name = ch; state = STATE_NAME; } else if (ch == praefixChar) { sql += praefixChar; sql += praefixChar; state = STATE_0; } else if (ch == '\\') { sql += praefixChar; state = STATE_ESC; } break; case STATE_NAME: if (std::isalnum(ch) || ch == '_') name += ch; else { log_debug("hostvar :" << name); sql += event.onHostVar(name); if (ch == '\\') state = STATE_ESC; else if (ch == praefixChar) state = STATE_NAME0; else { sql += ch; state = STATE_0; } } break; case STATE_STRING: sql += ch; if (ch == end_token) state = STATE_0; else if (ch == '\\') state = STATE_STRING_ESC; break; case STATE_STRING_ESC: sql += ch; state = (ch == end_token ? STATE_0 : STATE_STRING); break; case STATE_ESC: sql += ch; state = STATE_0; break; } } switch(state) { case STATE_NAME0: sql += praefixChar; break; case STATE_NAME: log_debug("hostvar :" << name); sql += event.onHostVar(name); break; default: ; } } } } tntdb-1.4/src/time.cpp000066400000000000000000000071201354703061500147260ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include namespace tntdb { Time Time::localtime() { struct timeval tv; struct tm tm; gettimeofday(&tv, 0); time_t t = static_cast(tv.tv_sec); localtime_r(&t, &tm); return Time(tm.tm_hour, tm.tm_min, tm.tm_sec, tv.tv_usec / 1000); } Time Time::gmtime() { struct timeval tv; struct tm tm; gettimeofday(&tv, 0); time_t t = static_cast(tv.tv_sec); gmtime_r(&t, &tm); return Time(tm.tm_hour, tm.tm_min, tm.tm_sec, tv.tv_usec / 1000); } std::string Time::getIso() const { // format hh:mm:ss.sss // 0....+....1....+ char ret[14]; ret[0] = '0' + _hour / 10; ret[1] = '0' + _hour % 10; ret[2] = ':'; ret[3] = '0' + _minute / 10; ret[4] = '0' + _minute % 10; ret[5] = ':'; ret[6] = '0' + _second / 10; ret[7] = '0' + _second % 10; ret[8] = '.'; unsigned short n = _millis; ret[11] = '0' + n % 10; n /= 10; ret[10] = '0' + n % 10; n /= 10; ret[9] = '0' + n % 10; return std::string(ret, 12); } inline unsigned short getNumber2(const char* s) { if (!std::isdigit(s[0]) || !std::isdigit(s[1])) throw TypeError(); return (s[0] - '0') * 10 + (s[1] - '0'); } inline unsigned short getNumber3(const char* s) { if (!std::isdigit(s[0]) || !std::isdigit(s[1]) || !std::isdigit(s[2])) throw TypeError(); return (s[0] - '0') * 100 + (s[1] - '0') * 10 + (s[2] - '0'); } Time Time::fromIso(const std::string& s) { Time ret; const char* d = s.data(); try { if (s.size() == 12 && d[2] == ':' && d[5] == ':' && d[8] == '.') { ret.set(getNumber2(d), getNumber2(d + 3), getNumber2(d + 6), getNumber3(d + 9)); } else if (s.size() == 8 && d[2] == ':' && d[5] == ':') { ret.set(getNumber2(d), getNumber2(d + 3), getNumber2(d + 6)); } else throw TypeError(); } catch (const TypeError&) { throw TypeError("failed to convert string \"" + s + "\" into time"); } return ret; } } tntdb-1.4/src/transaction.cpp000066400000000000000000000051131354703061500163150ustar00rootroot00000000000000/* * Copyright (C) 2010 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include log_define("tntdb.transaction") namespace tntdb { Transaction::Transaction(const Connection& db_, bool starttransaction) : db(db_), active(false) { if (starttransaction) begin(); } Transaction::~Transaction() { if (active) { try { rollback(); } catch (const std::exception& e) { } } } void Transaction::begin() { if (active) { log_warn("transaction already active in begin - rollback first"); rollback(); } log_debug("begin transaction"); db.beginTransaction(); active = true; } void Transaction::commit() { if (active) { log_debug("commit transaction"); db.commitTransaction(); active = false; } else { log_warn("transaction not active in commit"); } } void Transaction::rollback() { if (active) { log_debug("rollback transaction"); db.rollbackTransaction(); active = false; } else { log_warn("transaction not active in rollback"); } } void Transaction::lockTable(const std::string& tableName, bool exclusive) { db.getImpl()->lockTable(tableName, exclusive); } } tntdb-1.4/src/valueimpl.cpp000066400000000000000000000114671354703061500157770ustar00rootroot00000000000000/* * Copyright (C) 2005 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include namespace { bool isTrue(char ch) { return ch == 't' || ch == 'T' || ch == 'y' || ch == 'Y' || ch == '1'; } template T getValue(const std::string& s, const char* tname) { try { return cxxtools::convert(s); } catch (const cxxtools::ConversionError&) { std::ostringstream msg; msg << "can't convert \"" << s << "\" to " << tname; throw tntdb::TypeError(msg.str()); } } } namespace tntdb { bool ValueImpl::isNull() const { return null; } bool ValueImpl::getBool() const { if (null) throw NullValue(); return !data.empty() && isTrue(data.at(0)); } short ValueImpl::getShort() const { if (null) throw NullValue(); return getValue(data, "short"); } int ValueImpl::getInt() const { if (null) throw NullValue(); return getValue(data, "int"); } long ValueImpl::getLong() const { if (null) throw NullValue(); return getValue(data, "long"); } unsigned short ValueImpl::getUnsignedShort() const { if (null) throw NullValue(); return getValue(data, "unsigned short"); } unsigned ValueImpl::getUnsigned() const { if (null) throw NullValue(); return getValue(data, "unsigned"); } unsigned long ValueImpl::getUnsignedLong() const { if (null) throw NullValue(); return getValue(data, "unsigned long"); } int32_t ValueImpl::getInt32() const { if (null) throw NullValue(); return getValue(data, "int32_t"); } uint32_t ValueImpl::getUnsigned32() const { if (null) throw NullValue(); return getValue(data, "uint32_t"); } int64_t ValueImpl::getInt64() const { if (null) throw NullValue(); return getValue(data, "int64_t"); } uint64_t ValueImpl::getUnsigned64() const { if (null) throw NullValue(); return getValue(data, "uint64_t"); } Decimal ValueImpl::getDecimal() const { if (null) throw NullValue(); return getValue(data, "Decimal"); } float ValueImpl::getFloat() const { if (null) throw NullValue(); return getValue(data, "float"); } double ValueImpl::getDouble() const { if (null) throw NullValue(); return getValue(data, "double"); } char ValueImpl::getChar() const { if (null) throw NullValue(); return data.at(0); } void ValueImpl::getString(std::string& ret) const { if (null) throw NullValue(); ret.assign(data); } void ValueImpl::getBlob(Blob& ret) const { if (null) throw NullValue(); ret.assign(data.data(), data.size()); } Date ValueImpl::getDate() const { if (null) throw NullValue(); return Date::fromIso(data); } Time ValueImpl::getTime() const { if (null) throw NullValue(); return Time::fromIso(data); } Datetime ValueImpl::getDatetime() const { if (null) throw NullValue(); return Datetime::fromIso(data); } void IValue::getUString(cxxtools::String& ret) const { std::string r; getString(r); ret = cxxtools::Utf8Codec::decode(r); } } tntdb-1.4/test/000077500000000000000000000000001354703061500134545ustar00rootroot00000000000000tntdb-1.4/test/Makefile.am000066400000000000000000000007101354703061500155060ustar00rootroot00000000000000AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include dist_noinst_DATA = \ mysql-test.sql \ oracle-test.sql \ pg-test.sql \ sqlite-test.sql noinst_PROGRAMS = \ tntdb-test tntdb_test_SOURCES = \ base-test.cpp \ colname-test.cpp \ decimal-test.cpp \ sqlbuilder-test.cpp \ statement-test.cpp \ test-main.cpp \ timespan-test.cpp \ types-test.cpp \ value-test.cpp AM_LDFLAGS = -lcxxtools-unit LDADD = $(top_builddir)/src/libtntdb.la tntdb-1.4/test/base-test.cpp000066400000000000000000000417561354703061500160640ustar00rootroot00000000000000/* * Copyright (C) 2012 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include log_define("tntdb.unit.base") class TntdbBaseTest : public cxxtools::unit::TestSuite { tntdb::Connection conn; tntdb::Statement del; public: TntdbBaseTest() : cxxtools::unit::TestSuite("base") { registerMethod("testSelectValue", *this, &TntdbBaseTest::testSelectValue); registerMethod("testSelectRow", *this, &TntdbBaseTest::testSelectRow); registerMethod("testRowreader", *this, &TntdbBaseTest::testRowreader); registerMethod("testSelectResult", *this, &TntdbBaseTest::testSelectResult); registerMethod("testStmtSelectValue", *this, &TntdbBaseTest::testStmtSelectValue); registerMethod("testStmtSelectRow", *this, &TntdbBaseTest::testStmtSelectRow); registerMethod("testStmtSelectResult", *this, &TntdbBaseTest::testStmtSelectResult); registerMethod("testStmtSelectCursor", *this, &TntdbBaseTest::testStmtSelectCursor); registerMethod("testExecPlaceholder", *this, &TntdbBaseTest::testExecPlaceholder); registerMethod("testSelectPlaceholder", *this, &TntdbBaseTest::testSelectPlaceholder); registerMethod("testSelectMultiplePlaceholder", *this, &TntdbBaseTest::testSelectMultiplePlaceholder); registerMethod("testSelectCursorPlaceholder", *this, &TntdbBaseTest::testSelectCursorPlaceholder); registerMethod("testTransaction", *this, &TntdbBaseTest::testTransaction); registerMethod("testLimit", *this, &TntdbBaseTest::testLimit); registerMethod("testLimitOffset", *this, &TntdbBaseTest::testLimitOffset); } void setUp() { if (!conn) { const char* dburl = getenv("TNTDBURL"); if (!dburl) dburl = "sqlite:test.db"; log_info("testing with dburl=" << dburl); conn = tntdb::connect(dburl); del = conn.prepare("delete from tntdbtest"); del.execute(); } } void tearDown() { del.execute(); } void testSelectValue() { conn.execute("insert into tntdbtest(intcol) values(4)"); conn.execute("insert into tntdbtest(intcol) values(5)"); conn.execute("insert into tntdbtest(intcol) values(3)"); int maxVal = 0; bool notNull = conn.selectValue("select max(intcol) from tntdbtest").get(maxVal); CXXTOOLS_UNIT_ASSERT(notNull); CXXTOOLS_UNIT_ASSERT_EQUALS(maxVal, 5); } void testSelectRow() { conn.execute("insert into tntdbtest(intcol, shortcol, longcol) values(4, 5, 6)"); tntdb::Row r = conn.selectRow("select intcol, shortcol, longcol, unsignedshortcol from tntdbtest"); CXXTOOLS_UNIT_ASSERT_EQUALS(r.size(), 4); int intVal = 0; short shortVal = 0; long longVal = 0; unsigned short ushortVal = 0; bool intNotNull = r[0].get(intVal); bool shortNotNull = r[1].get(shortVal); bool longNotNull = r[2].get(longVal); bool ushortNotNull = r[3].get(ushortVal); CXXTOOLS_UNIT_ASSERT(intNotNull); CXXTOOLS_UNIT_ASSERT(shortNotNull); CXXTOOLS_UNIT_ASSERT(longNotNull); CXXTOOLS_UNIT_ASSERT(!ushortNotNull); CXXTOOLS_UNIT_ASSERT_EQUALS(intVal, 4); CXXTOOLS_UNIT_ASSERT_EQUALS(shortVal, 5); CXXTOOLS_UNIT_ASSERT_EQUALS(longVal, 6); } void testRowreader() { conn.execute("insert into tntdbtest(intcol, shortcol, longcol) values(4, 5, 6)"); tntdb::Row r = conn.selectRow("select intcol, shortcol, longcol, unsignedshortcol from tntdbtest"); CXXTOOLS_UNIT_ASSERT_EQUALS(r.size(), 4); int intVal = 0; short shortVal = 0; long longVal = 0; bool longNotNull = false; unsigned short ushortVal = 0; bool ushortNotNull = true; r.reader().get(intVal) .get(shortVal) .get(longVal, longNotNull) .get(ushortVal, ushortNotNull); CXXTOOLS_UNIT_ASSERT(longNotNull); CXXTOOLS_UNIT_ASSERT(!ushortNotNull); CXXTOOLS_UNIT_ASSERT_EQUALS(intVal, 4); CXXTOOLS_UNIT_ASSERT_EQUALS(shortVal, 5); CXXTOOLS_UNIT_ASSERT_EQUALS(longVal, 6); } void testSelectResult() { conn.execute("insert into tntdbtest(intcol, shortcol, longcol) values(4, 5, 6)"); conn.execute("insert into tntdbtest(intcol, shortcol, longcol) values(3, 4, 5)"); tntdb::Result r = conn.select("select intcol, shortcol, longcol, unsignedshortcol from tntdbtest order by intcol"); CXXTOOLS_UNIT_ASSERT_EQUALS(r.size(), 2); CXXTOOLS_UNIT_ASSERT_EQUALS(r[0].size(), 4); CXXTOOLS_UNIT_ASSERT_EQUALS(r[1].size(), 4); int intVal = 0; short shortVal = 0; long longVal = 0; unsigned short ushortVal = 0; bool intNotNull = r[0][0].get(intVal); bool shortNotNull = r[0][1].get(shortVal); bool longNotNull = r[0][2].get(longVal); bool ushortNotNull = r[0][3].get(ushortVal); CXXTOOLS_UNIT_ASSERT(intNotNull); CXXTOOLS_UNIT_ASSERT(shortNotNull); CXXTOOLS_UNIT_ASSERT(longNotNull); CXXTOOLS_UNIT_ASSERT(!ushortNotNull); CXXTOOLS_UNIT_ASSERT_EQUALS(intVal, 3); CXXTOOLS_UNIT_ASSERT_EQUALS(shortVal, 4); CXXTOOLS_UNIT_ASSERT_EQUALS(longVal, 5); intNotNull = r[1][0].get(intVal); shortNotNull = r[1][1].get(shortVal); longNotNull = r[1][2].get(longVal); ushortNotNull = r[1][3].get(ushortVal); CXXTOOLS_UNIT_ASSERT(intNotNull); CXXTOOLS_UNIT_ASSERT(shortNotNull); CXXTOOLS_UNIT_ASSERT(longNotNull); CXXTOOLS_UNIT_ASSERT(!ushortNotNull); CXXTOOLS_UNIT_ASSERT_EQUALS(intVal, 4); CXXTOOLS_UNIT_ASSERT_EQUALS(shortVal, 5); CXXTOOLS_UNIT_ASSERT_EQUALS(longVal, 6); } void testStmtSelectValue() { conn.execute("insert into tntdbtest(intcol) values(4)"); conn.execute("insert into tntdbtest(intcol) values(5)"); conn.execute("insert into tntdbtest(intcol) values(3)"); int maxVal = 0; bool notNull = conn.prepare("select max(intcol) from tntdbtest").selectValue().get(maxVal); CXXTOOLS_UNIT_ASSERT(notNull); CXXTOOLS_UNIT_ASSERT_EQUALS(maxVal, 5); } void testStmtSelectRow() { conn.execute("insert into tntdbtest(intcol, shortcol, longcol) values(4, 5, 6)"); tntdb::Row r = conn.prepare("select intcol, shortcol, longcol, unsignedshortcol from tntdbtest").selectRow(); CXXTOOLS_UNIT_ASSERT_EQUALS(r.size(), 4); int intVal = 0; short shortVal = 0; long longVal = 0; unsigned short ushortVal = 0; bool intNotNull = r[0].get(intVal); bool shortNotNull = r[1].get(shortVal); bool longNotNull = r[2].get(longVal); bool ushortNotNull = r[3].get(ushortVal); CXXTOOLS_UNIT_ASSERT(intNotNull); CXXTOOLS_UNIT_ASSERT(shortNotNull); CXXTOOLS_UNIT_ASSERT(longNotNull); CXXTOOLS_UNIT_ASSERT(!ushortNotNull); CXXTOOLS_UNIT_ASSERT_EQUALS(intVal, 4); CXXTOOLS_UNIT_ASSERT_EQUALS(shortVal, 5); CXXTOOLS_UNIT_ASSERT_EQUALS(longVal, 6); } void testStmtSelectResult() { conn.execute("insert into tntdbtest(intcol, shortcol, longcol) values(4, 5, 6)"); conn.execute("insert into tntdbtest(intcol, shortcol, longcol) values(3, 4, 5)"); tntdb::Result r = conn.prepare("select intcol, shortcol, longcol, unsignedshortcol from tntdbtest order by intcol").select(); CXXTOOLS_UNIT_ASSERT_EQUALS(r.size(), 2); CXXTOOLS_UNIT_ASSERT_EQUALS(r[0].size(), 4); CXXTOOLS_UNIT_ASSERT_EQUALS(r[1].size(), 4); int intVal = 0; short shortVal = 0; long longVal = 0; unsigned short ushortVal = 0; bool intNotNull = r[0][0].get(intVal); bool shortNotNull = r[0][1].get(shortVal); bool longNotNull = r[0][2].get(longVal); bool ushortNotNull = r[0][3].get(ushortVal); CXXTOOLS_UNIT_ASSERT(intNotNull); CXXTOOLS_UNIT_ASSERT(shortNotNull); CXXTOOLS_UNIT_ASSERT(longNotNull); CXXTOOLS_UNIT_ASSERT(!ushortNotNull); CXXTOOLS_UNIT_ASSERT_EQUALS(intVal, 3); CXXTOOLS_UNIT_ASSERT_EQUALS(shortVal, 4); CXXTOOLS_UNIT_ASSERT_EQUALS(longVal, 5); intNotNull = r[1][0].get(intVal); shortNotNull = r[1][1].get(shortVal); longNotNull = r[1][2].get(longVal); ushortNotNull = r[1][3].get(ushortVal); CXXTOOLS_UNIT_ASSERT(intNotNull); CXXTOOLS_UNIT_ASSERT(shortNotNull); CXXTOOLS_UNIT_ASSERT(longNotNull); CXXTOOLS_UNIT_ASSERT(!ushortNotNull); CXXTOOLS_UNIT_ASSERT_EQUALS(intVal, 4); CXXTOOLS_UNIT_ASSERT_EQUALS(shortVal, 5); CXXTOOLS_UNIT_ASSERT_EQUALS(longVal, 6); } void testStmtSelectCursor() { conn.execute("insert into tntdbtest(intcol, shortcol, longcol) values(4, 5, 6)"); conn.execute("insert into tntdbtest(intcol, shortcol, longcol) values(3, 4, 5)"); tntdb::Statement stmt = conn.prepare("select intcol, shortcol, longcol, unsignedshortcol from tntdbtest order by intcol"); unsigned rowcount = 0; for (tntdb::Statement::const_iterator cur = stmt.begin(); cur != stmt.end(); ++cur, ++rowcount) { tntdb::Row row = *cur; int intVal = 0; short shortVal = 0; long longVal = 0; unsigned short ushortVal = 0; bool intNotNull = row[0].get(intVal); bool shortNotNull = row[1].get(shortVal); bool longNotNull = row[2].get(longVal); bool ushortNotNull = row[3].get(ushortVal); CXXTOOLS_UNIT_ASSERT(intNotNull); CXXTOOLS_UNIT_ASSERT(shortNotNull); CXXTOOLS_UNIT_ASSERT(longNotNull); CXXTOOLS_UNIT_ASSERT(!ushortNotNull); CXXTOOLS_UNIT_ASSERT_EQUALS(static_cast(intVal), rowcount + 3); CXXTOOLS_UNIT_ASSERT_EQUALS(static_cast(shortVal), rowcount + 4); CXXTOOLS_UNIT_ASSERT_EQUALS(static_cast(longVal), rowcount + 5); } } void testExecPlaceholder() { tntdb::Statement ins = conn.prepare("insert into tntdbtest(intcol) values(:intcol)"); ins.set("intcol", 4).execute(); ins.set("intcol", 5).execute(); ins.set("intcol", 3).execute(); int maxVal = 0; bool notNull = conn.selectValue("select max(intcol) from tntdbtest").get(maxVal); CXXTOOLS_UNIT_ASSERT(notNull); CXXTOOLS_UNIT_ASSERT_EQUALS(maxVal, 5); } void testSelectPlaceholder() { conn.execute("insert into tntdbtest(intcol, shortcol, longcol) values(4, 5, 6)"); conn.execute("insert into tntdbtest(intcol, shortcol, longcol) values(3, 4, 5)"); tntdb::Statement sel = conn.prepare("select shortcol from tntdbtest where intcol = :intcol"); short shortVal = 0; bool shortNotNull = sel.set("intcol", 3).selectValue().get(shortVal); CXXTOOLS_UNIT_ASSERT(shortNotNull); CXXTOOLS_UNIT_ASSERT_EQUALS(shortVal, 4); } void testSelectMultiplePlaceholder() { conn.execute("insert into tntdbtest(intcol, shortcol, longcol) values(4, 5, 6)"); conn.execute("insert into tntdbtest(intcol, shortcol, longcol) values(3, 4, 5)"); conn.execute("insert into tntdbtest(intcol, shortcol, longcol) values(5, 6, 7)"); tntdb::Statement sel = conn.prepare("select count(*) from tntdbtest where intcol = :value or shortcol = :value"); unsigned count = 0; sel.set("value", 4).selectValue().get(count); CXXTOOLS_UNIT_ASSERT_EQUALS(count, 2); } void testSelectCursorPlaceholder() { conn.execute("insert into tntdbtest(intcol, shortcol, longcol) values(5, 6, 7)"); conn.execute("insert into tntdbtest(intcol, shortcol, longcol) values(4, 5, 6)"); conn.execute("insert into tntdbtest(intcol, shortcol, longcol) values(3, 4, 5)"); tntdb::Statement stmt = conn.prepare("select intcol, shortcol, longcol, unsignedshortcol from tntdbtest where intcol >= :intcol order by intcol"); stmt.set("intcol", 4); unsigned rowcount = 0; for (tntdb::Statement::const_iterator cur = stmt.begin(); cur != stmt.end(); ++cur, ++rowcount) { tntdb::Row row = *cur; int intVal = 0; short shortVal = 0; long longVal = 0; unsigned short ushortVal = 0; bool intNotNull = row[0].get(intVal); bool shortNotNull = row[1].get(shortVal); bool longNotNull = row[2].get(longVal); bool ushortNotNull = row[3].get(ushortVal); CXXTOOLS_UNIT_ASSERT(intNotNull); CXXTOOLS_UNIT_ASSERT(shortNotNull); CXXTOOLS_UNIT_ASSERT(longNotNull); CXXTOOLS_UNIT_ASSERT(!ushortNotNull); CXXTOOLS_UNIT_ASSERT_EQUALS(static_cast(intVal), rowcount + 4); CXXTOOLS_UNIT_ASSERT_EQUALS(static_cast(shortVal), rowcount + 5); CXXTOOLS_UNIT_ASSERT_EQUALS(static_cast(longVal), rowcount + 6); } } void testTransaction() { unsigned count = 0; conn.execute("insert into tntdbtest(intcol, shortcol, longcol) values(4, 5, 6)"); conn.execute("insert into tntdbtest(intcol, shortcol, longcol) values(3, 4, 5)"); { tntdb::Transaction trans(conn); conn.execute("insert into tntdbtest(intcol, shortcol, longcol) values(5, 6, 7)"); conn.selectValue("select count(*) from tntdbtest").get(count); CXXTOOLS_UNIT_ASSERT_EQUALS(count, 3); } conn.selectValue("select count(*) from tntdbtest").get(count); CXXTOOLS_UNIT_ASSERT_EQUALS(count, 2); { tntdb::Transaction trans(conn); conn.execute("insert into tntdbtest(intcol, shortcol, longcol) values(5, 6, 7)"); conn.selectValue("select count(*) from tntdbtest").get(count); CXXTOOLS_UNIT_ASSERT_EQUALS(count, 3); trans.commit(); } conn.selectValue("select count(*) from tntdbtest").get(count); CXXTOOLS_UNIT_ASSERT_EQUALS(count, 3); } void testLimit() { conn.execute("insert into tntdbtest(intcol) values(4)"); conn.execute("insert into tntdbtest(intcol) values(5)"); conn.execute("insert into tntdbtest(intcol) values(3)"); conn.execute("insert into tntdbtest(intcol) values(9)"); tntdb::Statement stmt = conn.prepareWithLimit("select intcol from tntdbtest order by 1", "l"); stmt.set("l", 2); int intVal = 0; bool notNull; tntdb::Statement::const_iterator cur = stmt.begin(); CXXTOOLS_UNIT_ASSERT(cur != stmt.end()); notNull = (*cur)[0].get(intVal); CXXTOOLS_UNIT_ASSERT(notNull); CXXTOOLS_UNIT_ASSERT_EQUALS(intVal, 3); ++cur; CXXTOOLS_UNIT_ASSERT(cur != stmt.end()); notNull = (*cur)[0].get(intVal); CXXTOOLS_UNIT_ASSERT(notNull); CXXTOOLS_UNIT_ASSERT_EQUALS(intVal, 4); ++cur; CXXTOOLS_UNIT_ASSERT(cur == stmt.end()); } void testLimitOffset() { conn.execute("insert into tntdbtest(intcol) values(4)"); conn.execute("insert into tntdbtest(intcol) values(5)"); conn.execute("insert into tntdbtest(intcol) values(3)"); conn.execute("insert into tntdbtest(intcol) values(9)"); tntdb::Statement stmt = conn.prepareWithLimit("select intcol from tntdbtest order by 1", "l", "o"); stmt.set("l", 2) .set("o", 1); int intVal = 0; bool notNull; tntdb::Statement::const_iterator cur = stmt.begin(); CXXTOOLS_UNIT_ASSERT(cur != stmt.end()); notNull = (*cur)[0].get(intVal); CXXTOOLS_UNIT_ASSERT(notNull); CXXTOOLS_UNIT_ASSERT_EQUALS(intVal, 4); ++cur; CXXTOOLS_UNIT_ASSERT(cur != stmt.end()); notNull = (*cur)[0].get(intVal); CXXTOOLS_UNIT_ASSERT(notNull); CXXTOOLS_UNIT_ASSERT_EQUALS(intVal, 5); ++cur; CXXTOOLS_UNIT_ASSERT(cur == stmt.end()); } }; cxxtools::unit::RegisterTest register_TntdbBaseTest; tntdb-1.4/test/colname-test.cpp000066400000000000000000000051261354703061500165570ustar00rootroot00000000000000/* * Copyright (C) 2012 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include log_define("tntdb.unit.colname") class TntdbColnameTest : public cxxtools::unit::TestSuite { tntdb::Connection conn; tntdb::Statement del; public: TntdbColnameTest() : cxxtools::unit::TestSuite("colname") { registerMethod("testColname", *this, &TntdbColnameTest::testColname); } void setUp() { if (!conn) { const char* dburl = getenv("TNTDBURL"); if (!dburl) dburl = "sqlite:test.db"; log_info("testing with dburl=" << dburl); conn = tntdb::connect(dburl); del = conn.prepare("delete from tntdbtest"); } } void tearDown() { del.execute(); } void testColname() { conn.execute("insert into tntdbtest(intcol) values(4718)"); tntdb::Row row = conn.selectRow("select intcol, intcol as foo from tntdbtest"); CXXTOOLS_UNIT_ASSERT_EQUALS(row.getName(0), "intcol"); CXXTOOLS_UNIT_ASSERT_EQUALS(row.getName(1), "foo"); } }; cxxtools::unit::RegisterTest register_TntdbColnameTest; tntdb-1.4/test/decimal-test.cpp000066400000000000000000000212231354703061500165330ustar00rootroot00000000000000/* * Copyright (C) 2010 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include namespace { bool nearBy(long double v1, long double v2, long double e = 1e-6) { long double q = v1 / v2; return q > 1 - e && q < 1 + e; } } class TntdbDecimalTest : public cxxtools::unit::TestSuite { public: TntdbDecimalTest() : cxxtools::unit::TestSuite("decimal") { registerMethod("testDouble", *this, &TntdbDecimalTest::testDouble); registerMethod("testFromString", *this, &TntdbDecimalTest::testFromString); registerMethod("testToString", *this, &TntdbDecimalTest::testToString); registerMethod("testInt", *this, &TntdbDecimalTest::testInt); registerMethod("testIntExp", *this, &TntdbDecimalTest::testIntExp); registerMethod("testCompare", *this, &TntdbDecimalTest::testCompare); } void testDouble() { tntdb::Decimal d; d = tntdb::Decimal(45.6); CXXTOOLS_UNIT_ASSERT(nearBy(d.getDouble(), 45.6)); d = tntdb::Decimal(-3.14); CXXTOOLS_UNIT_ASSERT(nearBy(d.getDouble(), -3.14)); d = tntdb::Decimal(5e97); CXXTOOLS_UNIT_ASSERT_EQUALS(d.getDouble(), 5e97); d = tntdb::Decimal(-123e-154); CXXTOOLS_UNIT_ASSERT(nearBy(d.getDouble(), -123e-154)); d = tntdb::Decimal(std::numeric_limits::max()); CXXTOOLS_UNIT_ASSERT(nearBy(d.getDouble(), std::numeric_limits::max())); d = tntdb::Decimal(std::numeric_limits::min()); CXXTOOLS_UNIT_ASSERT(nearBy(d.getDouble(), std::numeric_limits::min())); d = tntdb::Decimal(std::numeric_limits::infinity()); CXXTOOLS_UNIT_ASSERT_EQUALS(d.getDouble(), std::numeric_limits::infinity()); d = tntdb::Decimal(-std::numeric_limits::infinity()); CXXTOOLS_UNIT_ASSERT_EQUALS(d.getDouble(), -std::numeric_limits::infinity()); } void testFromString() { tntdb::Decimal d; d = tntdb::Decimal("45.6"); CXXTOOLS_UNIT_ASSERT(nearBy(d.getDouble(), 45.6)); d = tntdb::Decimal("-3.14"); CXXTOOLS_UNIT_ASSERT(nearBy(d.getDouble(), -3.14)); d = tntdb::Decimal("5e97"); CXXTOOLS_UNIT_ASSERT(nearBy(d.getDouble(), 5e97)); d = tntdb::Decimal("-123e-154"); CXXTOOLS_UNIT_ASSERT(nearBy(d.getDouble(), -123e-154)); d = tntdb::Decimal("12345678901234567890"); CXXTOOLS_UNIT_ASSERT_EQUALS(d.toStringFix(), "12345678901234567890"); d = tntdb::Decimal("inf"); CXXTOOLS_UNIT_ASSERT_EQUALS(d.getDouble(), std::numeric_limits::infinity()); d = tntdb::Decimal("-inf"); CXXTOOLS_UNIT_ASSERT_EQUALS(d.getDouble(), -std::numeric_limits::infinity()); d = tntdb::Decimal("nan"); CXXTOOLS_UNIT_ASSERT(d.getDouble() != d.getDouble()); d = tntdb::Decimal(" 1.00000000000000000000000000000000000000E+00 "); CXXTOOLS_UNIT_ASSERT_EQUALS(d.getDouble(), 1); d = tntdb::Decimal(" 1 "); CXXTOOLS_UNIT_ASSERT_EQUALS(d.getDouble(), 1); d = tntdb::Decimal(" 1.0 "); CXXTOOLS_UNIT_ASSERT_EQUALS(d.getDouble(), 1); d = tntdb::Decimal(" 1e0 "); CXXTOOLS_UNIT_ASSERT_EQUALS(d.getDouble(), 1); d = tntdb::Decimal(" 0.1e1 "); CXXTOOLS_UNIT_ASSERT_EQUALS(d.getDouble(), 1); d = tntdb::Decimal(" .00000000000000000000000000000000000000E+00"); CXXTOOLS_UNIT_ASSERT_EQUALS(d.getDouble(), 0); d = tntdb::Decimal("0"); CXXTOOLS_UNIT_ASSERT_EQUALS(d.getDouble(), 0); } void testToString() { tntdb::Decimal d; d = tntdb::Decimal("45.6"); CXXTOOLS_UNIT_ASSERT_EQUALS(d.toString(), "45.6"); CXXTOOLS_UNIT_ASSERT_EQUALS(d.toStringSci(), "4.56e1"); d = tntdb::Decimal("-3.14"); CXXTOOLS_UNIT_ASSERT_EQUALS(d.toString(), "-3.14"); CXXTOOLS_UNIT_ASSERT_EQUALS(d.toStringSci(), "-3.14e0"); d = tntdb::Decimal("5e97"); CXXTOOLS_UNIT_ASSERT_EQUALS(d.toString(), "5e97"); CXXTOOLS_UNIT_ASSERT_EQUALS(d.toStringSci(), "5e97"); d = tntdb::Decimal("-123e-154"); CXXTOOLS_UNIT_ASSERT_EQUALS(d.toString(), "-1.23e-152"); CXXTOOLS_UNIT_ASSERT_EQUALS(d.toStringSci(), "-1.23e-152"); d = tntdb::Decimal("12345678901234567890"); CXXTOOLS_UNIT_ASSERT_EQUALS(d.toStringFix(), "12345678901234567890"); CXXTOOLS_UNIT_ASSERT_EQUALS(d.toStringSci(), "1.234567890123456789e19"); d = tntdb::Decimal("1e23"); CXXTOOLS_UNIT_ASSERT_EQUALS(d.toStringFix(), "100000000000000000000000"); CXXTOOLS_UNIT_ASSERT_EQUALS(d.toStringSci(), "1e23"); CXXTOOLS_UNIT_ASSERT_EQUALS(d.toString(), "1e23"); d = tntdb::Decimal("-3e-23"); CXXTOOLS_UNIT_ASSERT_EQUALS(d.toStringFix(), "-0.00000000000000000000003"); CXXTOOLS_UNIT_ASSERT_EQUALS(d.toStringSci(), "-3e-23"); CXXTOOLS_UNIT_ASSERT_EQUALS(d.toString(), "-3e-23"); d = tntdb::Decimal("inf"); CXXTOOLS_UNIT_ASSERT_EQUALS(d.toString(), "inf"); d = tntdb::Decimal("-inf"); CXXTOOLS_UNIT_ASSERT_EQUALS(d.toString(), "-inf"); d = tntdb::Decimal("nan"); CXXTOOLS_UNIT_ASSERT_EQUALS(d.toString(), "nan"); } void testInt() { tntdb::Decimal d; long l; d = tntdb::Decimal(100, 0); l = d.getInteger(); CXXTOOLS_UNIT_ASSERT_EQUALS(l, 100l); d = tntdb::Decimal(45, 3); l = d.getInteger(); CXXTOOLS_UNIT_ASSERT_EQUALS(l, 45000l); d = tntdb::Decimal(std::numeric_limits::max(), 0); l = d.getInteger(); CXXTOOLS_UNIT_ASSERT_EQUALS(l, std::numeric_limits::max()); d = tntdb::Decimal(std::numeric_limits::min(), 0); l = d.getInteger(); CXXTOOLS_UNIT_ASSERT_EQUALS(l, std::numeric_limits::min()); d = tntdb::Decimal(-100, 0); l = d.getInteger(); CXXTOOLS_UNIT_ASSERT_EQUALS(l, -100l); } void testIntExp() { tntdb::Decimal d("453000"); long l = d.getInteger(-3); CXXTOOLS_UNIT_ASSERT_EQUALS(l, 453); d = tntdb::Decimal("45.6"); l = d.getInteger(1); CXXTOOLS_UNIT_ASSERT_EQUALS(l, 456); d = tntdb::Decimal("-78.334"); l = d.getInteger(4); CXXTOOLS_UNIT_ASSERT_EQUALS(l, -783340); } void testCompare() { tntdb::Decimal d0(45, 3); tntdb::Decimal d1(450, 2); tntdb::Decimal d2(449, 2); tntdb::Decimal d3(-449, 2); tntdb::Decimal d4(451, 2); CXXTOOLS_UNIT_ASSERT(d0 == d1); CXXTOOLS_UNIT_ASSERT(d0 != d2); CXXTOOLS_UNIT_ASSERT(d1 != d2); CXXTOOLS_UNIT_ASSERT(d3 != d0); CXXTOOLS_UNIT_ASSERT(d3 != d1); CXXTOOLS_UNIT_ASSERT(d3 != d2); CXXTOOLS_UNIT_ASSERT(d2 < d0); CXXTOOLS_UNIT_ASSERT(d2 < d1); CXXTOOLS_UNIT_ASSERT(d3 < d0); CXXTOOLS_UNIT_ASSERT(d3 < d1); CXXTOOLS_UNIT_ASSERT(d3 < d2); CXXTOOLS_UNIT_ASSERT(d2 < d4); CXXTOOLS_UNIT_ASSERT(d0 > d2); CXXTOOLS_UNIT_ASSERT(d1 > d2); CXXTOOLS_UNIT_ASSERT(d0 > d3); CXXTOOLS_UNIT_ASSERT(d1 > d3); CXXTOOLS_UNIT_ASSERT(d2 > d3); CXXTOOLS_UNIT_ASSERT(d2 <= d0); CXXTOOLS_UNIT_ASSERT(d0 <= d1); CXXTOOLS_UNIT_ASSERT(d2 <= d1); CXXTOOLS_UNIT_ASSERT(d0 >= d2); CXXTOOLS_UNIT_ASSERT(d0 >= d1); CXXTOOLS_UNIT_ASSERT(d1 >= d2); } }; cxxtools::unit::RegisterTest register_TntdbDecimalTest; tntdb-1.4/test/mysql-test.sql000066400000000000000000000010061354703061500163140ustar00rootroot00000000000000create table tntdbtest ( id integer not null primary key auto_increment, boolcol boolean, shortcol integer, intcol integer, longcol bigint, unsignedshortcol integer, unsignedcol bigint, unsignedlongcol decimal(24), int32col integer, uint32col bigint, int64col bigint, uint64col decimal(24), decimalcol decimal(16, 4), floatcol real, doublecol double precision, charcol char, stringcol varchar(255), blobcol blob, datecol date null, timecol time, datetimecol timestamp null ); tntdb-1.4/test/mysql_seq_test.sql000066400000000000000000000002651354703061500172540ustar00rootroot00000000000000create table foo ( a integer not null primary key auto_increment, b integer not null ); insert into foo (b) values (3); insert into foo (b) values (7); select * from foo; tntdb-1.4/test/oracle-test.sql000066400000000000000000000014001354703061500164120ustar00rootroot00000000000000--drop table tntdbtest; --drop sequence tntdbtest_seq; create sequence tntdbtest_seq; create table tntdbtest ( id integer not null primary key, boolcol number(1), shortcol integer, intcol number(10), longcol number(24), unsignedshortcol integer, unsignedcol number(10), unsignedlongcol number(24), int32col number(10), uint32col number(10), int64col number(24), uint64col number(24), decimalcol decimal(24, 4), floatcol binary_float, doublecol binary_double, charcol char, stringcol varchar2(255), blobcol blob, datecol date, timecol timestamp, datetimecol timestamp ); create trigger tntdbtest_trigger before insert on tntdbtest for each row begin select tntdbtest_seq.nextval into :new.id from dual; end; / tntdb-1.4/test/oracle_seq_test.sql000066400000000000000000000005411354703061500173510ustar00rootroot00000000000000drop table foo; drop sequence foo_seq; create table foo ( a number not null, b integer not null ); create sequence foo_seq; create trigger foo_trigger before insert on foo for each row begin select foo_seq.nextval into :new.a from dual; end; / insert into foo (b) values (3); insert into foo (b) values (7); select * from foo; tntdb-1.4/test/pg-test.sql000066400000000000000000000011321354703061500155550ustar00rootroot00000000000000create sequence tntdbtest_seq; create table tntdbtest ( id integer not null primary key default nextval('tntdbtest_seq'), boolcol boolean, shortcol integer, intcol integer, longcol bigint, unsignedshortcol integer, unsignedcol bigint, unsignedlongcol decimal(24), int32col integer, uint32col bigint, int64col bigint, uint64col decimal(24), decimalcol decimal(16, 4), floatcol real, doublecol double precision, charcol char, stringcol text, blobcol bytea, datecol date, timecol time, datetimecol timestamp ); alter sequence tntdbtest_seq owned by tntdbtest.id; tntdb-1.4/test/pg_seq_test.sql000066400000000000000000000003651354703061500165160ustar00rootroot00000000000000create sequence foo_seq; create table foo ( a integer not null default nextval('foo_seq'), b integer not null ); alter SEQUENCE foo_seq OWNED BY foo.a; insert into foo (b) values (3); insert into foo (b) values (7); select * from foo; tntdb-1.4/test/sqlbuilder-test.cpp000066400000000000000000000061511354703061500173060ustar00rootroot00000000000000/* * Copyright (C) 2011 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include class SqlBuilderTest : public cxxtools::unit::TestSuite { public: SqlBuilderTest() : cxxtools::unit::TestSuite("sqlbuilder") { registerMethod("testExtendParam", *this, &SqlBuilderTest::testExtendParam); registerMethod("testReplace", *this, &SqlBuilderTest::testReplace); registerMethod("testReplaceQ", *this, &SqlBuilderTest::testReplaceQ); registerMethod("testReplaceIf", *this, &SqlBuilderTest::testReplaceIf); } void testExtendParam() { tntdb::SqlBuilder s("select a from tab1 where b in (%c)"); s.extendParam("c", 3); CXXTOOLS_UNIT_ASSERT_EQUALS(s.str(), "select a from tab1 where b in ( :c0,:c1,:c2 )"); } void testReplace() { tntdb::SqlBuilder s("select a from %table where b = 5"); s.replace("table", "foo"); CXXTOOLS_UNIT_ASSERT_EQUALS(s.str(), "select a from foo where b = 5"); } void testReplaceQ() { tntdb::SqlBuilder s("select a from tab1 where b = 'Hi' and %col = 5"); s.replace("col", "c"); CXXTOOLS_UNIT_ASSERT_EQUALS(s.str(), "select a from tab1 where b = 'Hi' and c = 5"); tntdb::SqlBuilder s2("select a from tab1 where b = '\\' and %col = 5"); s2.replace("col", "c"); CXXTOOLS_UNIT_ASSERT_EQUALS(s2.str(), "select a from tab1 where b = '\\' and c = 5"); } void testReplaceIf() { tntdb::SqlBuilder s("select a from tab1 where b = 5 %c1 %c2"); s.replaceIf(true, "c1", "and c = :c") .replaceIf(false, "c2", "and d = :d"); CXXTOOLS_UNIT_ASSERT_EQUALS(s.str(), "select a from tab1 where b = 5 and c = :c "); } }; cxxtools::unit::RegisterTest register_SqlBuilderTest; tntdb-1.4/test/sqlite-test.sql000066400000000000000000000007421354703061500164560ustar00rootroot00000000000000create table tntdbtest ( id integer not null primary key autoincrement, boolcol boolean, shortcol integer, intcol integer, longcol integer, unsignedshortcol integer, unsignedcol integer, unsignedlongcol integer, int32col integer, uint32col integer, int64col integer, uint64col integer, decimalcol decimal(10, 4), floatcol real, doublecol real, charcol char, stringcol text, blobcol blob, datecol date, timecol time, datetimecol datetime ); tntdb-1.4/test/sqlite_seq_test.sql000066400000000000000000000002641354703061500174070ustar00rootroot00000000000000create table foo ( a integer not null primary key autoincrement, b integer not null ); insert into foo (b) values (3); insert into foo (b) values (7); select * from foo; tntdb-1.4/test/statement-test.cpp000066400000000000000000000225351354703061500171500ustar00rootroot00000000000000/* * Copyright (C) 2018 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include class TestStmt : public tntdb::IStatement { std::map _values; public: virtual void clear() { _values.clear(); } virtual void setNull(const std::string& col) { _values.erase(col); } virtual void setBool(const std::string& col, bool data) { _values[col] = cxxtools::convert(data); } virtual void setShort(const std::string& col, short data) { _values[col] = cxxtools::convert(data); } virtual void setInt(const std::string& col, int data) { _values[col] = cxxtools::convert(data); } virtual void setLong(const std::string& col, long data) { _values[col] = cxxtools::convert(data); } virtual void setUnsignedShort(const std::string& col, unsigned short data) { _values[col] = cxxtools::convert(data); } virtual void setUnsigned(const std::string& col, unsigned data) { _values[col] = cxxtools::convert(data); } virtual void setUnsignedLong(const std::string& col, unsigned long data) { _values[col] = cxxtools::convert(data); } virtual void setInt32(const std::string& col, int32_t data) { _values[col] = cxxtools::convert(data); } virtual void setUnsigned32(const std::string& col, uint32_t data) { _values[col] = cxxtools::convert(data); } virtual void setInt64(const std::string& col, int64_t data) { _values[col] = cxxtools::convert(data); } virtual void setUnsigned64(const std::string& col, uint64_t data) { _values[col] = cxxtools::convert(data); } virtual void setDecimal(const std::string& col, const tntdb::Decimal& data) { _values[col] = data.toString(); } virtual void setFloat(const std::string& col, float data) { _values[col] = cxxtools::convert(data); } virtual void setDouble(const std::string& col, double data) { _values[col] = cxxtools::convert(data); } virtual void setChar(const std::string& col, char data) { _values[col] = data; } virtual void setString(const std::string& col, const std::string& data) { _values[col] = data; } virtual void setBlob(const std::string& col, const tntdb::Blob& data) { _values[col] = std::string(data.data(), data.size()); } virtual void setDate(const std::string& col, const tntdb::Date& data) { _values[col] = data.getIso(); } virtual void setTime(const std::string& col, const tntdb::Time& data) { _values[col] = data.getIso(); } virtual void setDatetime(const std::string& col, const tntdb::Datetime& data) { _values[col] = data.getIso(); } virtual size_type execute() { return 0; } virtual tntdb::Result select() { return tntdb::Result(); } virtual tntdb::Row selectRow() { return tntdb::Row(); } virtual tntdb::Value selectValue() { return tntdb::Value(); } virtual tntdb::ICursor* createCursor(unsigned fetchsize) { return 0; } std::string value(const std::string& col) const { std::map::const_iterator it = _values.find(col); return it == _values.end() ? std::string() : it->second; } bool isNull(const std::string& col) const { return _values.find(col) == _values.end(); } }; class StatementTest : public cxxtools::unit::TestSuite { public: StatementTest() : cxxtools::unit::TestSuite("statement") { registerMethod("testSetValue", *this, &StatementTest::testSetValue); registerMethod("testClear", *this, &StatementTest::testClear); registerMethod("testSetTimespan", *this, &StatementTest::testSetTimespan); } void testSetValue() { TestStmt* testStmt = new TestStmt(); tntdb::Statement stmt(testStmt); stmt.set("bool", true) .set("short", short(42)) .set("int", int(42)) .set("long", long(45l)) .set("unsignedshort", (unsigned short)33) .set("unsigned", (unsigned)45) .set("unsignedlong", (unsigned long)46) .set("int32", (int32_t)50) .set("unsigned32", (uint32_t)51) .set("int64", (int64_t)52) .set("unsigned64", (uint64_t)53) .set("decimal", tntdb::Decimal("45.456")) .set("float", (float)54) .set("double", (double)55) .set("char", 'X') .set("string", "Hi there") .set("ustring", cxxtools::String("M\xc3\xa4kitalo")) .set("date", tntdb::Date(2018, 5, 3)) .set("time", tntdb::Time(13, 21, 11)) .set("datetime", tntdb::Datetime(2017, 9, 29, 13, 33, 41)); CXXTOOLS_UNIT_ASSERT_EQUALS(testStmt->value("bool"), "true"); CXXTOOLS_UNIT_ASSERT_EQUALS(testStmt->value("short"), "42"); CXXTOOLS_UNIT_ASSERT_EQUALS(testStmt->value("int"), "42"); CXXTOOLS_UNIT_ASSERT_EQUALS(testStmt->value("long"), "45"); CXXTOOLS_UNIT_ASSERT_EQUALS(testStmt->value("unsignedshort"), "33"); CXXTOOLS_UNIT_ASSERT_EQUALS(testStmt->value("unsigned"), "45"); CXXTOOLS_UNIT_ASSERT_EQUALS(testStmt->value("unsignedlong"), "46"); CXXTOOLS_UNIT_ASSERT_EQUALS(testStmt->value("int32"), "50"); CXXTOOLS_UNIT_ASSERT_EQUALS(testStmt->value("unsigned32"), "51"); CXXTOOLS_UNIT_ASSERT_EQUALS(testStmt->value("int64"), "52"); CXXTOOLS_UNIT_ASSERT_EQUALS(testStmt->value("unsigned64"), "53"); CXXTOOLS_UNIT_ASSERT_EQUALS(testStmt->value("decimal"), "45.456"); CXXTOOLS_UNIT_ASSERT_EQUALS(testStmt->value("float"), "54"); CXXTOOLS_UNIT_ASSERT_EQUALS(testStmt->value("double"), "55"); CXXTOOLS_UNIT_ASSERT_EQUALS(testStmt->value("char"), "X"); CXXTOOLS_UNIT_ASSERT_EQUALS(testStmt->value("string"), "Hi there"); CXXTOOLS_UNIT_ASSERT_EQUALS(testStmt->value("ustring"), "M\xc3\xa4kitalo"); CXXTOOLS_UNIT_ASSERT_EQUALS(testStmt->value("date"), "2018-05-03"); CXXTOOLS_UNIT_ASSERT_EQUALS(testStmt->value("time"), "13:21:11.000"); CXXTOOLS_UNIT_ASSERT_EQUALS(testStmt->value("datetime"), "2017-09-29 13:33:41.000"); } void testClear() { TestStmt* testStmt = new TestStmt(); tntdb::Statement stmt(testStmt); stmt.set("bool", true) .set("int", short(42)); CXXTOOLS_UNIT_ASSERT_EQUALS(testStmt->value("bool"), "true"); CXXTOOLS_UNIT_ASSERT_EQUALS(testStmt->value("int"), "42"); stmt.clear(); CXXTOOLS_UNIT_ASSERT_EQUALS(testStmt->value("bool"), ""); CXXTOOLS_UNIT_ASSERT_EQUALS(testStmt->value("int"), ""); } void testSetTimespan() { TestStmt* testStmt = new TestStmt(); tntdb::Statement stmt(testStmt); stmt.set("us", cxxtools::Microseconds(17)) .set("ms", cxxtools::Milliseconds(18)) .set("s", cxxtools::Seconds(19.01234)) .set("m", cxxtools::Minutes(20)) .set("h", cxxtools::Hours(21)) .set("d", cxxtools::Days(22)); CXXTOOLS_UNIT_ASSERT_EQUALS(testStmt->value("us"), "17"); CXXTOOLS_UNIT_ASSERT_EQUALS(testStmt->value("ms"), "18"); CXXTOOLS_UNIT_ASSERT_EQUALS(testStmt->value("s"), "19.01234"); CXXTOOLS_UNIT_ASSERT_EQUALS(testStmt->value("m"), "20"); CXXTOOLS_UNIT_ASSERT_EQUALS(testStmt->value("h"), "21"); CXXTOOLS_UNIT_ASSERT_EQUALS(testStmt->value("d"), "22"); } }; cxxtools::unit::RegisterTest register_StatementTest; tntdb-1.4/test/test-main.cpp000066400000000000000000000025611354703061500160650ustar00rootroot00000000000000/* * Copyright (C) 2010 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "cxxtools/unit/testmain.h" tntdb-1.4/test/test.cpp000066400000000000000000000174151354703061500151470ustar00rootroot00000000000000/* * Copyright (C) 2007 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include class Tester { tntdb::Connection conn; bool keep; public: Tester(const std::string& dburl) : conn(tntdb::connect(dburl)), keep(false) { } void setKeep(bool sw = true) { keep = sw; } bool isKeep() const { return keep; } void createTables(bool postgresql); void insertDataStmt(); void testSelect(); void testSelectRow(); void testSelectValue(); void testSelectByName(); void testSelectRowByName(); void testCursor(); void testCursorByName(); void testBlob(); void dropTables(); void test(bool postgresql); }; void Tester::createTables(bool postgresql) { std::cout << "create tables" << std::endl; try { if (postgresql) conn.execute( "create table tab1 (" " a integer not null primary key," " b bytea not null)" ); else conn.execute( "create table tab1 (" " a integer not null primary key," " b varchar(255) not null)" ); std::cout << "table tab1 created" << std::endl; } catch (const tntdb::Error& e) { std::cerr << "create table failed with error message: " << e.what() << std::endl; } } void Tester::insertDataStmt() { std::cout << "insert data" << std::endl; tntdb::Transaction trans(conn); tntdb::Statement stmt = conn.prepare( "insert into tab1 (a, b)" " values (:a, :b)"); stmt.set("a", 1) .set("b", "one") .execute(); stmt.set("a", 2) .set("b", "two") .execute(); stmt.set("a", 3) .set("b", "three") .execute(); trans.commit(); std::cout << "inserted data into tab1" << std::endl; } void Tester::testSelect() { std::cout << "select data" << std::endl; tntdb::Result res = conn.select( "select a, b" " from tab1" " order by a"); for (tntdb::Result::const_iterator it = res.begin(); it != res.end(); ++it) { int a = (*it)[0]; std::string b = (*it)[1]; std::cout << "a=" << a << "\tb=" << b << " len(b)=" << b.size() << std::endl; } std::cout << "selected" << std::endl; } void Tester::testSelectRow() { std::cout << "select row" << std::endl; tntdb::Row row = conn.selectRow( "select a, b" " from tab1" " where a = (select max(a) from tab1)"); int a = row[0]; std::string b = row[1]; std::cout << "a=" << a << "\tb=" << b << std::endl; } void Tester::testSelectValue() { std::cout << "select value" << std::endl; tntdb::Value max = conn.selectValue( "select max(a) from tab1"); std::cout << "max(a)=" << max.getInt() << std::endl; } void Tester::testSelectByName() { std::cout << "select data by name" << std::endl; tntdb::Result res = conn.select( "select a, b" " from tab1" " order by a"); for (tntdb::Result::const_iterator it = res.begin(); it != res.end(); ++it) { int a = (*it)["a"]; std::string b = (*it)["b"]; std::cout << "a=" << a << "\tb=" << b << std::endl; } std::cout << "selected" << std::endl; } void Tester::testSelectRowByName() { std::cout << "select row by name" << std::endl; tntdb::Row row = conn.selectRow( "select a, b" " from tab1" " where a = (select max(a) from tab1)"); int a = row["a"]; std::string b = row["b"]; std::cout << "a=" << a << "\tb=" << b << std::endl; } void Tester::testCursor() { std::cout << "select data with cursor" << std::endl; tntdb::Statement stmt = conn.prepare( "select a, b" " from tab1" " where a > :value" " order by a"); stmt.set("value", 1); for (tntdb::Statement::const_iterator it = stmt.begin(); it != stmt.end(); ++it) { int a = (*it)[0]; std::string b = (*it)[1]; std::cout << "a=" << a << "\tb=" << b << std::endl; } std::cout << "selected with cursor" << std::endl; } void Tester::testCursorByName() { std::cout << "select data by name with cursor" << std::endl; tntdb::Statement stmt = conn.prepare( "select a, b" " from tab1" " where a > :value" " order by a"); stmt.set("value", 1); for (tntdb::Statement::const_iterator it = stmt.begin(); it != stmt.end(); ++it) { int a = (*it)["a"]; std::string b = (*it)["b"]; std::cout << "a=" << a << "\tb=" << b << std::endl; } std::cout << "selected with cursor" << std::endl; } void Tester::testBlob() { std::cout << "blob insert" << std::endl; tntdb::Statement stmt = conn.prepare( "insert into tab1 (a, b)" " values (:a, :b)"); const char* bindata = "\1\2\3\0abc"; tntdb::Blob blob1(bindata, 7); std::cout << "blob1.size()=" << blob1.size() << std::endl; stmt.set("a", 10) .set("b", blob1) .execute(); cxxtools::Hdostream o; std::cout << "blob select" << std::endl; tntdb::Blob blob2 = conn.selectValue("select b from tab1 where a = 10").getBlob(); o << std::string(blob2.data(), blob2.size()) << std::flush; std::string blobData1(blob1.data(), blob1.size()); std::string blobData2(blob2.data(), blob2.size()); std::cout << "blob1==blob2: " << (blobData1 == blobData2) << " size=" << blobData2.size() << std::endl; if (blobData1 != blobData2) std::cerr << "blob failed" << std::endl; } void Tester::dropTables() { std::cout << "drop table" << std::endl; conn.execute("drop table tab1"); std::cout << "table tab1 dropped" << std::endl; } void Tester::test(bool postgresql) { createTables(postgresql); insertDataStmt(); testSelect(); testSelectRow(); testSelectValue(); testSelectByName(); testSelectRowByName(); testCursor(); testCursorByName(); testBlob(); if (!keep) dropTables(); else std::cout << "drop tables skipped" << std::endl; } int main(int argc, char* argv[]) { try { cxxtools::Arg keep(argc, argv, 'k'); cxxtools::Arg droponly(argc, argv, 'd'); cxxtools::Arg postgresql(argc, argv, 'p'); log_init(); if (argc < 2) { std::cerr << "usage: " << argv[0] << " dburl" << std::endl; return -1; } Tester tester(argv[1]); tester.setKeep(keep); if (droponly) tester.dropTables(); else tester.test(postgresql); std::cout << "success" << std::endl; } catch (const std::exception& e) { std::cerr << e.what() << std::endl; } } tntdb-1.4/test/timespan-test.cpp000066400000000000000000000065171354703061500167660ustar00rootroot00000000000000/* * Copyright (C) 2016 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include log_define("tntdb.unit.timespan") class TntdbTimespanTest : public cxxtools::unit::TestSuite { tntdb::Connection conn; tntdb::Statement del; public: TntdbTimespanTest() : cxxtools::unit::TestSuite("timespan") { registerMethod("testTimespan", *this, &TntdbTimespanTest::testTimespan); } void setUp() { if (!conn) { const char* dburl = getenv("TNTDBURL"); if (!dburl) dburl = "sqlite:test.db"; log_info("testing with dburl=" << dburl); conn = tntdb::connect(dburl); del = conn.prepare("delete from tntdbtest"); } } void tearDown() { del.execute(); } void testTimespan() { tntdb::Statement ins = conn.prepare( "insert into tntdbtest(intcol, doublecol, unsignedcol) values(:ts1, :ts2, :ts3)"); ins.set("ts1", cxxtools::Milliseconds(2000)) .set("ts2", cxxtools::Seconds(3.5)) .set("ts3", cxxtools::Days(2)) .execute(); tntdb::Statement sel = conn.prepare( "select intcol, doublecol, unsignedcol from tntdbtest"); tntdb::Row row = sel.selectRow(); cxxtools::Milliseconds ts1; cxxtools::Seconds ts2; cxxtools::Days ts3; row.get(ts1) .get(ts2) .get(ts3); CXXTOOLS_UNIT_ASSERT_EQUALS(ts1, cxxtools::Milliseconds(2000)); CXXTOOLS_UNIT_ASSERT_EQUALS(ts2, cxxtools::Seconds(3.5)); CXXTOOLS_UNIT_ASSERT_EQUALS(ts3, cxxtools::Days(2)); int v1; double v2; unsigned v3; row.get(v1) .get(v2) .get(v3); CXXTOOLS_UNIT_ASSERT_EQUALS(v1, 2000); CXXTOOLS_UNIT_ASSERT_EQUALS(v2, 3.5); CXXTOOLS_UNIT_ASSERT_EQUALS(v3, 2); } }; cxxtools::unit::RegisterTest register_TntdbTimespanTest; tntdb-1.4/test/tntdb-locktest.cpp000066400000000000000000000046721354703061500171320ustar00rootroot00000000000000/* * Copyright (C) 2013 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include log_define("locktest") int main(int argc, char* argv[]) { try { cxxtools::Arg wait(argc, argv, 'w', 0); cxxtools::Arg readLock(argc, argv, 'r'); if (argc < 3) { std::cerr << "usage: " << argv[0] << " dburl {tables}\n" << std::endl; return 1; } const char* dburl = argv[1]; log_init(); std::cout << "connect" << std::endl; tntdb::Connection conn = tntdb::connect(dburl); std::cout << "start transaction" << std::endl; tntdb::Transaction trans(conn); for (int a = 2; a < argc; ++a) { const char* tablename = argv[a]; log_info("lock table " << tablename); trans.lockTable(tablename, !readLock); log_info("table " << tablename << " locked"); cxxtools::Thread::sleep(wait); } trans.commit(); log_info("transaction finished"); } catch (const std::exception& e) { std::cerr << e.what() << std::endl; } } tntdb-1.4/test/types-test.cpp000066400000000000000000000430251354703061500163050ustar00rootroot00000000000000/* * Copyright (C) 2010 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include log_define("tntdb.unit.types") #define BEGIN_TEST(T, col) \ const std::string colName = col; \ bool isNotNull = false; \ tntdb::Statement::const_iterator cursor; \ tntdb::Statement ins = conn.prepare( \ "insert into tntdbtest(" col ") values(:" col ")"); \ tntdb::Statement sel = conn.prepare( \ "select " col " from tntdbtest"); \ tntdb::Value dbvalue; \ T res; #define TEST(val) \ del.execute(); \ ins.set(colName, val).execute(); \ dbvalue = sel.selectValue(); \ isNotNull = dbvalue.get(res); \ CXXTOOLS_UNIT_ASSERT(isNotNull); \ CXXTOOLS_UNIT_ASSERT_EQUALS(val, res); \ dbvalue = sel.select()[0][0]; \ isNotNull = dbvalue.get(res); \ CXXTOOLS_UNIT_ASSERT(isNotNull); \ CXXTOOLS_UNIT_ASSERT_EQUALS(val, res); \ cursor = sel.begin(4); \ CXXTOOLS_UNIT_ASSERT(cursor != sel.end()); \ isNotNull = (*cursor)[0].get(res); \ CXXTOOLS_UNIT_ASSERT(isNotNull); \ CXXTOOLS_UNIT_ASSERT_EQUALS(val, res); #define TESTEQ(val) \ del.execute(); \ ins.set(colName, val).execute(); \ dbvalue = sel.selectValue(); \ isNotNull = dbvalue.get(res); \ CXXTOOLS_UNIT_ASSERT(isNotNull); \ CXXTOOLS_UNIT_ASSERT(val == res); \ dbvalue = sel.select()[0][0]; \ isNotNull = dbvalue.get(res); \ CXXTOOLS_UNIT_ASSERT(isNotNull); \ CXXTOOLS_UNIT_ASSERT(val == res); \ cursor = sel.begin(4); \ CXXTOOLS_UNIT_ASSERT(cursor != sel.end()); \ isNotNull = (*cursor)[0].get(res); \ CXXTOOLS_UNIT_ASSERT(isNotNull); \ CXXTOOLS_UNIT_ASSERT(val == res); #define TESTFLOAT(val) \ del.execute(); \ ins.set(colName, val).execute(); \ dbvalue = sel.selectValue(); \ isNotNull = dbvalue.get(res); \ CXXTOOLS_UNIT_ASSERT(isNotNull); \ CXXTOOLS_UNIT_ASSERT(val / res >= .9999 && val / res <= 1.0001); \ dbvalue = sel.select()[0][0]; \ isNotNull = dbvalue.get(res); \ CXXTOOLS_UNIT_ASSERT(isNotNull); \ CXXTOOLS_UNIT_ASSERT(val / res >= .9999 && val / res <= 1.0001); \ cursor = sel.begin(4); \ CXXTOOLS_UNIT_ASSERT(cursor != sel.end()); \ isNotNull = (*cursor)[0].get(res); \ CXXTOOLS_UNIT_ASSERT(isNotNull); \ CXXTOOLS_UNIT_ASSERT(val == res); #define TESTDT(val) \ del.execute(); \ ins.set(colName, val).execute(); \ dbvalue = sel.selectValue(); \ isNotNull = dbvalue.get(res); \ if (isNotNull) \ { \ CXXTOOLS_UNIT_ASSERT(!res.isNull()); \ CXXTOOLS_UNIT_ASSERT_EQUALS(val.getIso(), res.getIso()); \ } \ else \ CXXTOOLS_UNIT_ASSERT(val.isNull()); \ dbvalue = sel.select()[0][0]; \ isNotNull = dbvalue.get(res); \ if (isNotNull) \ { \ CXXTOOLS_UNIT_ASSERT(!res.isNull()); \ CXXTOOLS_UNIT_ASSERT_EQUALS(val.getIso(), res.getIso()); \ } \ else \ CXXTOOLS_UNIT_ASSERT(val.isNull()); class TntdbTypesTest : public cxxtools::unit::TestSuite { tntdb::Connection conn; tntdb::Statement del; public: TntdbTypesTest() : cxxtools::unit::TestSuite("types") { registerMethod("testLimits", *this, &TntdbTypesTest::testLimits); registerMethod("testNull", *this, &TntdbTypesTest::testNull); registerMethod("testBool", *this, &TntdbTypesTest::testBool); registerMethod("testShort", *this, &TntdbTypesTest::testShort); registerMethod("testInt", *this, &TntdbTypesTest::testInt); registerMethod("testLong", *this, &TntdbTypesTest::testLong); registerMethod("testUnsignedShort", *this, &TntdbTypesTest::testUnsignedShort); registerMethod("testUnsigned", *this, &TntdbTypesTest::testUnsigned); registerMethod("testUnsignedLong", *this, &TntdbTypesTest::testUnsignedLong); registerMethod("testInt32", *this, &TntdbTypesTest::testInt32); registerMethod("testUint32", *this, &TntdbTypesTest::testUint32); registerMethod("testInt64", *this, &TntdbTypesTest::testInt64); registerMethod("testUint64", *this, &TntdbTypesTest::testUint64); registerMethod("testDecimal", *this, &TntdbTypesTest::testDecimal); registerMethod("testFloat", *this, &TntdbTypesTest::testFloat); registerMethod("testFloatFromDecimal", *this, &TntdbTypesTest::testFloatFromDecimal); registerMethod("testDouble", *this, &TntdbTypesTest::testDouble); registerMethod("testChar", *this, &TntdbTypesTest::testChar); registerMethod("testString", *this, &TntdbTypesTest::testString); registerMethod("testBlob", *this, &TntdbTypesTest::testBlob); registerMethod("testDate", *this, &TntdbTypesTest::testDate); registerMethod("testTime", *this, &TntdbTypesTest::testTime); registerMethod("testDatetime", *this, &TntdbTypesTest::testDatetime); registerMethod("testSequence", *this, &TntdbTypesTest::testSequence); registerMethod("testFloatNan", *this, &TntdbTypesTest::testFloatNan); registerMethod("testDoubleNan", *this, &TntdbTypesTest::testDoubleNan); } void setUp() { if (!conn) { const char* dburl = getenv("TNTDBURL"); if (!dburl) dburl = "sqlite:test.db"; log_info("testing with dburl=" << dburl); conn = tntdb::connect(dburl); del = conn.prepare("delete from tntdbtest"); } } void tearDown() { del.execute(); } void testBool() { BEGIN_TEST(bool, "boolcol"); TEST(true); TEST(false); } void testShort() { BEGIN_TEST(short, "shortcol"); TEST(static_cast(42)); TEST(static_cast(-123)); TEST(std::numeric_limits::max()); TEST(std::numeric_limits::min()); } void testInt() { BEGIN_TEST(int, "intcol"); TEST(static_cast(42)); TEST(static_cast(-123)); TEST(std::numeric_limits::max()); TEST(std::numeric_limits::min()); } void testLong() { BEGIN_TEST(long, "longcol"); TEST(static_cast(42)); TEST(static_cast(-123)); TEST(std::numeric_limits::max()); TEST(std::numeric_limits::min()); } void testUnsignedShort() { BEGIN_TEST(unsigned short, "unsignedshortcol"); TEST(static_cast(42)); TEST(std::numeric_limits::max()); TEST(std::numeric_limits::min()); } void testUnsigned() { BEGIN_TEST(unsigned, "unsignedcol"); TEST(static_cast(42)); TEST(std::numeric_limits::max()); TEST(std::numeric_limits::min()); } void testUnsignedLong() { BEGIN_TEST(unsigned long, "unsignedlongcol"); TEST(static_cast(42)); TEST(std::numeric_limits::max()); TEST(std::numeric_limits::min()); } void testInt32() { BEGIN_TEST(int32_t, "int32col"); TEST(static_cast(42)); TEST(static_cast(-123)); TEST(std::numeric_limits::max()); TEST(std::numeric_limits::min()); } void testUint32() { BEGIN_TEST(uint32_t, "uint32col"); TEST(static_cast(42)); TEST(std::numeric_limits::max()); TEST(std::numeric_limits::min()); } void testInt64() { BEGIN_TEST(int64_t, "int64col"); TEST(static_cast(42)); TEST(static_cast(-123)); TEST(std::numeric_limits::max()); TEST(std::numeric_limits::min()); } void testUint64() { BEGIN_TEST(uint64_t, "uint64col"); TEST(static_cast(42)); TEST(std::numeric_limits::max()); TEST(std::numeric_limits::min()); } void testDecimal() { BEGIN_TEST(tntdb::Decimal, "decimalcol"); TEST(tntdb::Decimal(456, 8)); TEST(tntdb::Decimal(456, -4)); TEST(tntdb::Decimal(-456, 8)); } void testFloat() { BEGIN_TEST(float, "floatcol"); TESTFLOAT(static_cast(42)); TESTFLOAT(static_cast(-123)); TESTFLOAT(std::numeric_limits::max() * .999999); TESTFLOAT(std::numeric_limits::min() * 1.00001); TEST(std::numeric_limits::infinity()); TEST(-std::numeric_limits::infinity()); } void testFloatFromDecimal() { BEGIN_TEST(float, "decimalcol"); TESTFLOAT(static_cast(42)); TESTFLOAT(static_cast(-123)); } void testDouble() { BEGIN_TEST(double, "doublecol"); TESTFLOAT(static_cast(42)); TESTFLOAT(static_cast(-123)); TESTFLOAT(std::numeric_limits::max() * .999999); TESTFLOAT(std::numeric_limits::min() * 1.00001); TEST(std::numeric_limits::infinity()); TEST(-std::numeric_limits::infinity()); } void testChar() { BEGIN_TEST(char, "charcol"); TEST('A'); TEST('Z'); TEST('\n'); } void testString() { BEGIN_TEST(std::string, "stringcol"); TEST(std::string("Hello\n")); TEST(std::string("M\xc3\xa4kitalo")); } void testBlob() { BEGIN_TEST(tntdb::Blob, "blobcol"); tntdb::Blob blobval = tntdb::Blob("\0\1\2\3\0xff", 5); TESTEQ(blobval); } void testDate() { BEGIN_TEST(tntdb::Date, "datecol"); TESTDT(tntdb::Date(2010, 2, 15)); TESTDT(tntdb::Date()); } void testTime() { BEGIN_TEST(tntdb::Time, "timecol"); TESTDT(tntdb::Time(20, 9, 31, 12)); TESTDT(tntdb::Time()); } void testDatetime() { BEGIN_TEST(tntdb::Datetime, "datetimecol"); TESTDT(tntdb::Datetime(2010, 2, 15, 20, 9, 31, 12)); TESTDT(tntdb::Datetime()); } void testSequence() { del.execute(); tntdb::Statement ins = conn.prepare( "insert into tntdbtest(intcol) values(:intcol)"); ins.set("intcol", 42) .execute(); long serialval = conn.lastInsertId("tntdbtest_seq"); tntdb::Statement sel = conn.prepare( "select id from tntdbtest"); tntdb::Value dbvalue = sel.selectValue(); long serialres = -1; dbvalue.get(serialres); CXXTOOLS_UNIT_ASSERT_EQUALS(serialval, serialres); } void testLimits() { del.execute(); tntdb::Statement ins = conn.prepare( "insert into tntdbtest(" " intcol, longcol, unsignedcol, unsignedlongcol," " int32col, uint32col, int64col, uint64col," " floatcol, doublecol)" " values(" " :intcol, :longcol, :unsignedcol, :unsignedlongcol," " :int32col, :uint32col, :int64col, :uint64col," " :floatcol, :doublecol)"); int intval = std::numeric_limits::max(); long longval = std::numeric_limits::max(); unsigned uval = std::numeric_limits::max(); unsigned long ulongval = std::numeric_limits::max(); int32_t int32val = std::numeric_limits::max(); uint32_t uint32val = std::numeric_limits::max(); int64_t int64val = std::numeric_limits::max(); uint64_t uint64val = std::numeric_limits::max(); float floatval = std::numeric_limits::max() * .999999; double doubleval = std::numeric_limits::max() * .999999; ins.set("intcol", intval) .set("longcol", longval) .set("unsignedcol", uval) .set("unsignedlongcol", ulongval) .set("int32col", int32val) .set("uint32col", uint32val) .set("int64col", int64val) .set("uint64col", uint64val) .set("floatcol", floatval) .set("doublecol", doubleval) .execute(); int intres = 0; long longres = 0; unsigned ures = 0; unsigned long ulongres = 0; int32_t int32res = 0; uint32_t uint32res = 0; int64_t int64res = 0; uint64_t uint64res = 0; float floatres = 0; double doubleres = 0; tntdb::Statement sel = conn.prepare( "select" " intcol, longcol, unsignedcol, unsignedlongcol," " int32col, uint32col, int64col, uint64col," " floatcol, doublecol" " from tntdbtest"); tntdb::Row row = sel.selectRow(); row[0].get(intres); row[1].get(longres); row[2].get(ures); row[3].get(ulongres); row[4].get(int32res); row[5].get(uint32res); row[6].get(int64res); row[7].get(uint64res); row[8].get(floatres); row[9].get(doubleres); float fq = floatval / floatres; double dq = doubleval / doubleres; CXXTOOLS_UNIT_ASSERT_EQUALS(intval, intres); CXXTOOLS_UNIT_ASSERT_EQUALS(longval, longres); CXXTOOLS_UNIT_ASSERT_EQUALS(uval, ures); CXXTOOLS_UNIT_ASSERT_EQUALS(ulongval, ulongres); CXXTOOLS_UNIT_ASSERT_EQUALS(int32val, int32res); CXXTOOLS_UNIT_ASSERT_EQUALS(uint32val, uint32res); CXXTOOLS_UNIT_ASSERT_EQUALS(int64val, int64res); CXXTOOLS_UNIT_ASSERT_EQUALS(uint64val, uint64res); CXXTOOLS_UNIT_ASSERT(fq >= .9999 && fq <= 1.0001); CXXTOOLS_UNIT_ASSERT(dq >= .9999 && dq <= 1.0001); } void testNull() { tntdb::Statement ins = conn.prepare( "insert into tntdbtest(intcol, longcol)" " values(:intcol, :longcol)"); long longval = 43; ins.setNull("intcol") .set("longcol", longval) .execute(); int intres; long longres; tntdb::Statement sel = conn.prepare( "select intcol, longcol" " from tntdbtest"); tntdb::Row row = sel.selectRow(); bool intnotnull = row[0].get(intres); bool longnotnull = row[1].get(longres); CXXTOOLS_UNIT_ASSERT(!intnotnull); CXXTOOLS_UNIT_ASSERT(longnotnull); } void testFloatNan() { BEGIN_TEST(float, "floatcol"); float n = std::numeric_limits::quiet_NaN(); del.execute(); \ ins.set("floatcol", n).execute(); dbvalue = sel.selectValue(); isNotNull = dbvalue.get(res); CXXTOOLS_UNIT_ASSERT(isNotNull); CXXTOOLS_UNIT_ASSERT(res != res); } void testDoubleNan() { BEGIN_TEST(double, "doublecol"); double n = std::numeric_limits::quiet_NaN(); del.execute(); \ ins.set("doublecol", n).execute(); dbvalue = sel.selectValue(); isNotNull = dbvalue.get(res); CXXTOOLS_UNIT_ASSERT(isNotNull); CXXTOOLS_UNIT_ASSERT(res != res); } }; cxxtools::unit::RegisterTest register_TntdbTypesTest; tntdb-1.4/test/value-test.cpp000066400000000000000000000073541354703061500162620ustar00rootroot00000000000000/* * Copyright (C) 2018 Tommi Maekitalo * * This library 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 2.1 of the License, or (at your option) any later version. * * As a special exception, you may use this file as part of a free * software library without restriction. Specifically, if other files * instantiate templates or use macros or inline functions from this * file, or you compile this file and link it with other files to * produce an executable, this file does not by itself cause the * resulting executable to be covered by the GNU General Public * License. This exception does not however invalidate any other * reasons why the executable file might be covered by the GNU Library * General Public License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include class ValueTest : public cxxtools::unit::TestSuite { public: ValueTest() : cxxtools::unit::TestSuite("value") { registerMethod("testReadValue", *this, &ValueTest::testReadValue); registerMethod("testTimespan", *this, &ValueTest::testTimespan); } void testReadValue() { tntdb::Value v; { v = tntdb::Value(new tntdb::ValueImpl("true")); bool r = false; v.get(r); CXXTOOLS_UNIT_ASSERT_EQUALS(r, true); } { v = tntdb::Value(new tntdb::ValueImpl("42")); int r = 3; v.get(r); CXXTOOLS_UNIT_ASSERT_EQUALS(r, 42); } } void testTimespan() { tntdb::Value v; { v = tntdb::Value(new tntdb::ValueImpl("15")); cxxtools::Microseconds r; v.get(r); CXXTOOLS_UNIT_ASSERT_EQUALS(r, cxxtools::Microseconds(15)); } { v = tntdb::Value(new tntdb::ValueImpl("15")); cxxtools::Milliseconds r; v.get(r); CXXTOOLS_UNIT_ASSERT_EQUALS(r, cxxtools::Milliseconds(15)); } { v = tntdb::Value(new tntdb::ValueImpl("15")); cxxtools::Seconds r; v.get(r); CXXTOOLS_UNIT_ASSERT_EQUALS(r, cxxtools::Seconds(15)); } { v = tntdb::Value(new tntdb::ValueImpl("15")); cxxtools::Minutes r; v.get(r); CXXTOOLS_UNIT_ASSERT_EQUALS(r, cxxtools::Minutes(15)); } { v = tntdb::Value(new tntdb::ValueImpl("15")); cxxtools::Hours r; v.get(r); CXXTOOLS_UNIT_ASSERT_EQUALS(r, cxxtools::Hours(15)); } { v = tntdb::Value(new tntdb::ValueImpl("15")); cxxtools::Days r; v.get(r); CXXTOOLS_UNIT_ASSERT_EQUALS(r, cxxtools::Days(15)); } } }; cxxtools::unit::RegisterTest register_ValueTest;