ADDED Bakefiles.bkgen Index: Bakefiles.bkgen ================================================================== --- /dev/null +++ Bakefiles.bkgen @@ -0,0 +1,21 @@ + + + + ./mysql++.bkl + + + + + autoconf,mingw,msvs2003prj,msvs2005prj,xcode2 + + + + -o$(INPUT_FILE_DIR)/Makefile.mingw + + + -ovc2003/mysql++.sln + + + -ovc2005/mysql++.sln + + ADDED COPYING.txt Index: COPYING.txt ================================================================== --- /dev/null +++ COPYING.txt @@ -0,0 +1,10 @@ +The MySQL++ library proper and the reference manual derived from +comments in the library source code are licensed under the GNU Lesser +General Public License. A copy is provided in this directory, in the +file LICENSE.txt. + +The MySQL++ User Manual is licensed under a unique license derived from +the Linux Documentation Project License. (The only changes are due to +the fact that the User Manual isn't actually part of the LDP, so a lot +of the language in the LDPL doesn't make sense when applied to the user +manual.) This license is provided in the file doc/userman/LICENSE.txt. DELETED COPYRIGHT Index: COPYRIGHT ================================================================== --- COPYRIGHT +++ /dev/null @@ -1,23 +0,0 @@ -The Mysql++ API is copyright 1998 by Kevin Atkinson and is released -under the LGPL license for now. - -The intent of doing this is allow developers to use my library to -develop commercial programs and to allow it it be distributed with -commercial databases. - -However if you do use it to develop a commercial program a small -donation to me would be greatly appreshated. Your donation will will -encourage me to continue to work on improving this API and also -encourage me to contune to keep it under the LGPL. Please send -donations too. - Kevin Atkinson - 7962 Helmart Dr. - Laurel, MD 20723 - -I reserve the right to change the license to future versions of the -library if I do not get suffecent pay-back to my work. However, it is -my promise to you that it will never become more restrictive than the -GPL (not LGPL) licence. - -You can contact me at kevinatk@home.com or (301) 498-3290 or at -7962 Helmart Dr./Laurel, MD 20723. ADDED CREDITS.txt Index: CREDITS.txt ================================================================== --- /dev/null +++ CREDITS.txt @@ -0,0 +1,93 @@ +MySQL++ was created by Kevin Atkinson during 1998. From version 1.0 +(released in June 1999) through 1.7.9 (May 2001), the primary maintainer +was Sinisa Milivojevic . Neither Kevin nor Sinisa +are currently involved in MySQL++ development. The current maintainer +is Warren Young , starting with version 1.7.10 in +August of 2004. + +For a fuller account of the library's history, see the first chapter +of the user manual. For the nitty-gritty details, see the ChangeLog +in the root package directory. ChangeLog items since 1.7.9 that +aren't attributed to anyone else were done by Warren Young. + + +Other contributors of note since 1.7.10: + + Chris Frey : Lots of GCC warning fixes for the + bleeding-edge compiler versions, and Gentoo ebuild support. + + Mark Meredino : Several fixes and + additions, including a lot of work on Microsoft Visual C++ + compatibility, and discoveries made while spelunking in the + library. + + Evan Wies : Contributed several C++ code + style cleanups. + + Arnon Jalon : Added the multi-query + result set handling features, and examples/multiquery.cpp to + demonstrate it. + + Korolyov Ilya has submitted several patches in many different + areas of the library. + + Remi Collet is maintaining offical RPMs + for Fedora, with other systems on the way. His work has improved + the RPM spec file we distribute greatly. + + Joel Fielder came up with the + original idea for Query::for_each() and Query::store_in(), + provided the basis for examples/for_each.cpp, and provided a fix + for exception flag propagation in Query. + + Jim Wallace demonstrated the need + for BadQuery::errnum(), and contributed the patches and also + examples/deadlock.cpp to test that this feature does what it is + supposed to. + + Jonathan Wakely rebuilt my original versions + of ConnectionPool, RefCountedPointer, and RefCountedBuffer. + They're now simpler and safer. He also created the numeric + conversion logic in lib/mystring.h introduced in v3.0. + + +Here are the personal credits from the old 1.7.9 documentation, +apparently written by Kevin Atkinson: + + Chris Halverson - For helping me get it to compile under Solaris. + + Fredric Fredricson - For a long talk about automatic conversions. + + Michael Widenius - MySQL developer who has been very supportive of + my efforts. + + Paul J. Lucas - For the original idea of treating the query object + like a stream. + + Scott Barron - For helping me with the shared libraries. + + Jools Enticknap - For giving me the Template Queries idea. + + M. S. Sriram - For a detailed dission of how the Template Queries + should be implemented, the suggestion to throw exceptions on bad + queries, and the idea of having a back-end independent query + object (ie SQLQuery). + + Sinisa Milivojevic - For becoming the new offical maintainer. + + D. Hawkins and E. Loic for their autoconf + automake contribution. + + +See the ChangeLog for further credits, and details about the differences +between the many versions of this library. + + +Please do not email any of these people with general questions about +MySQL++. All of us who are still active in MySQL++ development read the +mailing list, so questions sent there do get to us: + + http://lists.mysql.com/plusplus + +The mailing list is superior to private email because the answers are +archived for future questioners to find, and because you are likely to +get answers from more people. Index: ChangeLog ================================================================== --- ChangeLog +++ ChangeLog @@ -1,38 +1,2658 @@ -1999-10-15 Sinisa Milivojevic - -* Changed version to 1.2 -* First offical release. Version 1.0 and 1.1 were releases by Sinisa - before I (Kevin Atkinson) made him the offical maintainer, -* Many manual fixes. -* Changed README and Changelog -* Changed source to be compilable by gcc 2.95.xx, tribute to Kevin - Atkinson -* Added methods in Connection class which are necessary for - fullfilling administrative functions with MySQL -* Added many bug fixes in code pertaining to missing class - initializers , as notified by Michael Rendell -* Sinisa Milivojevic is now the offical - maintainer. - - -1999-08-02 Sinisa Milivojevic - -* Changed version to 1.1 -* Added several bug fixes -* Fixed memory leak problems and variables overlapping problems. -* Added automake and autoconf support by loic@net.fr -* Added Makefile for manual -* Added support for cygwin -* Added example sinisa_ex (let modesty prevail) which used to crash a - lot when memory allocation, memory leak and overlap problems were - present. Smooth running of this example proves that all those bugs are - fixed -* Changed manual -* Cheanged README -* Many other smaller things - -1999-06-09 Michael Widenius - -* Changed version to 1.0 -* Added patches from Orion Poplawski to support the - UnixWare 7.0 compiler +3.0.3, 2008.05.11 (r2284) + + o Fixed query well-formedness handling in Query::store() and use(). + It was quietly eating these errors, confusing them with the + no-results case. + + o Fixed examples/cpool.cpp to build without thread support. + + o No longer hiding all stdint.h typedefs inside namespace mysqlpp. + + o Fixed mysqlpp::String comparisons of empty strings against + nonempty strings; if the empty string was on the left hand side, + it would succeed because it was only comparing against characters + in the empty side, which matches everything. (Fixes bug 11588.) + + +3.0.2, 2008.04.13 (r2275) + + o Increased float to string conversion precision from 7 to 9 and + double from 16 to 17 digits. Previous values weren't enough + near the maximum values that each can hold. + + o Replaced Query's safe bool mechanism with an override of + basic_ios::operator void*() to avoid a conflict between the + two mechanisms. As the base class version isn't virtual, + this is arguably evil, but it should be harmless in typical use. + Besides, testing Query in bool context usually isn't the right + thing anyway: test the result set instead. + + o Made ConnectionPool::grab() virtual. + + o Overriding ConnectionPool::grab() and release() in + examples/cpool.cpp to show how to do connection-in-use count + limiting. Also, added a few more output indicator states to + allow one to better understand program flow. + + +3.0.1, 2008.03.23 (r2263) + + o String objects can now be compared to mysqlpp::null directly. + + o Added a template operator== and operator!= to String, syntactic + sugar for the existing String::compare() methods. + + o String::compare() now returns 0 ("equal") when one of the + strings is an uninitialized String() (no refcounted buffer) + and the other is empty. It used to consider any initialized + string greater than an uninitted one. An uninitialized String + appears empty, though, so this was incorrect. + + o Made Connection::thread_aware(), thread_start() and thread_end() + static methods, so they can be called before you create your + first connection. Ditto for DBDriver versions of these methods. + + o Calling Connection::thread_start() and thread_end() in + examples/cpool.cpp, as appropriate. Above changes were necessary + to make this work sensibly. + + o Made ConnectionPool::release() virtual, so your pool subclass can + override it. + + o Added ConnectionPool::size(), so a subclass can know the current + number of extant connections. + + o No longer single-quoting NOW() call generated for default + init of DateTime type when building queries from SSQLS objects + in Query::insert(), replace() and update(). The template query + and stream interfaces of Query treated NOW() correctly already. + + o Fixed a bug that left SSQLS::table_override_ uninitted if + you used certain of the generated ctors or set() member + functions instead of others used by the examples. This could + cause a crash any time you caused SSQLS.table() to be called, + such as when passing the SSQLS to Query::insert(). + + o Minor memset bug fixed in test/uds.cpp. Patch by Dave Jones. + + +3.0.0, 2008.02.29 (r2236) The "Giant Leap Forward" release + + THIS IS NOT A DROP-IN REPLACEMENT FOR MySQL++ v2.x! + + You will have to recompile your program against this version + of the library, and you will almost certainly have to make code + changes as well. Please see these sections in the user manual + for information on migrating your code to this new version: + + http://tangentsoft.net/mysql++/doc/html/userman/breakages.html#api-3.0.0 + http://tangentsoft.net/mysql++/doc/html/userman/breakages.html#abi-3.0.0 + + o Added ConnectionPool class, primarily to let multithreaded + programs share a set of Connection objects safely in situations + where it isn't acceptable to have a Connection per thread. + + o Created examples/cpool.cpp to demonstrate this new class. + + o Added RefCountedPointer template, which provides automatic + memory management and data sharing. It's not intended + for use outside of MySQL++ itself, but it's the mechanism + behind everything below where reference counting is mentioned. + I created the initial version of it, but Jonathan Wakely almost + completely rebuilt it, and Joseph Artsimovich provided helpful + commentary and advice as well. + + o Many improvements to Specialized SQL Structures (SSQLS): + + - Renamed custom* to ssqls*. There's still a custom.h which + #includes ssqls.h for you, but it's only intended to ease + the transition to the new name. It will go away in a future + release, probably as soon as v3.1. + + - SSQLSes are finally compatible with Null<>-wrapped types. This + feature is based loosely on the "Waba" patch posted to the + mailing list back in the v2.0 days, but extended to allow + Null types for key fields. (The Waba patch only allowed + these types in non-key fields.) + + - It's no longer necessary to define a different SSQLS for each + different field set you use in queries. That is to say, + you can define an SSQLS for an entire table and store just a + subset of the table in it now, with the other fields keeping + default values. Removed examples/custom6.cpp, as custom1.cpp + can now demonstrate the same thing, implicitly. + + - An SSQLS's field order no longer has to match the order of + fields in the result set it is populated from. + + - As a result of previous, removed sql_create_c_order_* macros; + they have no purpose now. + + - Removed order parameters from sql_create_complete_*, which now + gives it the same functionality as sql_create_c_names_* so + removed the latter, too. + + - Removed "basic" variants of SSQLS creation macros. They've + been unofficially deprecated by dint of being all but + undocumented and unexemplified for a very long time now. + + - It's now possible to use mysqlpp::String, Date, DateTime, and + Time types in the key field positions in an SSQLS as they + now support the necessary comparison interfaces. + + - If you use a floating-point data type in one of the key field + positions, it no longer uses exact comparison logic. Instead, + it now does [in]equality comparisons by testing whether the + difference between two floating-point values is less than a + configurable threshold defaulting to 0.00001. + + - You can now use 'bool' type in an SSQLS. + + - Renamed _table static member variable in each SSQLS to table_ + and made it private. There are now public setter and getter + methods, table(). + + - Added per-instance table name overriding via instance_table() + setter. table() getter returns static version if this is not + set, so it's still a global setting by default. + + o You can now use mysqlpp::null as a template query parameter to + get a SQL null. + + o Replaced template ColData_Tmpl: + + - Used to have typedef ColData_Tmpl MutableColData. + It was used only once within MySQL++ itself, and was never + documented as a class for end users. This one use within + the library was a crock, so we just replaced this use with + std::string and removed the typedef. + + - This left just one use of ColData_Tmpl, instantiating it + with the MySQL++ utility class const_string, basically a + clone of std::string with all the mutating features removed. + Folded the functionality of const_string into the template, + renamed the result to String, and deleted the const_string + class. It'd be a complete std::string replacement -- with + SQL-related enhancements -- if it were modifiable, but MySQL++ + doesn't need it to be modifiable. Yet, it's still the closest + thing MySQL++ has to its own string type; thus the name. + + - Replaced its internal buffer management with a much more + clever reference counted scheme. This shows its greatest + advantage in the return from Row::operator[](), which for + technical reasons must return by value, not by reference + as is more common. This lets you pass around Strings by + value while having the efficiency of reference semantics. + This can be important with large return values, like BLOBs. + + - Converting String to numeric types (ints, floats...) uses a + new, cleaner system by Jonathan Wakely. Unless you were + abusing weaknesses in the old system, you won't see a + difference. It's just more robust and flexible. + + o Redesigned SQLString: + + - It used to derive from std::string, and while MySQL++'s + internals did use it in place of std::string, these places + didn't take advantage of the additional features offered + by SQLString. So, replaced all those uses with std::string. + + - All the remaining uses are MySQL++ public interfaces that + need to be able to accept any of many different data types, + and we want that data to be automatically converted to a + SQL-compatible string form. Because it no longer has the + parentage to be a general-purpose string type and MySQL++ has + a new contender for that role (String), renamed SQLString to + SQLTypeAdapter to reflect its new, limited purpose. ("STA" + for short.) + + - Since we don't have the std::string base class to manage the + string buffer any more, using the same reference counted + buffer mechanism as String. In addition to saving code by + not creating yet another buffer management mechanism, it means + objects of the two classes can share a buffer when you assign + one to the other or pass one to the other's copy ctor. + + - Added many more conversion ctors. + + - STA interfaces using the 'char' data type now treat them as + single-character strings instead of one-byte integers, as + does the Standard C++ Library. + + - Added mysqlpp::tiny_int interfaces to STA to replace the + former char interfaces for those needing one-byte integers. + + o As a result of the ColData -> String redesign, removed + Row::raw_*(). Before String copies were efficient, this + was helpful in accessing BLOB data efficiently. It was also + required back when ColData didn't deal correctly with embedded + null characters, but that reason is gone now, too. + + o Row::operator[](const char*) no longer unconditionally throws the + BadFieldName exception when you ask for a field that doesn't + exist. It will still throw it if exceptions are enabled, but if + not, it'll just return an empty String. This was necessary to + make the SSQLS subset and field order independence features work. + + o Similarly, Result::field_num() returns -1 when exceptions are + disabled and you ask for a field that doesn't exist. + + o You can now use the OptionalExceptions mechanism to disable + exceptions on const MySQL++ objects. + + o Redesigned query result classes: + + - Instead of Result deriving from ResUse, the two derive from + a common base class -- ResultBase -- containing the bits that + are truly the same between them. Before, Result inherited + several methods that didn't really make sense for "store" + query result sets. + + - Renamed Result to StoreQueryResult and ResUse to UseQueryResult + so it's clearer what each is for. + + - Renamed ResNSel to SimpleResult. + + - Made all SimpleResult data members private and hid them behind + const accessor functions of the same name. + + - The result set classes all used to be friends of Connection + for various lame reasons. Since they are created by Query, + and Query has a good reason for a strong relationship with + Connection, moved Connection access out of each result set + class into the code in Query that creates that type of result + set object. + + - StoreQueryResult now derives from vector in addition to + ResultBase; it used to merely emulate a vector of Rows, poorly. + It can now dispose of the MYSQL_RESULT at the end of object + construction, because it creates all the Row objects up front + instead of on the fly. And as a result of *that*, operator[] + returns by reference instead of by value, operator -> works + correctly on iterators, all STL algorithms work, etc., etc. + + - IMPORTANT COMPATIBILITY BREAK: because we used fetch_row() + stuff in Result previously, it was okay to index past the + end of the result set: you'd just get a falsy Row when you + did this, just as happens when doing the same thing in a + "use" query. The simple1 and simple2 examples did this, + so it's likely that code exists that takes advantage of this + misfeature. New versions of these examples show how to index + through a StoreQueryResult without running past its end. + + - ResUse used to delay creation of its FieldNames and FieldTypes + objects until the point of need. This had several implications + for thread and exception safety that we fix by just creating + them in the ctor. If your code is multi-threaded and was + avoiding certain usage patterns due to crashes, it's worth + trying your preferred way again. + + - Result sets create a few data structures to hold information + common to all rows in that set. The row objects need access + to these shared data structures, so on creation each gets + a pointer back to the result set object that creates it. + This was efficient, but required that a result set object + outlive any row objects it creates. Now these shared data + structures are reference-counted, decoupling the lifetime of + the child row objects from their result set parent. + + - Copy operations for result sets used to actually be "moves" + before, for efficiency. (MySQL++ itelf only copied result + sets in returning them by value from the query execution + methods of Query, so this was acceptable if you didn't do + anything uncommon with these objects.) Reference counted + data structures allow us to have copy semantics now without + sacrificing efficiency. + + - You can now use Query::storein() with an STL container of Row + objects now, instead of having to use SSQLSes. The lifetime + issue guaranteed a crash if you tried this before. + + - Removed a bunch of unnecessary alias methods: + + - columns() -> num_fields() + - names() -> field_names() + - rows() -> num_rows() + - types() -> field_types() + + - Renamed several methods for grammar reasons: + + - fields(unsigned int) -> field(unsigned int) + - names(const std::string&) -> field_num(const std::string&) + - names(int) -> field_name(int) + - types(int) -> field_type(int) + + - Removed several "smelly" methods: + + - purge() + - raw_result() + - reset_names() + - reset_field_names() + - reset_types() + - reset_field_types() + + o Field class used to just be a typedef for the corresponding C + API class. Now it's a real C++ class providing a more MySQL++ + sort of interface, plus good OO things like information hiding + and implementation detail abstraction. This changes several + things about the interface. + + o Fields class was basically a specialized std::vector work-alike + for dealing with the C API to get access to MYSQL_FIELD objects + and present them as contained Field objects. New Field type + let us replace it with "typedef std::vector Fields" + + o Major improvements to the quoting and escaping mechanisms: + + - Replaced almost all of the type-specific interfaces in manip.h + with a single version taking STA. The compiler can convert + almost anything to STA without losing any information we need + for correct quoting and escaping. This has the side benefit + that we can now do correct quoting and escaping for more data + types now, including plain C and C++ string types. + + - Fixed a bug in quote_double_only manipulator for String: was + using single quotes by mistake. + + - Escaping and quoting only works in instances where MySQL++ + can tell you're building a SQL query and are using a data type + that requires it. This affects many things, but the one most + likely to cause trouble is that inserting MySQL++'s quoting + and escaping manipulators in non-Query ostreams is now a no-op. + + - Added escape_string() member functions to Query and + SQLQueryParms::escape_string(), and removed the global function + of the same name. Because these are tied indirectly to a + Connection object, this also has the effect that escaping is + now aware of the current default character set used by the + database server. There's only one case where this isn't done + now, and that's when we're disconnected from the server. + + - Previous two items form a trade-off: if your code was depending + on MySQL++ to get SQL escaping and it no longer happens for + what we consider a good reason, you can build a replacement + mechanism using these new functions. Quoting needs no special + support in MySQL++. + + - Removed 'r' and 'R' template query parameter modifiers, + which meant "always quote" and "always quote and escape" + regardless of the data type of the parameter. There are no + corresponding manipulators (for good reason), so the removal + restores symmetry. + + o Created DBDriver class from code previously in Connection and + Query to almost completely wrap the low-level MySQL C API: + + - Connection creates a DBDriver object upon connection and + passes a pointer to it down to Query objects it creates. + In turn, they pass the pointer on to any of their children + that need access to the C API. + + - Nothing outside DBDriver calls the C API directly now, though + DBDriver leaks C API data structures quite a lot, so this + feature doesn't constitute "database independence." See the + Wishlist for what must be done to get to that point. + + o Completely redesigned the connection option setting mechanism: + + - There's now just a single Connection::set_option() method that + takes a pointer to the abstract Option base class, and there is + an Option subclass for every connection option we understand. + Thus, type errors are now caught at compile time instead of + at run time. + + - Replaced Connection::enable_ssl() with SslOption class. + + - Enabling data compression and setting the connection timeout + are no longer set via parameters to Connection interfaces. + These are now set with CompressOption and ConnectTimeoutOption. + + - Similarly, removed client_flag parameters from Connection's + ctor and connect() method and added corresponding Option + subclasses. There's about a dozen, so rather than list them + here, look for similarly-named classes in lib/options.h. + + o Added Connection::count_rows() to execute "SELECT COUNT(*) FROM + tablename" queries for you. + + o Moved Connection::affected_rows(), info() and insert_id() methods + to class Query, as they relate to the most recently-executed + query, not to the connection. + + o Several method name changes in Connection: + + - client_info() -> client_version() + - host_info() -> ipc_info() + - proto_info() -> protocol_version() + - server_info() -> server_version() + - stat() -> status() + + o Removed Connection::api_version(). It does the same thing as + client_version(). + + o Lots of changes to Date, DateTime, and Time classes: + + - If you use the default constructor for DateTime and don't + subsequently set its year, month, day, hour, minute or second + data members to nonzero values, it becomes the SQL function + "NOW()" in a query string. You can also use DateTime::now() + as syntactic sugar for this. + + - As a result of above, had to hide all of DateTime's data + members behind accessor functions, to keep the state of the + object consistent. (If it's initialized as "now" and you + give it an explicit year value, say, it is no longer "now", + so the setter has to clear the now-flag.) There are getters + and setters for year, month, day, hour, minute and second, + all named after the member. + + - Did the same for Date and Time for consistency, even though it + isn't technically required. + + - The sql_timestamp typedef now aliases DateTime instead of Time. + + - Renamed template class DTbase to Comparable. The fact + that it's the common base class of all date and time classes + is irrelevant; making subclasses comparable is what it does, + so that's what it should be named after. + + - Added a DateTime ctor taking discrete year, month, day, hour, + minute, and second values. + + - Implicit conversion from stringish types to the date and time + types is no longer allowed. This is part of the "Waba" + Null patch mentioned above; allowing implicit conversions + would break this new feature. + + - Added operator std::string and str() methods to all of these + classes. Adding this to the existing operator << support, you + now have several ways to convert these objects to string form. + + - Added time_t conversion to Date and Time classes. DateTime + already had it, since it's more legitimate to convert time_t + to DateTime, but you could already "slice" it with something + like Time(DateTime(time(0))) so there's no point pretending + you can't get from time_t to Date or Time. Might as well + legitimize it. + + o Improved tiny_int class: + + - Turned it into a template parameterized on the value type so + you can get both signed and unsigned TINYINTs + + - Changed the sql_tinyint and sql_tinyint_unsigned typedefs to + use mysqlpp::tiny_int instead of raw chars + + - Added a bool conversion ctor and operator, and typedef'd it + to sql_bool and sql_boolean to match MySQL server behavior + + o Added many more sql_* typedefs. We now have a typedef for every + type the MySQL server knows about, including those it supports + just for compatibility with other database servers. + + o Changed the sql_*int* typedefs to use integer types of the same + size as the MySQL server. (Run test/inttypes.cpp to test it.) + + o Added copy ctor and assignment operator to Row. + + o Row::operator[]() takes int now instead of unsigned int. + This finally (!) makes it possible to say row[0] without the + compiler giving an ambiguous overload error. + + o Changed all uses of row.at(0) in the examples to row[0] + + o Added operator[] to all classes that only had at(). + + o Query now automatically resets itself unless the query fails + or you're using template queries. In either case, the contents + of the query's internal buffers are considered precious, + either for debugging, or future queries. Except when using + template queries, this means you may be able to avoid calling + Query::reset() entirely. It's still safe to call reset() + as before, just unnecessary most of the time. + + o Removed reset_query parameter from all Query methods. It was + almost completely broken before, and above change does what + was really wanted to begin with. + + o Query::store_next() and Result::fetch_row() no longer throw + the EndOfResults and EndOfResultSets exceptions; these are not + exceptional conditions! These methods simply return false now. + + o Removed examples/usequery.cpp: there's no essential difference + between what it did and what examples/simple3.cpp does now as + a result of the previous change. + + o Added Query::exec(void), paralleling Query::execute(void). + + o Removed Query::preview(). The most direct replacement is str(), + which has always done the same thing. + + o You can now insert a Query object into an ostream to get a copy + of the built query. This means Query::str() is only necessary + when using template queries. + + o Removed overloads of Query::execute(), store(), and use() + that take const char*. It was redundant because const char* + converts implicitly to STA, for which overloads already exist. + + o Renamed Query::def to Query::template_defaults to make its + purpose clearer. + + o Query::error() now returns const char*, not a std::string by + value. There's no point in making a copy of the error string. + The method is now const as well, as it doesn't change the + Query object. + + o Added Query::errnum(), which just wraps Connection::errnum(). + + o Added error number parameters and accessor functions to BadQuery, + ConnectionFailed and DBSelectionFailed exceptions, to preserve + the state of Connection::errnum() at the point of the exception, + so you don't have to rely on this value remaining unchanged + during the exception throw process. All places that use these + exceptions now include this value where possible. Thanks for the + initial patch go to Jim Wallace. + + o Removed Lockable mechanism from Connection and Query; it was + conceptually flawed. See the new user manual chapter on + threading for advice on using MySQL++ safely without locking. + There is mutex locking now in ConnectionPool, but that's it. + + o Connection::query() now takes an optional query string, allowing + the returned Query object to start off with a value. Especially + useful when the query string is static, either because it's + a simple query or because it's a template. You can now build + chains like "if (conn.query("CREATE INDEX ...").exec()) { ..." + + o Added Connection::thread_aware(), thread_end(), thread_id() + and thread_safe(). See user manual's threading chapter for + explanations. + + o Renamed "success" data members in Connection, Query and + SimpleResult (neĆ© ResNSel) to "copacetic_", making them private + if they weren't before. This better reflects their actual + use, which isn't to say that there has necessarily been actual + success, but rather that everything's okay with the object. + + o Removed success() member functions from above classes. All can + be tested in bool context to get the same information. + + o Replaced all operator bool()s in MySQL++ classes with safer + alternatives. See http://www.artima.com/cppsource/safebool.html + Thanks to Jonathan Wakely for much helpful commentary, advice, + and code used in these mechanisms. + + o Decoupled Connection::copacetic_ from Connection::is_connected_. + It is now possible for the object to be copacetic without being + connected. However, if it tries to connect and fails, then + it is not copacetic. If it is copacetic and not connected, it + means we haven't even tried to connect yet, a useful distinction. + + o Collapsed Connection's host, port, and socket_name down into + a new combined 'server' parameter which is parsed to determine + what kind of connection you mean. These interfaces are still + compatible with v2.3 and earlier up through the port parameter. + There are differences beyond this. + + o Added TCPConnection, UnixDomainSocketConnection and + WindowsNamedPipeConnection subclasses for Connection giving + simpler construction and connect() method interfaces for + instances where you know what kind of connection you want at + compile time. + + o Changed Connection::ping() return value from int to bool. + + o Renamed NullisNull to NullIsNull -- capital I -- and similar for + NullisZero and NullisBlank. + + o It's now a compile-time error to try to convert a MySQL++ + representation of a SQL null to any other data type, rather + than a run-time error as in previous versions. Removed + BadNullConversion exception as a result. + + o Way back in v1.7.x we used the BadQuery exception for all kinds + of exceptional conditions, not just bad queries. Replaced + most of these in v2.0.0 with new dedicated exceptions, but a + few remained: + + - Errors that occur during the processing of a "use" query after + the query itself executes correctly now throw UseQueryError. + It's not a "bad query", because the query executed + successfully. It just choked during subsequent processing, + so it's a different exception. Thanks for this patch go to + Jim Wallace. + + - Replaced BadQuery exceptions thrown in Row constructor due + to bad ctor parameters with new ObjectNotInitialized exception + This is also Jim Wallace's work. + + o The examples now all use getopt() type command line options + instead of positional options. This makes it possible to + pass options in any order, leave at their default options that + used to be in the middle of the sequence, and offer different + subsets of options for different programs. Also allows for + special internal-use options, like -D passed by dtest to let + examples change their behavior when run under dtest to produce + only predictable output. + + o Split old libutil functionality into two modules, one holding + all the "print data" functions, and another holding all the + command line parsing stuff. This makes it easier for newbies + to ignore the command line stuff, treating it like a black box. + The wish to understand the "print data" routines is much more + common, so the two needed to be disentangled. + + o Renamed examples' libutil to libexcommon. + + o Removed connect_to_db() libutil function. It combined command + line parsing, which users don't care about, with database + connection establishment, which they do care about. Now the + examples just call out to libexcommon to parse the command + line, and use the values they get back to explicitly make the + connection, so it isn't hidden. + + o Removed cchar and uint typedefs. + + o Redesigned dbinfo example's output to be easier to read. + + o Fixed an output formatting bug created in 2.3.0 that caused the + tabular output from examples to not line up. + + o Renamed examples/tquery.cpp to tquery1.cpp. Created tquery2.cpp + to demonstrate passing parameters via a SQLQueryParametrs object + instead of discretely. Created tquery3.cpp for testing unquoted + template parameters, such as integers. + + o Renamed fieldinf1.cpp example to fieldinf.cpp, and simplified + its output so it can be part of the dtest sequence. + + o Renamed examples/xaction.cpp to transaction.cpp. It created too + much cognotive dissonance whenever thinking about both it and + lib/transaction.cpp. + + o Added examples/deadlock.cpp, to test handling of exceptions due + to server-side transaction deadlock detection. Also added + code to resetdb to create a table needed to test this. + Initial version created by Jim Wallace to test the value of + all his BadQuery exception work, with reworking by me. + + o Greatly expanded dtest suite. Primary change is that we now + have a handful of unit tests, where in v2.3.2 we only tested + a subset of the examples. Still very low coverage ratio, + but it's a big improvement. + + o Optimized #includes, especially in lib/*.h to reduce + dependencies and thus compile time when one of these changes. + + o Fixed a typo in RPM filename generation that prevented -devel + RPM from recognizing that the corresponding MySQL++ library + RPM was installed. + + o RPM spec file improvements by Remi Collet. + + o Renamed NO_LONG_LONGS to MYSQLPP_NO_LONG_LONGS to avoid a risk + of collision in the global macro namespace. + + o First cut at Xcode2 project support. Testing needed! + + o Debug build of library on VC++ and Xcode have a _d suffix now + so you can have both versions of the library installed without + conflict. + + o Moved the VC++ 2003 project files into a new vs2003 subdirectory + because there are so many of them. Also created vs2005 + subdirectory for VC++ 2005 and 2008 compatible project files. + 2005 makes an even bigger mess of the directory containing + the .sln file, so the incentive is bigger. Plus, we have to + disable several things to get VC++ 2003 to build MySQL++ now, + so we need a special 2005+ version of the project files for a + complete build, if the user has one of the newer compilers. + + o ...plus dozens of small bug fixes and internal enhancements, + many documentation improvements, and expansion of support for + newer operating systems and compilers. + + +2.3.2, 2007.07.11 (r1669) + + o Previous release's const_string change caused more problems + than it fixed. This release contains the real fix. :) + + o New Connection::set_option() handling deals with the multi + statements option correctly again. examples/multiquery now + runs again as a result. + + o Added new unit testing script, called dtest. See the + HACKERS file for details. (This tool caught the previous + two problems!) + + o Squished a GCC pedantic warning. Thanks for the patch go to + Andrew Sayers. + + +2.3.1, 2007.07.10 (r1659) The "After the Fireworks" release + + o const_string objects now keep a copy of their data, not + just a pointer to it. This is less efficient, but necessary + to allow SSQLS to work with BLOBs. Without this, we were + seeing segfaults due to accessing freed memory pointed to + by the const_string, because the underlying object went + out of scope. + + o Fixed many more potential embedded null handling problems + in manip.h. + + o MySQL++ can now optionally reference MySQL C API headers as + being in a mysql subdirectory, a common thing on *ix systems, + by defining MYSQLPP_MYSQL_HEADERS_BURIED before #including + mysql++.h. + + o Restored ColData_Tmpl::get_string(), removed in v2.3.0, + along with warnings in the docs saying why you don't want + to use it, and what your alternatives are. + + o VC++ and MinGW builds now define the HAVE_MYSQL_SSL_SET + macro, which lets you use the C API's SSL features. + This assumes your C API library does actually have these + features enabled, which is the case with the official binary + releases on Windows. (Builds on *ix systems continue to + test for these features at configure time.) + + o Fixed simple examples-only Makefile generation, for RPMs. + + +2.3.0, 2007.07.02 (r1645) + + o Added Query::for_each() and Query::store_if() methods + proposed by Joel Fielder, and added examples for each. + + o It's now possible to store BLOB data in an SSQLS. It's not + foolproof, so added a section to the user manual (5.9) to + document the method. Also, changed examples/cgi_jpeg to use + this new mechanism, instead of the ugly "raw row data" method + it used to use. + + o Revamped Connection::set_option() handling. These options + used to be queued up, and applied only just before actually + establishing the connection. This made error reporting less + helpful because the diagnostic was separated from the cause. + Plus, the error messages were misleading to begin with. Now, + set_option() takes effect immediately if the connection is not + yet up (excepting one special option that can actually be set + after the connection is up) and issues better diagnostics when + it detects errors. + + o Connection::connect() used to set a few options in such a + way that the user couldn't override them. Now it's smart enough + to set them with the desired default values only when we see + that the user hasn't given them other values. + + o SQLString can now be initialized from a mysqlpp::null, + giving a "NULL" string. This is useful for template queries. + Patch by Michael Hanselmann. + + o resetdb error message about mixing library and header version + numbers is now more explicit. + + o Changed BadConversion exception's "what" message text to be + more like the other exceptions. The inconsistency lead one + to incorrectly copy-paste code from another exception handler, + expecting it to behave the same way. Now it does. + + o Added Row::raw_size(), as a shortcut for Row::at().size(). + + o ssqls-pretty now detects when it's being run from within + the MySQL++ distribution tree and gives a different -I flag + to the compiler, so that it picks up the distribution headers + instead of those that may be on the system already. + + o The quote manipulator now works for char[] correctly. + Thanks for this patch go to Andrew Sayers. (It's always + worked for char*, but C++ doesn't consider that to be the + same type, so it used the generic quote handling path, + which doesn't do anything for char[].) + + o Fixed a build bug on older Solaris versions where the + test for the C API library was erroneously failing, stopping + the configuration process. + + o Simplified mysql_shutdown() level argument detection. + Already had to do a version number ifdef check for the + Windows case, so there's really no point to doing it with + autoconf on Unixy platforms. Moved version number check + into lib/connection.cpp, and nuked the separate autoconf and + Windows tests. + + o Removed dependency of sql_types.h on myset.h and (indirectly) + datetime.h. Now we only define sql_* typedef aliases for those + MySQL++ types if the headers are included before sql_types.h. + + o Fixed a typo in one of the storein_sequence() template + overloads, which is apparently rarely (or never?) used, because + no one reported the compiler error you'd get if you tried. + + o Fixed a few more embedded null handling problems. + + o ColData used to keep two copies of all data it held. + Now it keeps just one. + + o Fixed install.bat script to track the unified Bakefile change + and the lack of separate debug and release builds under MinGW. + + o Yet another STLport + Query memory leak fix. + + o Squished a warning in newer GCCs having to do with identifier + shadowing. Patch by Jonathan Wakely. + + o Fixed a null-termination bug in Query::parse(). If you + somehow constructed a query string without a terminating null + character, then tried to parse it as a template query, it could + walk off the end of the string. Patch by Worster Chen. + + o Removed MYSQLPP_EXPORT tag from FieldNames and FieldTypes + class declarations, as this can cause problems in programs + that use vector in VC++. It has to do with multiply + defined templates, since these classes derive from that + template, and VC++ can't resolve the conflict without help. + Since these classes aren't actually used outside the library, + this shouldn't cause a problem. Patch by Nils Woetzel. + + o Partial fix to Doxygen PDF build on RHEL4 and 5. Needs + hand-coaxing to complete successfully on RHEL4, and doesn't + yet work at all on RHEL5. + + o Shortened the "no*" options to the bootstrap script, so that + the usage message fits on a single line. + + o Added "nodoc" bootstrap script option, for disabling the + documentation build during the dist target build. Allows for + building binary RPMs on CentOS 5.0, where doc building is + currently broken. + + o Removed the updel example program. It was kind of silly, + and if you were to rewrite it today, you'd use for_each() anyway. + + o Lots of documentation improvements. + + +2.2.3, 2007.04.17 (r1538) The "Tax Day" release + + o Previous version left examples/vstudio/* out of the tarball + by accident. + + o Improved generation of RPM temporary build directory path + name generation. Was using a hacked variant of the Fedora + Packaging Guidelines' second best choice. Now we're using + the choice they recommend most highly, without changes. + + o Removed unnecessary resources from vstudio/wforms example. + + o Minor URL fix in refman + + +2.2.2, 2007.04.13 (r1526) The "Nervousmaking Friday the 13th" release + + o More small fixes to embedded null handling in Query. + + o Fixed a bug in single-parameter template query handling. + + o Added tquery example, to demonstrate proper use of template + queries. Previously, resetdb was the only exemplar, and + it wasn't really suited for that. This example also tests + the previous item. + + o Added examples/vstudio/mfc, allowing us to improve the way + we demonstrate Unicode handling. Old way wasn't realistic. + On *ix, people will depend on the terminal code to handle + UTF-8. On Windows, users are almost certain to be writing + a GUI program, which requires different Unicode handling + than the old examples showed. + + o Removed explicit Unicode conversion stuff from command line + examples, and reworked the Unicode chapter in the user + manual. + + o Added examples/vstudio/wforms to show integration with + C++/CLI and Windows Forms. Documented this in README.vc. + + o Rewrote load_file and cgi_image examples to be more + useful, renaming them to load_jpeg and cgi_jpeg along + the way. Also, resetdb now creates a second table in the + sample database for these two examples' use. Also, added + examples/logo.jpg to the distribution as sample data for + these examples. + + o Limited the ostream base class casting stuff in Query to + VC++ 2003, which is the only platform that really needed it. + VC++ 2005 emits a warning with that hack in place, and on + other platforms it's just replicating work that the compiler + does already. + + o Added library version information to main library target + so that systems that version shared libraries work as + expected. Thanks for this patch go to Jack Eidsness. + + o Merged much of the diffs between Remi Collet's RPM spec file + into the official one. + + o Reorganized the doc subdir a bit. Generated HTML is now all + under doc/html instead of scattered under other subdirs, + and renamed doc/README.mysql++ to doc/README.manuals. + + o Improvements to top-level manual building make targets: + manuals now only rebuild at need, it's easier to request + a rebuild of all manuals, and we force a rebuild attempt + before building the distribution tarball so we don't ship + outdated manuals. + + o Added ability to run examples under gdb using exrun, + using same mechanism as we currently have for valgrind. + Thanks for this patch go to Michael Hanselmann. + + o Added "Important Underlying C API Limitations" chapter to the + user manual, to cover problems we keep seeing on the + mailing list that are the result of ignorance of the way + libmysqlclient behaves, not bugs MySQL++ is really in a + position to fix. + + +2.2.1, 2007.02.28 (r1433) + + o Fixed the new localtime() alternative selection code + for VS2003 and various uses of STLport. + + o No longer inserting a null character into the query stream + on calling one of the preview() functions. This was harmless + in v2.1, which used C strings more extensively, but began + causing problems in v2.2 due to its wider use of C++ strings. + + o Fixed a bug in the Connection copy ctor where it didn't + completely initialize the object. + + o Optimized Query::preview_char() a bit. Patch by Jonathan + Wakely. + + o Reordered directory list used by autconf when locating the + MySQL C API library. The list is now ordered with the + most likely locations for the library first, so we're less + distracted by incorrect libraries. This fixes a specific + build error under RHEL4 with recent versions of MySQL 5.0. + + +2.2.0, 2007.01.23 (r1417) + + o ColData, const_string, and SQLString can now be constructed + with an explicit length parameter. Furthermore, Query + class's execute(), store() and use() call chains terminate + in a version taking an explicit length parameter, instead + of one taking a simple C string. Together, this means + that it's now easier to handle data from the SQL server + containing nulls. The library is almost certainly not yet + capable of handling embedded nulls in all cases, but this + is a big first step towards that. + + o Can now construct a DateTime object from a time_t, and + convert a DateTime back to a time_t. Patch by Korolyov Ilya. + + o Changed the way we're handling exported functions in the + Windows DLL case so that it works more reliably under MinGW. + + o Added proper copy semantics to Connection, so that you get a + new connection with the same parameters, not just a bitwise + copy of the object. + + o Using an explicitly thread-safe variant of localtime() for + time conversions where one is available. + + o Removed ListInsert template from myset.h. This wasn't used + within the library, and was never documented, so I'm betting + that no one actually uses it. + + o Result::copy() was not copying the exception flag in + all cases. Fix by Steven Van Ingelgem. + + o Added exrun shell script and exrun.bat files to distribution, + to avoid linkage errors when running the examples while + you still have an older version of MySQL++ installed. + + o Renamed MYSQLPP_LIB_VERSION to MYSQLPP_HEADER_VERSION, as + what it really encodes is the version number in the mysql++.h + file you're using, not the actual library version number. + + o Added mysqlpp::get_library_version(), which returns the + library version number at build time. Between this and + the header version constant, you can check that you're not + mixing MySQL++ header and library versions. + + o resetdb example uses these new version number affordances to + double-check that you're not mixing libraries and headers + from different versions. This happens easily unless you + take care of it (such as by using exrun) when you have one + version of MySQL++ installed and you're trying to build and + test a new version without blowing away the old one first + or overwriting it. + + o No longer using recursive Makefiles on Unixy platforms + or split lib + examples project files on VC++. Everything is + handled by a single top-level Makefile or project file, which + is simpler for the end user, and makes better dependency + management possible. + + o When looking for the MySQL C library on systems using + autoconf, looking in .../lib64 wherever we are also looking + in .../lib. + + o RPM build process no longer depends on Bakefile. It means + you have to build the examples when building an RPM even + though they're never used within the RPM, but it's a better + tradeoff in my opinion. + + o Updated include and library paths on Windows to reflect + changes in the most recent MySQL installers. + + o Merged lib/defs.h and lib/platform.h into new file, + lib/common.h. Just cleans up the library internals. + + o Fixed build errors on Windows due to recent changes in MySQL. + + o Fixed a few memory leaks and double-deletes in Query class. + + o Fixed compatibility with STLPort's string implementation. + Patch by dengxy at cse.buaa.edu.cn. + + o Fixed a compatibility problem between Set<> template and + SSQLS. Patch by Korolyov Ilya. + + o Fixed build bug in SQLQueryParms due to a character + signedness issue on PowerPC with GCC. Patch by Michael + Hanselmann. + + o ~Transaction() can no longer throw exceptions. It'll just + quietly eat them, to avoid program termination. Fix + suggested by Alex Burton. + + o Fixed thread safety testing in autoconf case, accidentally + broken during v2.1.0 development cycle. + + o Using Doxygen 1.5.1 to generate documentation. + + +2.1.1, 2006.04.04 (r1289) + + o MinGW and Cygwin will now build and link to mysqlpp DLLs. + + o Fixed bug in Query, causing it to initialize the "throw + exceptions" flag incorrectly. Thanks for this patch go to + Joel Fielder. + + o Added -v flag for custom.pl script, which turns off the + multiply-defined static variable fix. Needed for VS 2003, + which doesn't support variadic macros. Also, added + a diagnostic to detect the need for the -v flag, and + suppressed the test for this feature in examples/util.cpp. + + +2.1.0, 2006.03.24 (r1269) + + o Converted automake and makemake files to their equivalents in + Bakefile format. + + o Added the Transaction class, which makes it easy to use + transaction sets in MySQL++. + + o Added xaction example to test new Transaction class. + + o Resetdb example now creates its example table using the + InnoDB storage engine, in order to test the new transaction + support. Resetdb also declares the table as using UTF-8 + text; this doesn't change anything, but it does correctly + document what we're doing. + + o Added sql_types.h header, containing C++ typedefs + corresponding to each MySQL column type. Using those new + types in the type_info module, and in the SSQLS examples. + + o Replaced the way we were handling the template query + version of Query member functions, to allow an arbitrary + number of template query parameters. By default, we + now support 25 parameters, up from the old limit of 12. + It's now possible to change just one number, run a script, + and have a new limit. + + o Connection class does a better job of returning error + messages if you call certain member functions that depend + on a connection to the server before the connection is + established. + + o Updated libmysqlclient.def for newer versions of MySQL. (Fixes + build errors having to do with mysql_more_results() and + mysql_next_result(). + + o Replaced final use of strcpy() with strncpy(). + + o custom.pl now runs without complaint in strict mode, with + warnings turned on. Thanks for this patch go to "Waba". + + o Fixed a bug in custom.pl where incorrect code would be + generated for some SSQLS set() methods. Thanks for this + patch go to "Waba". + + o SSQLS structures now support long and unsigned long fields. + Thanks for this patch go to "Waba". + + o It's now possible to put SSQLS definitions in a header + file used by multiple modules in a program without + getting multiple static member definition errors. See the + documentation for details. Thanks for this patch go to + Viktor Stark. + + o Moved the definition of the 'stock' SSQLS out of the + custom*.cpp example files and into a new stock.h file. + Also, #including that file in the util module to test out + the new SSQLS multiple static definition fix. + + o Using all of the digits of precision guaranteed by the + IEEE 754 spec when stringizing floating point numbers + to build queries. Previously, we would use the platform + default, which can be as few as 6 digits. + + o Removed lib/compare.h. Not used within the library, never + documented, and nobody seems to want to defend it. + + +2.0.7, 2005.11.23 (r1147) + + o Added explicit mysqlpp namespace qualifiers to generated code in + custom*.h so you can use SSQLS in places where it doesn't make + sense to say "using namespace mysqlpp" before the declaration. + Also updated some of the examples to not have this "using" + declaration to make it clear to users that it isn't needed, if you + want to use explicit namespace qualifiers as well. Thanks for + this patch to Chris Frey. + + o Removed an apparently useless unlock() call from ResUse; there is + no nearby lock() call, so if this unlock() is in fact necessary, + it shouldn't be here anyway, because the two calls should be + nearby each other. Thanks for this patch to Chris Frey. + + o Fixed Query ostream initialization bug affecting SunPro CC (at + least). While this bug violates the Standard, it doesn't affect + many real compilers because they don't enforce this rule. Fixed + by Chris Frey. + + o Previously, we only used the C99 style "long long" support when + building under GNU CC. This is now the default. This should + allow the code to work under SunPro CC. + + o Added another dynamic cast needed for proper Query ostream + subclass overloading under VC++. (7.1 at least...) + + o Detecting whether MySQL is built with SSL support on platforms + using autotools. Needed on some old Sun systems, for instance. + Thanks for this patch to Ovidiu Bivolaru. + + o Fixed a potential memory bug in ColData's conversion to SQL null. + + o Many minor packaging tweaks. (README clarifications, file + permission fixes, better adherence to GNU packaging standards, + etc.) + + +2.0.6, 2005.09.28 (r1123) + + o Fixed makemake.bat so it works on cmd.exe, not just 4NT. + + o Documentation fixes. + + +2.0.5, 2005.09.13 (r1114) + + o Visual C++ build now requires GNU make. It is tested to work + with either the Cygwin or the MinGW versions. The previous + version of MySQL++ used nmake. This change enabled the + following features: + + o Debug and Release versions are both built into + separate subdirectories. + + o Dependency tracking for release version works + correctly now. (Previously dependencies worked + only for debug version.) + + o 'make clean' removes release version binaries + in addition to debug versions. + + o MinGW makemake support updated to support new release/debug + subdirectory system. This is probationary support, since + this code currently can't be built as a DLL. As a result, + it is no more useful than the Cygwin version, for licensing + reasons. + + o Several fixes to allow building on Solaris 8. These fixes may + also help on other SVR4-derived systems. + + o Removed Borland C++ makemake support, because this version + of the library does not work completely, and there seems + to be almost no user interest in fixing it. + + o Clarified "Handling SQL Nulls" section of user manual's + Tutorial chapter. + + +2.0.4, 2005.08.29 (r1076) + + o Made mysql_shutdown() second parameter autoconf check less + sensitive to compiler pedantry. + + o VC++ library Makefile is now smart enough to re-create the + import library, if it is deleted while leaving the DLL alone. + + o Added libmysqlclient.def to tarball. + + o Reworked most of the top-level README* files. + + o Renamed LGPL file to LICENSE. + + +2.0.3, 2005.08.25 (r1060) + + o Visual C++ makemake system updated to build both debug and + release versions of library DLL. + + o Fixed bug in simple1 example that caused crashes on Windows. + + o Doing UTF-8 to ANSI text translation in simple examples now. + + o Previous two releases built libmysqlpp with wrong soname on + autotools-based systems. Fixed. + + +2.0.2, 2005.08.18 (r1050) + + o Fixes to makemake system for cmd.exe. + + o Fixed the case where the system's C++ library includes an slist + implementation in namespace std. + + +2.0.1, 2005.08.17 (r1046) + + o Added new simple1 example, showing how to retrieve just one + column from a table. Old simple1 is now called simple2, and + simple2 is likewise shifted to simple3. + + o Added custom6 example, showing how to do the same thing with + SSQLS. + + o Updated user manual to cover new examples. + + o Was accidentally shipping Subversion crap with tarball. Fixed. + + +2.0.0, 2005.08.16 (r1031) The "Excess Hair Removal" release + + THIS IS NOT A DROP-IN REPLACEMENT FOR MySQL++ v1.7! + + At minimum, you will have to recompile your program against + this library. You may also have to make code changes. + Please see the "Incompatible Library Changes" chapter of + the user manual for a guide to migrating your code to this + new version: + + http://tangentsoft.net/mysql++/doc/html/userman/breakages.html + + o The library's shared object file name (soname) scheme has + changed. (This mainly affects POSIX systems.) + + The soname for the last 1.7.x releases of MySQL++ was + libmysqlpp.so.4, meaning the fourth version of the library's + application binary interface (ABI). (The first ABI version + in this scheme was that provided by 1.7.9.) MySQL++ + 2.0.0's soname is libmysqlpp.so.2.0.0. Since the dynamic + linker setup on some systems will create a symlink to + that file called libmysqlpp.so.2, it's possible that this + library could be confused with that for MySQL++ 1.7.19 + through .21, which also used this number. Do not install + this library on a system which still has binaries linked + against that version of the library! + + The new scheme is {ABI}.{feature}.{bug fix}. That is, + the first number changes whenever we break the library's + binary interface; the second changes when adding features + that do not break the ABI; and the last changes when the + release contains only internal bug fixes. This means + that we will probably end up with MySQL++ 3.0 and 4.0 at + some point, so there will be further soname conflicts. + Hopefully we can put these ABI changes off long enough + to avoid any real problems. + + o autoconf now installs headers into $prefix/include/mysql++, + instead of $prefix/include. If you were using the + --includedir configure script option to get this behavior + before, you no longer need it. + + o Linux binary RPMs will henceforth include only the + libmysqlpp.so.X.Y.Z file, and create any short names + required, to allow multiple versions to be installed at + once. Currently, you cannot install two MySQL++ library + RPMs at once, because they both have /usr/lib/libmysqlpp.so.X, + for instance. + + o Replaced the Visual C++ and Borland C++ project files with + a new "makemake" system, which creates Makefiles specific + to a particular toolchain. This new mechanism also supports + MinGW and generic GCC-on-*ix. This was done partly to reduce + the number of places we have to change when changing the + file names in MySQL++ or adding new ones, and partly so we're + not tied to one particular version of each of these tools. + + o VC++ Makefiles create a DLL version of the library only + now, so there's no excuse for LGPL violations now. + This same mechanism should make DLL builds under other + Windows compilers easy. + + o Added Connection::enable_ssl(), which enables encrypted + connections to the database server using SSL. + + o Connection::create_db() and drop_db() now return true on + success, not false. + + o Connection::create_db() and drop_db() use Query::exec() + now, for efficiency, rather than Query::execute(). + + o Removed Connection::infoo(). Apparently just there to + save you from a typo when calling the info() method, since + it was a mere alias. + + o Renamed Connection::real_connect() to connect(), gave + several more of its parameters defaults, and removed old + connect() function. Then changed user manual and examples + to use new APIs. + + o Replaced Connection::read_option() with new set_option() + mechanism. The name change matches the method's purpose + better. Functional changes are that it returns true on + success instead of 0, it supports a broader set of options + than read_option() did, and it enforces the correct option + argument type. + + o You can now call Connection::set_option() before the + connection is established, which will simply queue the option + request up until the connection comes up. If you use this + feature, you should use exceptions, because that's the only + way an option setting failure can be signalled in this case. + + o Removed query-building functions (exec*(), store*(), + use()) from class Connection, and moved all the implementation + code to class Query. Query no longer delegates the final + step of sending the query to the database server to + Connection(). + + o Added Connection::enable_ssl(), for turning on SSL support on + a connection. + + o Extracted exception disabling mechanism out of the many + classes that had the feature into a new OptionalExceptions + base class, which all classes having this feature now + derive from. Also, removed all per-method exception + handling flags. Finally, added NoExceptions class. With + all of these changes, there is now a common way to disable + exceptions with fine granularity on all objects that + support the feature. + + o All custom MySQL++ exceptions now derive from the new + Exceptions class. This regularizes the exception interface + and allows you to use a single catch() block if you want. + + o The "throw exceptions" flag is passed from parent to child + in all situations now. (Or if not, please report it as + a bug.) This fulfills a promise made in the v1.7.9 user + manual, with the cost being that some programs will see + new exceptions thrown that they're not expecting. + + o Added a bunch of new exception types: BadOption, + ConnectionFailed, DBSelectionFailed, EndOfResults, + EndOfResultSets, LockFailed, and ObjectNotInitialized. + Some of these replace the use of BadQuery, which in v1.7.x + was a kind of generic exception, thrown when something more + specific wasn't available. Beware, this means that programs + may start crashing after recompiling them under v2.0 due to + uncaught exceptions, if they were only trying to catch BadQuery. + + There are additional instances where the library will + throw new exceptions. One is when calling a method that + forces the internals to use an out-of-bounds index on a + vector; previously, this would just make the program + likely to crash. Another is that the library uses the + BadFieldName exception -- created in v1.7.30 -- in more + apropos situations. + + o Renamed SQLQueryNEParms to BadParamCount, to match naming + style of other concrete exception types. + + o Extracted lock()/unlock() functions from Connection and + Query classes into a new Lockable interface class. Locking + is implemented in terms of a different class hierarchy, Lock, + which allows multiple locking strategies with a single ABI. + + o Removed ResUse::eof(). It's based on a deprecated MySQL + C API feature, and it isn't needed anyway. + + o Removed arrow operator (->) for iterator returned by Fields, + Result and Row containers. It was inherently buggy, because + a correct arrow operator must return the address of an + object, but the underlying element access functions in these + classes (e.g. at()) return objects by value, of necessity. + Therefore, this operator could only return the address of + a temporary, which cannot be safely dereferenced. + + o Returned Row subscripting to something more like the + v1.7.9 scheme: there are two operator[] overloads, one for an + integer (field by index) and another for const char* (field + by name). lookup_by_name() has been removed. Because row[0] + is ambiguous again, added Row::at() (by analogy with STL + sequence containers), which always works. + + o Collapsed two of the Row::value_list*() overloads into + two other similar functions using default parameters. + This changes the API, but the removed functions aren't + used within the library, and I doubt they are used outside, + either. + + o Merged RowTemplate into Row. + + o Merged SQLQuery class into Query class. + + o Query is now derived from std::ostream instead of + std::stringstream, and we manage our own internal string + buffer. + + o Moved SQLParseElement and SQLQueryParms into their own + module, qparms. + + o Added multiple result set handling to Query. MySQL 4.1 + and higher allow you to give multiple SQL statements in a + single "store" call, which requires extensions to MySQL++ + so you can iterate through the multiple result sets. Also, + stored procedures in MySQL 5.0 reportedly return multiple + result sets. Thanks for the initial patch go to Arnon Jalon; + I reworked it quite a bit. + + o Query::storein*() now supports more varieties of the + nonstandard slist comtainer. (Singly-linked version of + STL std::list.) + + o Template query mechanism and user manual had several + mismatches. Made manual match actual behavior, or + made library match documented behavior, as apropriate. + Initial patch by Jürgen MF Gleiss, with corrections and + enhancements by Warren Young. + + o Collapsed mysql_* date and time base classes' methods and + data into the subclasses. Also, DateTime no longer derives + from Date and Time; you could get away with that in the + old hierarchy, but now it creates an inheritance diamond, + and allows unsupported concepts like comparing a Time to + a DateTime. + + o Removed "field name" form of Row::field_list(). It was + pretty much redundant -- if you have the field names, why + do you need a list of field names? + + o ColData can convert itself to bool now. Thanks for this + patch go to Byrial Jensen. + + o Removed simp_list_b type; wasn't being used, and doesn't + look to be useful for end-user code. + + o Several methods that used to take objects by value now + do so by const reference, for efficiency. + + o Several variable and function renamings so that MySQL++ + isn't needlessly tied to MySQL. Even if we never make + the library work with other database servers, there's + little point in tying this library to MySQL blindly. + + o Renamed all private data members of MySQL++ classes to + have trailing underscores. + + o 'private' section follows 'public' section in all classes + now. + + o Removed mysql++.hh and sqlplus.hh backwards-compatibility + headers. + + o Added copy ctors to Date/Time classes so that they will + work in SSQLS under GCC 4.0.0. Without these, the compiler + couldn't make the conversion from raw MySQL row data. + + o Fixed a bunch of GCC 4.0 pedantic warnings: added virtual + dtors to all base classes, calling base class ctors from leaf + classes, etc. + + o All warnings fixed under VC++ at warning level 3. (Mostly + harmless signedness and integer conversion stuff.) + + o Updated LGPL license/copyright comments at the top of + several files to use FSF's new physical address. + + o Relicensed user manual under a close variant of the Linux + Documentation Project License, as it's designed for + documentation, which the LGPL is not. Permission for this + received from Kevin Atkinson and MySQL AB. + + o Added ABI and API breakages chapter to user manual. It + is basically a subset of this ChangeLog, with only the + information an end-user must know when migrating between + versions. + + o Reworked user manual's DocBook code quite a bit after + reading Bob Stayton's book "DocBook XSL" 3/e. Better handling + of stylesheets, taking advantage of some superior DocBook + features, prettier output (especially the HTML version), etc. + + o Rewrote doc/userman/README to make it clearer how to get + started contributing to the user manual. It's essentially a + "getting started with DocBook" guide now! + + o Lots of small text improvements to user and reference + manuals. Aside from the obvious tracking of library changes, + made a bunch of minor style and clarity improvements. + + o Added CSS stylesheets for userman and refman to + make the HTML versions of each a) not ugly; and b) match + tangentsoft.net. (Yes, some may say that these are incompatible + goals....) + + o Standardized exception handling code in the examples that + use it. + + o Fixed a potential memory leak due to exceptions thrown from + ResUse. Thanks for this patch go to Chris Frey. + + o Using new "no exceptions" feature of library in simple1 + example, so it is now truly simple. + + o simple1 example no longer depends as much on util module, so + that all of the important code is in one place. Makes + learning MySQL++ a little less intimidating. + + o Added new simple2 and usequery examples, to demonstrate + the proper way to handle a "use" query, with exceptions + disabled, and not, respectively. Added them to the user + manual, in the appropriate place. + + o Refactored the "print stock table" example functions + again, to make code using them clearer. + + o UTF-8 to UCS-2 handling in examples is now automatic on + Windows. + + o Removed debug code from Windows Unicode output examples + that slipped into previous release. + + o resetdb example is now clearer, and more robust in the + face of database errors. + + o Simplified connect_to_db() in examples' util module. + + o Added sample autoconf macro for finding MySQL++ libraries, for + people to use in their own autotools-based projects. + + o Lots and lots of minor cleanups not worth mentioning + individually... + + +1.7.40, 2005.05.26 (r719) + + o Multiple item form of insert() now works if you're using the + SQLQuery class, or its derivative, Query. Thanks to Mark + Meredino for this patch. + + o Fixed a bug in const_string::compare(), in which MySQL++ + would walk off the end of the shorter of the two strings. + All was well if the two were the same length. + + o ResUse::operator=() now fully updates the object, so it's more + like the behavior of the full ctor. + + o All source files now contain a license and copyright statement + somewhere within them. + + o Optimized mysql++.h a bit: it now #includes only the minimum set + of files required, and there is now an idempotency guard. + This improves compile times a smidge, but mainly it was + done to clean up the generated #include file graph in the + reference manual. Before, it was a frightful tangle because + we #included everything except custom*.h. + + o Constness fix in MySQL++ date/time classes to avoid compiler + warnings with SSQLS. Thanks to Wolfram Arnold for this patch. + + o Fixed some compiler warnings in custom*.h. Thanks to Chris Frey + for this patch. + + o Added "Submitting Patches" and "Maintaining a Private CVS + Repository" sections to the HACKERS file. Thanks to Chris + Frey for the source material for these sections. The HACKERS + file was improved in several other ways at the same time. + + o PDF version of user manual no longer has links to the reference + manual. They were ugly, and they were broken anyway due to the + way we move the PDFs after generating them. If you want + interlinked manuals, use the HTML version. + + o PDF version of user manual now has hard page breaks between + chapters. + + o Removed complic1 example. Wasn't pulling its own weight. + Everything it is supposed to demonstrate is shown in other + examples already. + + o Refactored print_stock_table() in examples/util module to be + four functions, and made all the examples use various of + these functions where appropriate. Before, several of + the examples had one-off stock table printing code because + print_stock_table() wasn't exactly the right thing, for one + reason or another. One practical problem with this is that + some of the examples missed out on the recent Unicode updates; + now such a change affects all examples the same way. + + o Since so many of the examples rely on the util module, the user + manual now covers it. The simple1 example in the user manual + didn't make much sense before, in particular, because it's + really just a driver for the util module. + + o Added custom5 example. It shows how to use the equal_list() + functionality of SSQLS. Thanks to Chris Frey for the original + version of this program. (I simplified it quite a bit after + accepting it.) + + o New user manual now covers the value_list(), equal_list() and + field_list() stuff that the old manual covered but which was + left out in previous versions of the new manaul. Most of the + examples are the same, but the prose is almost completely new. + This new section includes the custom5 example. + + o Every declaration in MySQL++ is now documented in the reference + manual, or explicitly treated as "internal only". + + o Improved docs for MySQL++'s mechanism to map between MySQL + server types and C++ types. Initial doc patch by Chris Frey, + which I greatly reworked. + + o Improved a lot of existing reference manual documentation while + adding the new stuff. + + o Expanded greatly on the exception handling discussion in the user + manual. + + o Added all-new "Quoting and Escaping" section to the user + manual's Tutorial chapter. Moved some existing comments on + quoting and escaping around and added some new ones to other + sections as a result. + + o Added all-new "Handling SQL Nulls" section to the user manual's + Tutorial chapter. + + o Many improvements to the Overview section of the user manual. + + o Row::operator[] reference now explains the right and wrong way to + use the values it returns. This is in response to a mailing list + post where someone was incorrectly using this feature and getting + a bunch of dangling pointers. + + o Updated Doxyfile so 1.3.19.1 parses it without warnings. Still + works with versions back to 1.2.18, at least. (These are + the versions shipped with Fedora Core 3 and Red Hat Linux 9, + respectively.) + + o Using a superior method to make Doxygen ignore certain sections + of the source code. Between this change and the fact that + everything not so ignored is documented, Doxygen no longer + generates any warnings. + + o Lots of code style updates. Everything should now be consistently + formatted. + + +1.7.35, 2005.05.05 (r601) The "Cinco de Mayo" release + + o Added a "how to use Unicode with MySQL++" chapter to the user + manual. (Too bad "Cinco de Mayo" doesn't have any accented + characters. That would be just _too_ precious.) + + o VC++ examples now use the Unicode Win32 APIs, so they can display + Unicode data from MySQL++. + + o Added an optional conversion function to examples/util.cpp to + handle the conversion from UTF-8 to UCS-2 on Win32. + + o Moved "brief history of MySQL++" from intro section of refman to + intro section of userman. + + o Lots of small bits of documentation polishing. + + o Made some minor constness fixes. Thanks to Erwin van Eijk + for this patch. + + o Made some warning fixes for GCC 4.0. Not all warnings are + fixed, because some of the needed changes would break the ABI. + Thanks to Chris Frey for this patch. + + o Added lib/Doxyfile to distribution. + + +1.7.34, 2005.04.30 (r573) + + o Added a multiple-insert method for Query, which lets you insert + a range of records from an STL container (or the whole thing, + if you like) in a single SQL query. This is faster, and it + reduces coding errors due to less repetition. Thanks to Mark + Meredino for the patch. + + o Reference and user manual now get rebuilt automatically when + required. (E.g. on 'make dist', or explicitly now through 'make + docs'.) + + o Made it easier to change the maximum number of SSQLS data members + in generated custom-macros.h file. It used to be hard-coded in + several places in lib/custom.pl; now it's a variable at the top of + the file. + + o Changed default SSQLS data member limit to 25, which is what it + has been documented as for a long time now. It was actually 26 + within custom.pl. + + o Fixed a regression in previous version. + + o Trimmed some fat from the distribution packages. + + o Some more small doucmentation improvements. + + +1.7.33, 2005.04.29 (r555) + + o Worked around an overloaded operator lookup bug in VC++ 7.1 + that caused SSQLS insert, replace and update queries to get + mangled. (Symptom was that custom2 and custom3 examples didn't + work right.) Thanks to Mark Meredino for digging up the + following, which explains the problem and gives the solution: + + http://groups-beta.google.com/group/microsoft.public.vc.stl/browse_thread/thread/9a68d84644e64f15 + + o Some VC++ warning fixes. + + o Major documentation improvements: + + o Using DocBook for user manual and Doxygen for reference + manual. The former now references the latter where + useful. + + o Split out HACKERS and CREDITS files from main README, + and improved remaining bits of README. + + o Moved the text from the old v1.7.9 LaTeX-based + documentation over into the new systems, and reworked + it to more closely resemble English. + + o Added a lot of new material to documentation, and + simplified a lot of what already existed. + + o Documentation is now being built in HTML and PDF forms. + + o ebuild file updated to take advantage of recent configure script + features. Thanks to Chris Frey for this patch. + + + +1.7.32, 2005.03.10 (r479) + + o Example building may now be skipped with --disable-examples + configure script flag. + + o Changed stock items added in resetdb. One is now UTF-8 encoded, + to show that basic use of Unicode with MySQL++ is easy, yet not + foolproof. (See formatting of table on systems where cout isn't + UTF-8 aware!) Other stock items now follow a theme, for your + amusement. :) + + o custom3 example now changes UTF-8 item's name to the 7-bit ASCII + equivalent. Previously, this example would fix a spelling error + in the table. + + o resetdb example now says 'why' when it is unable to create the + sample database. + + o Small formatting change to print_stock_table(), used by several + examples. + + o Was issuing a VC++-specific warning-disable pragma when built by + any Windows compiler. Fixed. + + +1.7.31, 2005.03.05 (r462) The "Inevitable Point-one Followup" release + + o Check for threads support must now be explicitly requested via + configure script's new --enable-thread-check flag. + + o Fix for contacting MySQL server on a nonstandard port number. + Thanks to Chris Frey for this patch. + + o Example programs using standard command line format now accept a + fourth optional parameter, a port number for the server. Thanks + to Chris Frey for this patch. + + o One more g++ 3.4 pedantic warning fix by Chris Frey. + + o Exception handling in resetdb is no longer nested, because you'd + get a segfault on some systems when an exception was thrown from + one of the inner try blocks. + + o Improvements to Connection class's handling of locking mechanism. + Concept based on patches by Rongjun Mu. + + o Implemented the declared-but-never-defined Query::lock(). Thanks + to Rongjun Mu for this patch. + + o Cleaned up some unclear if/else blocks in connection.cpp by + adding explicit braces, correct indenting and putting normal + code path in the if side instead of the else. + + +1.7.30, 2005.02.28 (r443) The "Power of Round Numbers" release + + o bootstrap script now accepts a 'pedantic' argument, which sets a + bunch of CFLAGS that make g++ very picky about the code it + accepts without warnings. + + o Fixed a bunch of things that generated warnings with g++ in + pedantic mode. Only two warnings remain, having to do with + floating point comparisons. (See Wishlist for plans on how to + deal with these.) Thanks to Chris Frey for this patch. + + o Split long tests out of configure.in into M4 files in new config + subdir. This makes configure.in easier to read. + + o Added preliminary thread support. Currently, this just means that + we detect the required compiler and linker thread flags, and link + against the proper thread-safe libraries. THERE MAY BE + UN-THREAD-SAFE CODE IN MYSQL++ STILL! + + o Standard C++ exceptions are the default now. Old pre-Standard + exception stuff removed. + + o Row::lookup_by_name() will throw the new BadFieldName exception if + you pass a bad field name. Thanks for this patch to Chris Frey. + + o Row::operator[] will throw a Standard C++ out of bounds exception + by way of std::vector::at() if you pass it a bad index. Thanks + for this patch to Chris Frey. + + o Setting Connection::is_connected flag to false on close(). + Previously, is_connected() would continue to return true after + close() was called. + + o All number-to-string conversion ctors in SQLString class now use + ostringstream to do the conversion. Previously, we used + snprintf(), which isn't available on all systems. Also, we used a + C99 format specifier for the "long long" conversion, which is also + not available on all systems. This new ostringstream code should + be platform-independent, finally. + + +1.7.28, 2005.02.04 (r403) + + o --with-mysql* flags to configure script now try the given + directory explicitly, and only if that fails do they try + variations, like tacking '/lib' and such onto it to try and find + the MySQL includes and libraries. Thanks to Matthew Walton for + the patch. + + o Finally removed sql_quote.h's dependence on custom.h, by moving + the one definition it needed from custom.h to deps.h. This will + help portability to compilers that can't handle the SSQLS macros, + by making that part of the library truly optional. + + +1.7.27, 2005.01.12 (r395) + + o configure check for libmysqlclient now halts configuration if the + library isn't found. Previously, it would just be flagged as + missing, and MySQL++ would fail to build. + + o Added sql_string.cpp to VC++ and BCBuilder project files. + + o Removed Totte Karlsson's 'populate' example, which never made it + into the distribution anyway. + + o Removed last vestiges of 'dummy.cpp'. + + o Renamed *.cc to *.cpp in BCBuilder project files. + + o Worked around a BCBuilder C++ syntax processing bug in row.h. + + +1.7.26, 2004.12.17 (r382) + + o Moved all of the SQLString definitions out of the header and into + a new .cpp file, reformatted it all, and made the integer + conversion functions use snprintf() or _snprintf() instead of + sprintf(). Also, widened some of the buffers for 64-bit systems. + + o Using quoted #include form for internal library headers, to avoid + some problems with file name clashes. (The headers should still + be installed in their own separate directory for best results, + however.) Thanks to Chris Frey and Evan Wies for the patch and + the discussion that lead to it. + + o Removed unnecessary semicolons on namespace block closures. + Thanks to Evan Wies for this patch. + + o Fixed namespace handling in the legacy headers mysql++.hh and + sqlplus.hh. Thanks to Chris Frey for this patch. + + o #including iostream instead of ostream in lib/null.h for + broader C++ compatibility. (This may allow MySQL++ to work on GCC + 2.95.2 again, but this is unconfirmed.) + + o Detecting proper mysql_shutdown() argument handling automatically + in platform.h for the Windows compiler case instead of making the + user edit the file. Thanks to Evan Wies for this patch. + + o Fixed examples/Makefile.simple to use new *.cpp file naming. + + o Fix to Gentoo ebuild file's exception configure switch handling. + Thanks to Chris Frey for this patch. + + o Rebuilding lib/custom*.h intelligently now, to avoid unnecessary + recompiles after running bootstrap script. + + +1.7.25, 2004.12.09 (r360) + + o Yet more fixes to the --with-mysql-lib and --with-mysql-include + flags. + + o Added DLLEXPORT stuff to platform.h, hopefully so that someone + can figure out how to make VC++ make a DLL version of MySQL++. + + o Renamed *.cc to *.cpp. + + o Made 'set -> myset' change in VC++ project files. + + o Some style changes (mostly whitespace) in header files. + + +1.7.24, 2004.12.08 (r343) + + o Fixed the --with-mysql-lib and --with-mysql-include flags' + behavior, and extended their search ability to handle one other + common case. (Fixed by Steve Roberts) + + o Fixes to put freestanding functions in namespace mysqlpp. (They + weren't in the namespace, while all the class member functions + were.) This required bumping the ABI version number to 4. + + o Renamed set module to myset, to avoid conflicts with Standard C++ + Library's set.h when MySQL++ headers were installed into one of + the standard system include directories. + + o Renamed all the idempotency guards to make them consistent in + style and unique to MySQL++. + + o Reformatted all of lib/*.cc. + + +1.7.23, 2004.11.20 (r333) + + o Query::reset() now empties the stored query string. If you + subsequently stored a longer query in the object, you'd overwrite + the previous query, but otherwise the longer part of the previous + one would stick out past the new query. + + o We now look to the NO_LONG_LONGS macro only to decide whether to + fake 64-bit integer support using 32-bit integers. + + o 64-bit integer support under Visual C++ may be working now, using + that platform's __int64_t type. This has not been tested. + + o Removed 64-bit integer support for Codewarrior on Mac OS 9 and + earlier. OS X uses GCC, so it requires no special support. + + o Added MinGW detection in platform.h. + + o If you pass a flag (-X) to the examples that take the standard + parameters (resetdb, simple1, etc.), it prints a usage message. + + o Better error handling in resetdb example, where errors are the + most critical. (If that one runs without errors, the others + probably will, too, and you have to run that one first.) + + o resetdb now reports success, rather than succeeding silently. + + o Removed the code in sample1 example that duplicated util module's + print_stock_table(), and called that function instead. + + o Moved the preview() calls in the example programs to before the + query execution calls, because execution modifies the query. + + o All examples that take the standard command line parameters now + exit when connect_to_db() fails in one of the ways that don't + throw an exception, rather than bulling onward until the next + MySQL database call fails because the connection isn't up. + + o dbinfo example now takes the standard command line parameters. + + o Much better output formatting in dbinfo example. + + o Calling reset() where appropriate in the various example programs. + Before, the programs may have worked, but not for the right + reason. This lead some people to believe that calling reset() + was not necessary. + + o Fixed an incorrect use of row["string"] in complic1 example. + + o Lots of code style improvements to the examples. + + o Some VC++ type warnings squished. Some remain. + + +1.7.22, 2004.11.17 (r302) + + o Applied patches by Zahroof Mohammed to allow it to build under GCC + 3.4.2. Tested on MinGW and Fedora Core 3 systems. + + o Removed all the forward declarations in defs.h, and added + forward declarations where necessary in individual header files. + #including defs.h in fewer locations as a result. + + o Legacy headers sqlplus.hh and mysql++.hh now declare they are + using namespace mysqlpp, to allow old code to compile against the + new library without changes. + + o Removed query_reset parameter from several class Query member + functions. In the implementation, these parameters were always + overridden! No sense pretending that we pay attention to these + parameters. This changes the ABI version to 3. + + o #including custom.h in sql_query.h again...it's necessary on GCC + 3.4. + + o bootstrap script runs lib/config.pl after configure. This is + just a nicety for those running in 'maintainer mode'. + + +1.7.21, 2004.11.05 (r273) + + o Generating a main mysql++ RPM containing just the library files + and basic documentation, and the -devel package containing + everything else. + + o Devel package contains examples now, along with a new Makefile + that uses the system include and library files, rather than the + automake-based Makefile.am we currently have which uses the files + in the mysql++ source directory. + + o Renamed sqlplusint subdirectory in the package to lib. + + o Removed the obsolete lib/README file. + + o lib/sql_query.h no longer #includes custom.h, simplifying + build-time dependencies and shortening compile times. + + +1.7.20, 2004.11.03 (r258) + + o Collapsed all numbered *.hh headers into a single *.h file. For + example, the contents of row1.hh, row2.hh and row3.hh are now in + row.h. + + o While doing the previous change, broke several circular + dependencies. (The numbered file scheme was probably partly done + to avoid this problem.) The practical upshot of most of these + changes is that some functions are no longer inline. + + o Removed define_short.hh and everything associated with it. The + library now uses the short names exclusively (e.g. Row instead of + MysqlRow). + + o Put all definitions into namespace mysqlpp. For most programs, + simply adding a 'using namespace mysqlpp' near the top of the + program will suffice to convert to this version. + + o Once again, the main include file was renamed, this time to + mysql++.h. Hopefully this is the last renaming! + + o mysql++.hh still exists. It emits a compiler warning that the + file is obsolete, then it #includes mysql++.h for you. + + o sqlplus.hh is back, being a copy of the new mysql++.hh. Both of + these files may go away at any time. They exist simply to help + people transition to the new file naming scheme. + + o Renamed mysql++-windows.hh to platform.h, and added code to it to + handle #inclusion of config.h on autotools-based systems + intelligently. This fixes the config.h error when building under + Visual C++. + + o There is now only one place where conditional inclusion of + winsock.h happens: platform.h. + + o Beautified the example programs. + + +1.7.19, 2004.10.25 (r186) + + o Fixed an infinite loop in the query mechanism resulting from the + strstream change in the previous version. There is an overloaded + set of str() member functions that weren't a problem when query + objects were based on strstream. + + o Query mechanism had a bunch of const-incorrectness: there were + several function parameters and functions that were const for + the convenience of other parts of the code, but within these + functions the constness was const_cast away! This was evil + and wrong; now there are fewer const promises, and only one is + still quietly broken within the code. (It's in the SQLQuery + copy ctor implementation; it should be harmless.) + + o Removed operator=() in Query and SQLQuery classes. It cannot take + a const argument for the same reason we have to cast away const + in the SQLQuery copy ctor. It's tolerable to do this in the copy + ctor, but intolerable in an operator. Since the copy ctor is good + enough for all code within the library and within my own code, I'm + removing the operator. + + o Above changes required bumping the ABI to version 2. + + o Visual C++ projects now look for MySQL build files in c:\mysql, + since that's the default install location. (Previously, it was + c:\program files\mysql.) + + +1.7.18, 2004.10.01 (r177) + + o Changed all the strstream (and friends) stuff to stringstream type + classes. Let there be much rejoicing. + + o Query object now lets you use store() even when the SQL query + cannot return a result, such as a DROP TABLE command. This is + useful for sending arbitrary SQL to the server. Thanks to + Jose Mortensen for the patch. + + o Quote fix in configure.in, thanks to David Sward. + + o Renamed undef_short file to undef_short.hh. + + o Gentoo ebuild file is actually being shipped with the tarball, + instead of just sitting in my private CVS tree since 1.7.14 was + current. Ooops.... + + +1.7.17, 2004.09.16 (r170) + + o Reverted one of the VC++ warning fix changes from 1.7.16 that + caused crashes on Linux. + + o Added a configure test that conditionally adds the extra 'level' + parameter to mysql_shutdown() that was added in MySQL 4.1.3 and + 5.0.1. + + +1.7.16, 2004.09.13 (r160) + + o Building VC++ version with DLL version of C runtime libraries, and + at warning level 3 with no warnings emitted. + + o VC++ build no longer attempts to fake "long long" support. See + the Wishlist for further thoughts on this. + + +1.7.15, 2004.09.02 (r144) + + o Renamed Configure file to common.am, to avoid file name conflict + with configure script on case-sensitive file systems. + + o Added ebuild file and ebuild target to top-level Makefile for + Gentoo systems. Thanks to Chris Frey for this. + + o Small efficiency improvements to BadQuery exception handling. + Initial idea by Chris Frey, improvements by Warren Young. + + +1.7.14, 2004.08.26 (r130) + + o Builds with Visual C++ 7.1. + + o Fixed a bug in custom macro generation that caused problems with + GCC 3.4. (X_cus_value_list ctor definition was broken.) + + +1.7.13, 2004.08.23 (r92) + + o Removed USL CC support. (System V stock system compiler.) Use + GCC on these platforms instead. + + o Added examples/README, explaining how to use the examples, and + what they all do. + + o Most of the example programs now accept command line arguments for + host name, user name and password, like resetdb does. + + o Renamed sinisa_ex example to dbinfo. + + o Several Standard C++ syntax fixes to quash errors emitted by + GCC 3.4 and Borland C++ Builder 6. Thanks to Steffen Schumacher + and Totte Karlsson for their testing and help with these. + + o Added proper #includes for BCBuilder, plus project files for same. + Thanks to Totte Karlsson for these. + + +1.7.12, 2004.08.19 (r63) + + o Many Standard C++ fixes, most from the GCC 3.4 patch by + Rune Kleveland. + + o Added Wishlist file to distribution. + + o Fixed a problem in the bootstrap script that caused complaints + from the autotools on some systems. + + o RPM building is working properly now. + + o Fixed the idempotency guard in datetime1.hh. + + +1.7.11, 2004.08.17 (r50) + + o Renamed mysql++, defs and define_short files, adding .hh to the + end of each. (They're header files!) This shouldn't impact + library users, since these are hopefully used internal to the + library only. + + o Removed sqlplus.hh file. Use mysql++.hh instead. + + o Added mysql++.spec, extracted from contributed 1.7.9 source RPM, + and updated it significantly. Also, added an 'rpm' target to + Makefile.am to automate the process of building RPMs. + + o Added bootstrap and LGPL files to distribution tarball. + + o Added pre-1.7.10 history to this file. + + o Removed .version file. Apparently it's something required by old + versions of libtool. + + +1.7.10, 2004.08.16 (r27) + + o Maintenance taken over by Warren Young (mysqlpp at etr dash usa + dot com.) See http://lists.mysql.com/plusplus/3326 for details. + + o Applied many of the GCC 3.x patches submitted for 1.7.9 over + the years. This allows it to build on everything from 3.0 to + 3.3.3, at least. Because so many patches are rolled up in one + big jump, it's difficult to describe all the changes and where + they came from. Mostly they're Standard C++ fixes, as GCC + has become more strict in the source code that it will accept. + + o MysqlRow used to overload operator[] for string types as well as + integers so you could look up a field by its name, rather than by + its index. GCC 3.3 says this is illegal C++ due to ambiguities in + resolving which overload should be used in various situations. + operator[] is now overloaded only for one integer type, and a + new member function lookup_by_name() was added to maintain the old + by-field-name functionality. + + o Fixed another operator overloading problem in SSQLS macro + generation with GCC 3.3. + + o The _table member of SSQLS-defined structures is now const char*, + so you can assign to it from a const char* string. + + o Got autoconf/automake build system working with current versions + of those tools again. Removed the generated autotools files from + CVS. + + o Renamed library file from libsqlplus to libmysqlpp. + + +1.7.9 (May 1 2001) Sinisa Milivojevic + + * Fixed a serious bug in Connection constructor when reading MySQL + * options + * Improved copy constructor and some other methods in Result / + * ResUse + * Many other minor improvements + * Produced a complete manual with chapter 5 included + * Updated documentation, including a Postscript format + +1.7.8 (November 14 2000) Sinisa Milivojevic + + * Introduced a new, standard way of dealing with C++ exceptions. + * MySQL++ now supports two different methods of tracing exceptions. + * One is by the fixed type (the old one) and one is standard C++ + * type by the usage of what() method. A choice of methods has to be + * done in building a library. If configure script is run with + * -enable-exception option , then new method will be used. If no + * option is provided, or -disable-exception is used, old MySQL++ + * exceptions will be enforced. This innovation is a contribution of + * Mr. Ben Johnson + * MySQL++ now automatically reads at connection all standard MySQL + * configuration files + * Fixed a bug in sql_query::parse to enable it to parse more then 99 + * char's + * Added an optional client flag in connect, which will enable usage + * of this option, e.g. for getting matched and not just affected + * rows. This change does not require any changes in existing + * programs + * Fixed some smaller bugs + * Added better handling of NULL's. Programmers will get a NULL + * string in result set and should use is_null() method in ColData to + * check if value is NULL + * Further improved configuration + * Updated documentation, including a Postscript format + +1.7.6 (September 22 2000) Sinisa Milivojevic + + * This release contains some C++ coherency improvements and scripts + * enhacements + * result_id() is made available to programmers to fetch + * LAST_INSERT_ID() value + * Connection constroctur ambiguity resolved, thanks to marc@mit.edu + * Improved cnnfigure for better finding out MySQL libraries and + * includes + * Updated documentation, including a Postscript format + +1.7.5 (July 30 2000) Sinisa Milivojevic + + * This release has mainl bug fixes and code improvements + * A bug in FieldNames::init has been fixed, enabling a bug free + * usage of this class with in what ever a mixture of cases that is + * required + * Changed behaviour of ResUse, Result and Row classes, so that they + * could be re-used as much as necessary, without any memory leaks, + * nor with any re-initializations necessary + * Fixed all potential leaks that could have been caused by usage of + * delete instead of delete[] after memory has been allocated with + * new[] + * Deleted all unused classes and macros. This led to a reduction of + * library size to one half of the original size. This has + * furthermore brought improvements in compilation speed + * Moved all string manipulation from system libraries to + * libmysqlclient, thus enabling uniformity of code and usage of 64 + * bit integers on all platforms, including Windows, without + * reverting to conditional compilation. This changes now requires + * usage of mysql 3.23 client libraries, as mandatory + * Changed examples to reflect above changes + * Configuration scripts have been largely changed and further + * changes shall appear in consecutive sub-releases. This changes + * have been done and shall be done by our MySQL developer Thimble + * Smith + * Changed README, TODO and text version of manual. Other versions of + * manual have not been updated + * Fixed .version ``bug''. This is only partially fixed and version + * remains 1.7.0 due to some problems in current versions of libtool. + * This shall be finally fixed in a near future + * Several smaller fixes and improvements + * Added build.sh script to point to the correct procedure of + * building of this library. Edit it to add configure options of your + * choice + +1.7 (May17 2000) Sinisa Milivojevic + + * This is mainly a release dealing with bug fixes, consistency + * improvements and easier configure on some platforms + * A bug in fetch_row() method of ResUse class has been fixed. Beside + * changes that existed in a distributed patch, some additional error + * checking has been introduced + * A bug in escape manipulator has been fixed that could cause an + * error if all characters had to be escaped + * An inconsistency in column indexing has been fixed. Before this + * version, column names in row indexing with strings, i.e. + * row[] , has been case sensitive, which was inconsistent + * with MySQL server handling of column names + * An inconsistency in conversion from strings to integers or floats + * has been fixed. In prior version a space found in data would cause + * a BadConversion exception. This has been fixed, but 100% + * consistency with MySQL server has not been targeted, so that other + * non-numeric characters in data will still cause BadConversion + * exception or error. As this API is used in applications, users + * should provide feedback if full compatibility with MySQL server is + * desired, in which case BadConversion exception or error would be + * abolished in some of future versions + * A new method in ColData class has been introduced. is_null() + * method returns a boolean to denote if a column in a row is NULL. + * Finally, as of this release, testing for NULL values is possible. + * Those are columns with empty strings for which is_null() returns + * true. + * Some SPARC Solaris installations had C++ exception problems with + * g++ 2.95.2 This was a bug that was fixed in GNU gcc, as from + * release 2.95 19990728. This version was thoroughly tested and is + * fully functional on SPARC Solaris 2.6 with the above version of + * gcc. + * A 'virtual destructor ' warning for Result class has been fixed + * Several new functions for STL strings have been added. Those + * functions (see string_util.hh) add some of the functionality + * missing in existing STL libraries + * Conversion for 64 bit integers on FreeBSD systems has been added. + * On those systems _FIX_FOR_BSD_ should be defined in CXXFLAGS prior + * to configuring. Complete conversion to the usage of functions for + * integer conversion found in mysqlclient library is planned for one + * of the next releases + * A completely new, fully dynamic, dramatic and fully mutable result + * set has been designed and will be implemented in some of 2.x + * releases + * Several smaller fixes and improvements, including defaulting + * exceptions to true, instead of false, as of this version + * An up-to-date and complete Postscript version of documentation is + * included in this distribution + * Large chunks of this manual are changed, as well as README and + * TODO files. + +1.6 (Feb 3 2000) Sinisa Milivojevic + + * This is a major release as it includes new features and major + * rewrites + * Automatic quoting and escaping with streams. It works + * automatically , depending on the column type. It will work with << + * on all ostream derived types. it is paricularly handy with query + * objects and strstreams. Automatic quoting and escaping on cout, + * cerr and clog stream objects is intentionally left out, as quoting + * / escaping on those stream objects is not necessary. This feature + * can be turned of by setting global boolean dont_quote_auto to + * true. + * Made some major changes in code, so that now execute method should + * be used only with SSQL and template queries, while for all other + * query execution of UPDATE's, INSERT's, DELETE's, new method exec() + * should be used. It is also faster. + * New method get_string is inroduced for easier handling / casting + * ColData into C++ strings. + * Major rewrite of entire code, which led to it's reduction and + * speed improvement. This also led to removal of several source + * files. + * Handling of binary data is introduced. No application program + * changes are required. One of new example programs demonstrates + * handling of binary data + * Three new example programs have been written and thoroughly + * tested. Their intention is to solve some problems addressed by + * MySQL users. + * Thorough changes is Makefile system has been made + * Better configuration scripts are written, thanks to D.Hawkins + * + * Added several bug fixes + * Changed Manual and Changelog + +1.5 (Dec 1 1999) Sinisa Milivojevic + + * Fixed bug in template queries, introduced in 1.4 (!) + * Fixed connect bug + * Fixed several bug in type_info classes + * Added additional robustness in classes + * Added additional methods for SQL type info + * Changed Changelog and README + +1.4 (Nov 25 1999) Sinisa Milivojevic + + * Fixed bug in store and storein methods + * Fixed one serious memory leak + * Fixed a very serious bug generated by gcc 2.95.xx !! + * Added robustness in classes, so that e.g. same query and row + * objects can be re-used + * Changed sinisa_ex example to reflect and demonstrate this + * stability + * Changed Changelog and README + * Few other bug fixes and small improvements and speed-ups + +1.3 (Nov 10 1999) Sinisa Milivojevic + + * Fixed several erronous definitions + * Further changed source to be 2.95.2 compatible + * Expunged unused statements, especially dubious ones, like use of + * pointer_tracker + * Corrected bug in example file fieldinf1 + * Finally fixed mysql_init in Connection constructor, which provided + * much greater stability ! + * Added read and get options, so that clients, like mysqlgui can use + * it + * Changed Changelog and README + * Many other bug fixes. + +1.2 (Oct 15 1999) Sinisa Milivojevic + + * First offical release. Version 1.0 and 1.1 were releases by Sinisa + * before I (Kevin Atkinson) made him the offical maintainer, + * Many manual fixes. + * Changed README and Changelog + * Changed source to be compilable by gcc 2.95.xx, tribute to Kevin + * Atkinson + * Added methods in Connection class which are necessary for + * fullfilling administrative functions with MySQL + * Added many bug fixes in code pertaining to missing class + * initializers , as notified by Michael Rendell + * Sinisa Milivojevic is now the offical + * maintainer. + +1.1 (Aug 2 1999) Sinisa Milivojevic + + * Added several bug fixes + * Fixed memory leak problems and variables overlapping problems. + * Added automake and autoconf support by loic@ceic.com + * Added Makefile for manual + * Added support for cygwin + * Added example sinisa_ex (let modesty prevail) which used to crash + * a lot when memory allocation, memory leak and overlap problems + * were present. Smooth running of this example proves that all those + * bugs are fixed + * Corrected bugs in sql_query.cc regarding delete versus delete[] + * and string length in manip.cc + * Changed manual + * Changed README + * Many other smaller things + +1.0 (June 9 1999) Michael Widenius + + * Added patches from Orion Poplawski to support the + * UnixWare 7.0 compiler + +.64.1.1a (Sep 27 1998) + + * Fixed several bugs that caused my library to fail to compile with + * egcs 1.1. Hopefully it will still compile with egcs 1.0 however I + * have not been able to test it with egcs 1.0. + * Removed some problem causing debug output in sql++pretty. + +.64.1a (Aug 1 1998) + + * Added an (almost) full guide to using Template Queries. + * Fixed it so the SQLQuery will throw an exception when all the + * template parameters are not provided. + * Proofread and speedchecked the manual (it really needed it). + * Other minor document fixes. + +.64.0.1a (July 31 1998) + + * Reworked the Class Reference section a bit. + * Minor document fixes + * Added more examples for SSQLS. + * Changed the syntax of equal_list for SSQLS from equal_list (cchar + * *, Manip, cchar *) to (cchar *, cchar *, Manip). + * Added set methods to SSQLS. These new methods do the same thing as + * there corresponding constructors. + * Added methods for creating a mysql_type_info from a C++ type_info. + +.64.a (July 24 1998) + + * Changed the names of all the classes so they no longer have to + * have Mysql in the begging of it. However if this creates a problem + * you can define a macro to only use the old names instead. + * The Specialized SQL Structures (formally known as Custom Mysql + * Structures) changed from mysql_ to sql_. + * Added the option of using exceptions thoughout the API. + * ColData (formally known as MysqlStrings) will now throw an + * exception if there is a problem in the conversion. + * Added a null adapter. + * Added Mutable Result Sets + * Added a very basic runtime type identification for SQL types + * Changed the document format from POD to LYX . + * Am now using a modified version of Perceps to extract the class + * information directly from the code to make my life easier. + * Added an option of defining a macro to avoid using the automatic + * conversion with binary operators. + * Other small fixed I probully forgot to mentune. + +.63.1.a + + * Added Custom Mysql Structures. + * Fixed the Copy constructor of class Mysql + * Started adding code so that class Mysql lets it children now when + * it is leaving + * Attempted to compile it into a library but still need help. As + * default it will compile as a regular program. + * Other small fixes. + +.62.a (May 3 1998) + + * Added Template Queries + * Created s separate SQLQuery object that is independent of an SQL + * connection. + * You no longer have to import the data for the test program as the + * program creates the database and tables it needs. + * Many small bug fixes. + +.61.1.a (April 28 1998) + + * Cleaned up the example code in test.cc and included it in the + * manual. + * Added an interface layout plan to the manual. + * Added a reverse iterator. + * Fixed a bug with row.hh (It wasn't being included because of a + * typo). + +.61.0.a + + * Major interface changes. I warned you that the interface may + * change while it is in pre-alpha state and I wasn't kidding. + * Created a new and Separate Query Object. You can no longer execute + * queries from the Mysql object instead you have to create a query + * object with Mysql::query() and use it to execute queries. + * Added the comparison operators to MysqlDate, MysqlTime and + * MysqlDateTime. Fixed a few bugs in the MysqlDate... that effected + * the stream output and the conversion of them to strings. + * Reflected the MysqlDate... changes in the manual. + * Added a new MysqlSet object and a bunch of functions for working + * with mysql set strings. + +.60.3a (April 24 1998) + + * Changed strtoq and strtouq to strtoll and strtull for metter + * compatibility Minor Manual fix. + * Changed makefile to make it more compatible with Solaris (Thanks + * Chris H) + * Fixed bug in comparison functions so that they would compare in he + * right direction. + * Added some items to the to do list be sure to have a look. + ADDED HACKERS.txt Index: HACKERS.txt ================================================================== --- /dev/null +++ HACKERS.txt @@ -0,0 +1,228 @@ +If you are going to make any changes to MySQL++, this file has some +hints and commentary you may find helpful. + + +Subversion Access +~~~~~~~~~~~~~~~~~ + To check out the current development version from the Gna! + Subversion repository, say: + + $ svn co svn://svn.gna.org/svn/mysqlpp/trunk mysqlpp + + If you're a MySQL++ committer, use svn over ssh instead: + + $ svn co svn+ssh://LOGIN@svn.gna.org/svn/mysqlpp/trunk mysqlpp + + where LOGIN is your Gna! login name. You will have to have your + ssh public key(s) registered with Gna! for this to work. + + +Bootstrapping the Library +~~~~~~~~~~~~~~~~~~~~~~~~~ + When you check out MySQL++ from svn, there are a lot of things + "missing" as compared to a distributed tarball, because the + svn repository contains only source files, no generated files. + + If you're using Windows, there is a simple batch file called + bootstrap.bat which wraps up all the steps you need to build + these "missing" files. To run it, just say "bootstrap" from a + command shell in the top MySQL++ source directory. For it to run + correctly, you will need Bakefile 0.2.3 (http://bakefile.org/) and + a Perl 5 interpreter installed on your system, both in the PATH. + The bootstrap script is smart enough to recognize when these + tools are missing and stop processing so you can fix the problem. + + For all other platforms, there's a Bourne shell script called + bootstrap. It's quite a bit more complex than the bootstrap.bat + file. It does more, and takes many optional arguments to control + its behavior. All of this is documented in a separate section + below. For many systems, it suffices to just run it without + any arguments: + + $ ./bootstrap + + In addition to Bakefile 0.2.3 and Perl 5, you'll also need autoconf + 1.59 or higher for this to run successfully. + + +Submitting Patches +~~~~~~~~~~~~~~~~~~ + If you wish to submit a patch to the library, please send it to + the MySQL++ mailing list, or attach it to an entry in our bug + tracker on Gna! We want patches in unified diff format. + + The easiest way to get a unified diff is to check out a copy of + the current MySQL++ tree as described in the previous section. + Then make your change, cd to the MySQL++ root directory, and ask + Subversion to generate the diff for you: + + $ svn diff > mychange.patch + + If your patch adds new files to the distribution, you can say + "svn add newfile" before you do the diff, which will include + the contents of that file in the patch. (You can do this even + when you've checked out the tree anonymously.) Then say "svn + revert newfile" to make Subversion forget about the new file. + + If you're making a patch against a MySQL++ distribution tarball, + then you can generate the diff this way: + + $ diff -ruN mysql++-olddir mysql++-newdir > mychange.patch + + The diff command is part of every Unix and Linux system, and + should be installed by default. If you're on a Windows machine, + GNU diff is part of Cygwin (http://cygwin.com/). Subversion is + also available for all of these systems. There are no excuses + for not being able to make unified diffs. :) + + +Testing Your Proposed Change +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + In v2.3.2, we added a new script called 'dtest'. You run it + like you would most of the examples, except that you don't need + to run it via exrun: + + $ ./dtest [password] [user] [server_addr] + + This automatically runs most of the examples, captures the outputs + to a file, and then compares that to a known-good run's outputs. + The purpose of this is that, before you submit a patch, run dtest + and see if it indicates that anything has changed. If something + has and you can't account for it, it represents a problem that + you'll have to fix before submitting the patch. + + If your change purposely causes different outputs from the dtest + run stored in svn, remove the bmark.txt file, then re-run dtest and + include the bmark.txt diffs with your patch. This communicates + to us the fact that you know there are differences and want the + patch evaluated anyway. Otherwise, we are likely to view the + change as a bug. + + +Adding Support for a Different Compiler +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + MySQL++ uses the Bakefile system for creating project files + and makefiles. This allows us to make changes to a single set + of files, and have the proper changes be made to all generated + project files and makefiles. In the past, we used more ad-hoc + systems, and we'd frequently forget to update individual project + files and makefiles, so at any given time, at least one target + was likely to be broken. + + If MySQL++ doesn't currently ship with project files or makefiles + tuned for your compiler of choice, you need to work through the + Bakefile mechanism to add support. We're not willing to do ad-hoc + platform support any more, so please don't ask if you can send + us project files instead; we don't want them. + + If you want to port MySQL++ to another platform, we need to be + confident that the entire library works on your platform before + we'll accept patches. In the past, we've had broken ports that + were missing important library features, or that crashed when built + in certain ways. Few people will knowingly use a crippled version + of MySQL++, since there are usually acceptable alternatives. + Therefore, such ports become maintenance baggage with little + compensating value. + + +On Manipulating the Build System Source Files +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + If you're using Visual C++, there are two ways to change the Visual + Studio project files: + + - You can just make the changes directly within Visual Studio. This + is a fine way to do it if you're only making small changes for + your own purposes. + + - The Visual Studio project files are actually generated from + mysql++.bkl by a tool called Bakefile, not maintained directly. + (We do it this way because Bakefile can generate many different + types of makefiles and project files from this single source file, + so all the platforms we support get all the changes at once.) So, + if you want to make changes to the project files and contribute + them back to the MySQL++ project, you need to do the changes + in mysql++.bkl instead. Rather than run Bakefile directly to + regenerate the project files, we've wrapped up the necessary steps + in the rebake.bat batch file. Any arguments passed to rebake get + sent on to Bakefile without change. + + If you're on a Unixy platform, things are a little more complex + because the build system uses Autoconf in addition to Bakefile. + The source files are mysql++.bkl, configure.ac, and config/*. If you + change any of these, run the bootstrap script to rebuild all their + descendant files. + + The bootstrap script also has other functions besides running + Bakefile and Autoconf for you: + + $ ./bootstrap [no{doc,ex,lib,opt}] [pedantic] [bat] \ + [configure flags] + + Arguments: + + nodoc The documentation won't be considered a prerequisite for + building the distribution tarball. This is useful on systems + where the documentation doesn't build correctly, and you only + need to make a binary RPM. That process requires a tarball, + but doesn't need the documentation. Don't distribute the + tarball or SRPM that results, as they are no good for any + other purpose. + + noex The generated Makefiles and project files won't try to build + any of the examples. + + nolib The generated Makefiles and project files won't try to build + the MySQL++ library. + + nomaint Turn off "maintainer mode" stuff in the build. These are + features used only by those building MySQL++ from svn. The + 'dist' build target uses this when creating the tarball. + + noopt Compiler optimization will be turned off. (This currently + has no effect on MinGW or Visual C++.) + + pedantic + Turns on all of GCC's warnings and portability checks. + Good for checking changes before making a public release. + + bat Asks cmd.exe to run bootstrap.bat for you. This is useful + when using Cygwin just as a command shell in preference + to cmd.exe, as opposed to using Cygwin to build MySQL++ + using its native tools. Passing 'bat' stops all command + line processing in the bootstrap script, so if you + also pass some of the other options, make 'bat' last. + The only options that affect the built project files and + Makefiles work are the no* ones. + + configure options + As soon as the bootstrap script sees an option that it + doesn't understand, it stops processing the command line. + Any subsequent options are passed to the configure script. + See README-Unix.txt for more on configure script options. + + +Maintaining a Private CVS Repository +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + You may find it helpful to maintain your own CVS repository. + Whenever there is a new MySQL++ release, import it on the vendor + branch like this: + + $ cvs import -m "Version 1.7.35" software/mysql++ mysql++ mysql++-1_7_35 + + (This assumes that you have your CVSROOT environment variable + set properly.) + + Update the HEAD branch like this: + + $ cd mysql++ + $ cvs update -PdA + $ cvs update -j HEAD -j mysql++-1_7_35 -Pd + $ cvs ci -m "merged 1.7.35 into HEAD" + $ cvs tag mysql++-1_7_35-merged + + Then any changes you make can easily be tracked, and diffs can + be produced with rdiff: + + $ cvs rdiff -ru mysql++-1_7_35 -r mysql++-1_7_35_equal_list \ + $(cat CVS/Repository) > equal_list.patch + ADDED INSTALL.txt Index: INSTALL.txt ================================================================== --- /dev/null +++ INSTALL.txt @@ -0,0 +1,9 @@ +The installation procedure depends on the compiler you use to build +MySQL++. See: + + README-Cygwin.txt - for Cygwin + README-MinGW.txt - for MinGW + README-Unix.txt - for Unix, Linux, Mac OS X, etc. + README-Visual-C++.txt - for Visual C++ + +Also see the main README.txt file for things that apply to all systems. DELETED LGPL Index: LGPL ================================================================== --- LGPL +++ /dev/null @@ -1,481 +0,0 @@ - GNU LIBRARY GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 library GPL. It is - numbered 2 because it goes with version 2 of the ordinary GPL.] - - 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 Library General Public License, applies to some -specially designated Free Software Foundation software, and to any -other libraries whose authors decide to use it. You can use it for -your libraries, too. - - When we speak of free software, we are referring to freedom, 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 or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the 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 a program 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. - - Our method of protecting your rights has two steps: (1) copyright -the library, and (2) offer you this license which gives you legal -permission to copy, distribute and/or modify the library. - - Also, for each distributor's protection, we want to make certain -that everyone understands that there is no warranty for this free -library. If the library is modified by someone else and passed on, we -want its recipients to know that what they have is not the original -version, so that any problems introduced by others will not reflect on -the original authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that companies distributing free -software will individually obtain patent licenses, thus in effect -transforming the program into proprietary software. To prevent this, -we have made it clear that any patent must be licensed for everyone's -free use or not licensed at all. - - Most GNU software, including some libraries, is covered by the ordinary -GNU General Public License, which was designed for utility programs. This -license, the GNU Library General Public License, applies to certain -designated libraries. This license is quite different from the ordinary -one; be sure to read it in full, and don't assume that anything in it is -the same as in the ordinary license. - - The reason we have a separate public license for some libraries is that -they blur the distinction we usually make between modifying or adding to a -program and simply using it. Linking a program with a library, without -changing the library, is in some sense simply using the library, and is -analogous to running a utility program or application program. However, in -a textual and legal sense, the linked executable is a combined work, a -derivative of the original library, and the ordinary General Public License -treats it as such. - - Because of this blurred distinction, using the ordinary General -Public License for libraries did not effectively promote software -sharing, because most developers did not use the libraries. We -concluded that weaker conditions might promote sharing better. - - However, unrestricted linking of non-free programs would deprive the -users of those programs of all benefit from the free status of the -libraries themselves. This Library General Public License is intended to -permit developers of non-free programs to use free libraries, while -preserving your freedom as a user of such programs to change the free -libraries that are incorporated in them. (We have not seen how to achieve -this as regards changes in header files, but we have achieved it as regards -changes in the actual functions of the Library.) The hope is that this -will lead to faster development of free libraries. - - 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, while the latter only -works together with the library. - - Note that it is possible for a library to be covered by the ordinary -General Public License rather than by this special one. - - GNU LIBRARY GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library which -contains a notice placed by the copyright holder or other authorized -party saying it may be distributed under the terms of this Library -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 compile 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) 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. - - c) 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. - - d) 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 source code 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 to -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 Library 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 - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! ADDED LICENSE.txt Index: LICENSE.txt ================================================================== --- /dev/null +++ LICENSE.txt @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin St, 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 + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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. + + 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 St, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + DELETED Makefile.am Index: Makefile.am ================================================================== --- Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -EXTRA_DIST = .version Configure doc devel - -SUBDIRS = sqlplusint examples doc ADDED Makefile.mingw Index: Makefile.mingw ================================================================== --- /dev/null +++ Makefile.mingw @@ -0,0 +1,588 @@ +# ========================================================================= +# This makefile was generated by +# Bakefile 0.2.3 (http://www.bakefile.org) +# Do not modify, all changes will be overwritten! +# ========================================================================= + + + +# ------------------------------------------------------------------------- +# These are configurable options: +# ------------------------------------------------------------------------- + +# Compiler flags to link shared library +LINK_DLL_FLAGS := -shared + +# C++ compiler +CXX := g++ + +# Standard flags for C++ +CXXFLAGS := + +# Standard preprocessor flags (common for CC and CXX) +CPPFLAGS := + +# Standard linker flags +LDFLAGS := + +# Type of compiled binaries [debug,release] +BUILD := debug + + + +# ------------------------------------------------------------------------- +# Do not modify the rest of this file! +# ------------------------------------------------------------------------- + +### Variables: ### + +CPPDEPS = -MT$@ -MF$@.d -MD +MYSQLPP_CXXFLAGS = $(__DEBUGINFO) -mthreads -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -DHAVE_MYSQL_SSL_SET -I"C:\Program Files\MySQL\MySQL Server \ + 5.0\include" $(CPPFLAGS) $(CXXFLAGS) +MYSQLPP_OBJECTS = \ + mysqlpp_beemutex.o \ + mysqlpp_connection.o \ + mysqlpp_cpool.o \ + mysqlpp_datetime.o \ + mysqlpp_dbdriver.o \ + mysqlpp_field_names.o \ + mysqlpp_field_types.o \ + mysqlpp_manip.o \ + mysqlpp_myset.o \ + mysqlpp_mysql++.o \ + mysqlpp_mystring.o \ + mysqlpp_null.o \ + mysqlpp_options.o \ + mysqlpp_qparms.o \ + mysqlpp_query.o \ + mysqlpp_result.o \ + mysqlpp_row.o \ + mysqlpp_sql_buffer.o \ + mysqlpp_stadapter.o \ + mysqlpp_tcp_connection.o \ + mysqlpp_transaction.o \ + mysqlpp_type_info.o \ + mysqlpp_uds_connection.o \ + mysqlpp_vallist.o \ + mysqlpp_wnp_connection.o +TEST_CPOOL_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +TEST_CPOOL_OBJECTS = \ + test_cpool_cpool.o +TEST_DATETIME_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +TEST_DATETIME_OBJECTS = \ + test_datetime_datetime.o +TEST_INTTYPES_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +TEST_INTTYPES_OBJECTS = \ + test_inttypes_inttypes.o +TEST_MANIP_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +TEST_MANIP_OBJECTS = \ + test_manip_manip.o +TEST_NULL_COMPARISON_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE \ + -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server \ + 5.0\include" $(CPPFLAGS) $(CXXFLAGS) +TEST_NULL_COMPARISON_OBJECTS = \ + test_null_comparison_null_comparison.o +TEST_QSSQLS_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +TEST_QSSQLS_OBJECTS = \ + test_qssqls_qssqls.o +TEST_QSTREAM_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +TEST_QSTREAM_OBJECTS = \ + test_qstream_qstream.o +TEST_STRING_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +TEST_STRING_OBJECTS = \ + test_string_string.o +TEST_TCP_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +TEST_TCP_OBJECTS = \ + test_tcp_tcp.o +TEST_UDS_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +TEST_UDS_OBJECTS = \ + test_uds_uds.o +TEST_WNP_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +TEST_WNP_OBJECTS = \ + test_wnp_wnp.o +EXCOMMON_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +EXCOMMON_OBJECTS = \ + excommon_cmdline.o \ + excommon_printdata.o +CGI_JPEG_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +CGI_JPEG_OBJECTS = \ + cgi_jpeg_cgi_jpeg.o +CPOOL_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +CPOOL_OBJECTS = \ + cpool_cpool.o +DBINFO_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +DBINFO_OBJECTS = \ + dbinfo_dbinfo.o +DEADLOCK_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +DEADLOCK_OBJECTS = \ + deadlock_deadlock.o +FIELDINF_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +FIELDINF_OBJECTS = \ + fieldinf_fieldinf.o +FOR_EACH_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +FOR_EACH_OBJECTS = \ + for_each_for_each.o +LOAD_JPEG_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +LOAD_JPEG_OBJECTS = \ + load_jpeg_load_jpeg.o +MULTIQUERY_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +MULTIQUERY_OBJECTS = \ + multiquery_multiquery.o +RESETDB_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +RESETDB_OBJECTS = \ + resetdb_resetdb.o +SIMPLE1_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +SIMPLE1_OBJECTS = \ + simple1_simple1.o +SIMPLE2_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +SIMPLE2_OBJECTS = \ + simple2_simple2.o +SIMPLE3_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +SIMPLE3_OBJECTS = \ + simple3_simple3.o +SSQLS1_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +SSQLS1_OBJECTS = \ + ssqls1_ssqls1.o +SSQLS2_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +SSQLS2_OBJECTS = \ + ssqls2_ssqls2.o +SSQLS3_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +SSQLS3_OBJECTS = \ + ssqls3_ssqls3.o +SSQLS4_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +SSQLS4_OBJECTS = \ + ssqls4_ssqls4.o +SSQLS5_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +SSQLS5_OBJECTS = \ + ssqls5_ssqls5.o +STORE_IF_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +STORE_IF_OBJECTS = \ + store_if_store_if.o +TQUERY1_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +TQUERY1_OBJECTS = \ + tquery1_tquery1.o +TQUERY2_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +TQUERY2_OBJECTS = \ + tquery2_tquery2.o +TQUERY3_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +TQUERY3_OBJECTS = \ + tquery3_tquery3.o +TRANSACTION_CXXFLAGS = -mthreads $(__DEBUGINFO) -Ilib -DUNICODE -D_UNICODE \ + -DMYSQLPP_NO_DLL -I"C:\Program Files\MySQL\MySQL Server 5.0\include" \ + $(CPPFLAGS) $(CXXFLAGS) +TRANSACTION_OBJECTS = \ + transaction_transaction.o + +### Conditionally set variables: ### + +ifeq ($(BUILD),debug) +__DEBUGINFO = -g +endif +ifeq ($(BUILD),release) +__DEBUGINFO = +endif + + +### Targets: ### + +all: mysqlpp.dll test_cpool.exe test_datetime.exe test_inttypes.exe test_manip.exe test_null_comparison.exe test_qssqls.exe test_qstream.exe test_string.exe test_tcp.exe test_uds.exe test_wnp.exe libmysqlpp_excommon.a cgi_jpeg.exe cpool.exe dbinfo.exe deadlock.exe fieldinf.exe for_each.exe load_jpeg.exe multiquery.exe resetdb.exe simple1.exe simple2.exe simple3.exe ssqls1.exe ssqls2.exe ssqls3.exe ssqls4.exe ssqls5.exe store_if.exe tquery1.exe tquery2.exe tquery3.exe transaction.exe + +clean: + -if exist .\*.o del .\*.o + -if exist .\*.d del .\*.d + -if exist mysqlpp.dll del mysqlpp.dll + -if exist libmysqlpp.a del libmysqlpp.a + -if exist test_cpool.exe del test_cpool.exe + -if exist test_datetime.exe del test_datetime.exe + -if exist test_inttypes.exe del test_inttypes.exe + -if exist test_manip.exe del test_manip.exe + -if exist test_null_comparison.exe del test_null_comparison.exe + -if exist test_qssqls.exe del test_qssqls.exe + -if exist test_qstream.exe del test_qstream.exe + -if exist test_string.exe del test_string.exe + -if exist test_tcp.exe del test_tcp.exe + -if exist test_uds.exe del test_uds.exe + -if exist test_wnp.exe del test_wnp.exe + -if exist libmysqlpp_excommon.a del libmysqlpp_excommon.a + -if exist cgi_jpeg.exe del cgi_jpeg.exe + -if exist cpool.exe del cpool.exe + -if exist dbinfo.exe del dbinfo.exe + -if exist deadlock.exe del deadlock.exe + -if exist fieldinf.exe del fieldinf.exe + -if exist for_each.exe del for_each.exe + -if exist load_jpeg.exe del load_jpeg.exe + -if exist multiquery.exe del multiquery.exe + -if exist resetdb.exe del resetdb.exe + -if exist simple1.exe del simple1.exe + -if exist simple2.exe del simple2.exe + -if exist simple3.exe del simple3.exe + -if exist ssqls1.exe del ssqls1.exe + -if exist ssqls2.exe del ssqls2.exe + -if exist ssqls3.exe del ssqls3.exe + -if exist ssqls4.exe del ssqls4.exe + -if exist ssqls5.exe del ssqls5.exe + -if exist store_if.exe del store_if.exe + -if exist tquery1.exe del tquery1.exe + -if exist tquery2.exe del tquery2.exe + -if exist tquery3.exe del tquery3.exe + -if exist transaction.exe del transaction.exe + +mysqlpp.dll: $(MYSQLPP_OBJECTS) + $(CXX) $(LINK_DLL_FLAGS) -fPIC -o $@ $(MYSQLPP_OBJECTS) $(LDFLAGS) -Wl,--out-implib=libmysqlpp.a $(__DEBUGINFO) -mthreads -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lwsock32 -lmysqlclient + +test_cpool.exe: $(TEST_CPOOL_OBJECTS) mysqlpp.dll + $(CXX) -o $@ $(TEST_CPOOL_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlclient -lmysqlpp + +test_datetime.exe: $(TEST_DATETIME_OBJECTS) mysqlpp.dll + $(CXX) -o $@ $(TEST_DATETIME_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlclient -lmysqlpp + +test_inttypes.exe: $(TEST_INTTYPES_OBJECTS) mysqlpp.dll + $(CXX) -o $@ $(TEST_INTTYPES_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlclient -lmysqlpp + +test_manip.exe: $(TEST_MANIP_OBJECTS) mysqlpp.dll + $(CXX) -o $@ $(TEST_MANIP_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlclient -lmysqlpp + +test_null_comparison.exe: $(TEST_NULL_COMPARISON_OBJECTS) mysqlpp.dll + $(CXX) -o $@ $(TEST_NULL_COMPARISON_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlclient -lmysqlpp + +test_qssqls.exe: $(TEST_QSSQLS_OBJECTS) mysqlpp.dll + $(CXX) -o $@ $(TEST_QSSQLS_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlclient -lmysqlpp + +test_qstream.exe: $(TEST_QSTREAM_OBJECTS) mysqlpp.dll + $(CXX) -o $@ $(TEST_QSTREAM_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlclient -lmysqlpp + +test_string.exe: $(TEST_STRING_OBJECTS) mysqlpp.dll + $(CXX) -o $@ $(TEST_STRING_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlclient -lmysqlpp + +test_tcp.exe: $(TEST_TCP_OBJECTS) mysqlpp.dll + $(CXX) -o $@ $(TEST_TCP_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlclient -lmysqlpp + +test_uds.exe: $(TEST_UDS_OBJECTS) mysqlpp.dll + $(CXX) -o $@ $(TEST_UDS_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlclient -lmysqlpp + +test_wnp.exe: $(TEST_WNP_OBJECTS) mysqlpp.dll + $(CXX) -o $@ $(TEST_WNP_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlclient -lmysqlpp + +libmysqlpp_excommon.a: $(EXCOMMON_OBJECTS) mysqlpp.dll + if exist $@ del $@ + ar rcu $@ $(EXCOMMON_OBJECTS) + ranlib $@ + +cgi_jpeg.exe: $(CGI_JPEG_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll + $(CXX) -o $@ $(CGI_JPEG_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlpp_excommon -lmysqlclient -lmysqlpp + +cpool.exe: $(CPOOL_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll + $(CXX) -o $@ $(CPOOL_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlpp_excommon -lmysqlclient -lmysqlpp + +dbinfo.exe: $(DBINFO_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll + $(CXX) -o $@ $(DBINFO_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlpp_excommon -lmysqlclient -lmysqlpp + +deadlock.exe: $(DEADLOCK_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll + $(CXX) -o $@ $(DEADLOCK_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlpp_excommon -lmysqlclient -lmysqlpp + +fieldinf.exe: $(FIELDINF_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll + $(CXX) -o $@ $(FIELDINF_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlpp_excommon -lmysqlclient -lmysqlpp + +for_each.exe: $(FOR_EACH_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll + $(CXX) -o $@ $(FOR_EACH_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlpp_excommon -lmysqlclient -lmysqlpp + +load_jpeg.exe: $(LOAD_JPEG_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll + $(CXX) -o $@ $(LOAD_JPEG_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlpp_excommon -lmysqlclient -lmysqlpp + +multiquery.exe: $(MULTIQUERY_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll + $(CXX) -o $@ $(MULTIQUERY_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlpp_excommon -lmysqlclient -lmysqlpp + +resetdb.exe: $(RESETDB_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll + $(CXX) -o $@ $(RESETDB_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlpp_excommon -lmysqlclient -lmysqlpp + +simple1.exe: $(SIMPLE1_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll + $(CXX) -o $@ $(SIMPLE1_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlpp_excommon -lmysqlclient -lmysqlpp + +simple2.exe: $(SIMPLE2_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll + $(CXX) -o $@ $(SIMPLE2_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlpp_excommon -lmysqlclient -lmysqlpp + +simple3.exe: $(SIMPLE3_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll + $(CXX) -o $@ $(SIMPLE3_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlpp_excommon -lmysqlclient -lmysqlpp + +ssqls1.exe: $(SSQLS1_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll + $(CXX) -o $@ $(SSQLS1_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlpp_excommon -lmysqlclient -lmysqlpp + +ssqls2.exe: $(SSQLS2_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll + $(CXX) -o $@ $(SSQLS2_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlpp_excommon -lmysqlclient -lmysqlpp + +ssqls3.exe: $(SSQLS3_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll + $(CXX) -o $@ $(SSQLS3_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlpp_excommon -lmysqlclient -lmysqlpp + +ssqls4.exe: $(SSQLS4_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll + $(CXX) -o $@ $(SSQLS4_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlpp_excommon -lmysqlclient -lmysqlpp + +ssqls5.exe: $(SSQLS5_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll + $(CXX) -o $@ $(SSQLS5_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlpp_excommon -lmysqlclient -lmysqlpp + +store_if.exe: $(STORE_IF_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll + $(CXX) -o $@ $(STORE_IF_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlpp_excommon -lmysqlclient -lmysqlpp + +tquery1.exe: $(TQUERY1_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll + $(CXX) -o $@ $(TQUERY1_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlpp_excommon -lmysqlclient -lmysqlpp + +tquery2.exe: $(TQUERY2_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll + $(CXX) -o $@ $(TQUERY2_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlpp_excommon -lmysqlclient -lmysqlpp + +tquery3.exe: $(TQUERY3_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll + $(CXX) -o $@ $(TQUERY3_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlpp_excommon -lmysqlclient -lmysqlpp + +transaction.exe: $(TRANSACTION_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll + $(CXX) -o $@ $(TRANSACTION_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -L"C:\Program Files\MySQL\MySQL Server 5.0\lib\opt" -lmysqlpp_excommon -lmysqlclient -lmysqlpp + +mysqlpp_beemutex.o: ./lib/beemutex.cpp + $(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $< + +mysqlpp_connection.o: ./lib/connection.cpp + $(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $< + +mysqlpp_cpool.o: ./lib/cpool.cpp + $(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $< + +mysqlpp_datetime.o: ./lib/datetime.cpp + $(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $< + +mysqlpp_dbdriver.o: ./lib/dbdriver.cpp + $(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $< + +mysqlpp_field_names.o: ./lib/field_names.cpp + $(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $< + +mysqlpp_field_types.o: ./lib/field_types.cpp + $(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $< + +mysqlpp_manip.o: ./lib/manip.cpp + $(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $< + +mysqlpp_myset.o: ./lib/myset.cpp + $(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $< + +mysqlpp_mysql++.o: ./lib/mysql++.cpp + $(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $< + +mysqlpp_mystring.o: ./lib/mystring.cpp + $(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $< + +mysqlpp_null.o: ./lib/null.cpp + $(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $< + +mysqlpp_options.o: ./lib/options.cpp + $(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $< + +mysqlpp_qparms.o: ./lib/qparms.cpp + $(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $< + +mysqlpp_query.o: ./lib/query.cpp + $(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $< + +mysqlpp_result.o: ./lib/result.cpp + $(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $< + +mysqlpp_row.o: ./lib/row.cpp + $(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $< + +mysqlpp_sql_buffer.o: ./lib/sql_buffer.cpp + $(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $< + +mysqlpp_stadapter.o: ./lib/stadapter.cpp + $(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $< + +mysqlpp_tcp_connection.o: ./lib/tcp_connection.cpp + $(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $< + +mysqlpp_transaction.o: ./lib/transaction.cpp + $(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $< + +mysqlpp_type_info.o: ./lib/type_info.cpp + $(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $< + +mysqlpp_uds_connection.o: ./lib/uds_connection.cpp + $(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $< + +mysqlpp_vallist.o: ./lib/vallist.cpp + $(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $< + +mysqlpp_wnp_connection.o: ./lib/wnp_connection.cpp + $(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $< + +test_cpool_cpool.o: ./test/cpool.cpp + $(CXX) -c -o $@ $(TEST_CPOOL_CXXFLAGS) $(CPPDEPS) $< + +test_datetime_datetime.o: ./test/datetime.cpp + $(CXX) -c -o $@ $(TEST_DATETIME_CXXFLAGS) $(CPPDEPS) $< + +test_inttypes_inttypes.o: ./test/inttypes.cpp + $(CXX) -c -o $@ $(TEST_INTTYPES_CXXFLAGS) $(CPPDEPS) $< + +test_manip_manip.o: ./test/manip.cpp + $(CXX) -c -o $@ $(TEST_MANIP_CXXFLAGS) $(CPPDEPS) $< + +test_null_comparison_null_comparison.o: ./test/null_comparison.cpp + $(CXX) -c -o $@ $(TEST_NULL_COMPARISON_CXXFLAGS) $(CPPDEPS) $< + +test_qssqls_qssqls.o: ./test/qssqls.cpp + $(CXX) -c -o $@ $(TEST_QSSQLS_CXXFLAGS) $(CPPDEPS) $< + +test_qstream_qstream.o: ./test/qstream.cpp + $(CXX) -c -o $@ $(TEST_QSTREAM_CXXFLAGS) $(CPPDEPS) $< + +test_string_string.o: ./test/string.cpp + $(CXX) -c -o $@ $(TEST_STRING_CXXFLAGS) $(CPPDEPS) $< + +test_tcp_tcp.o: ./test/tcp.cpp + $(CXX) -c -o $@ $(TEST_TCP_CXXFLAGS) $(CPPDEPS) $< + +test_uds_uds.o: ./test/uds.cpp + $(CXX) -c -o $@ $(TEST_UDS_CXXFLAGS) $(CPPDEPS) $< + +test_wnp_wnp.o: ./test/wnp.cpp + $(CXX) -c -o $@ $(TEST_WNP_CXXFLAGS) $(CPPDEPS) $< + +excommon_cmdline.o: ./examples/cmdline.cpp + $(CXX) -c -o $@ $(EXCOMMON_CXXFLAGS) $(CPPDEPS) $< + +excommon_printdata.o: ./examples/printdata.cpp + $(CXX) -c -o $@ $(EXCOMMON_CXXFLAGS) $(CPPDEPS) $< + +cgi_jpeg_cgi_jpeg.o: ./examples/cgi_jpeg.cpp + $(CXX) -c -o $@ $(CGI_JPEG_CXXFLAGS) $(CPPDEPS) $< + +cpool_cpool.o: ./examples/cpool.cpp + $(CXX) -c -o $@ $(CPOOL_CXXFLAGS) $(CPPDEPS) $< + +dbinfo_dbinfo.o: ./examples/dbinfo.cpp + $(CXX) -c -o $@ $(DBINFO_CXXFLAGS) $(CPPDEPS) $< + +deadlock_deadlock.o: ./examples/deadlock.cpp + $(CXX) -c -o $@ $(DEADLOCK_CXXFLAGS) $(CPPDEPS) $< + +fieldinf_fieldinf.o: ./examples/fieldinf.cpp + $(CXX) -c -o $@ $(FIELDINF_CXXFLAGS) $(CPPDEPS) $< + +for_each_for_each.o: ./examples/for_each.cpp + $(CXX) -c -o $@ $(FOR_EACH_CXXFLAGS) $(CPPDEPS) $< + +load_jpeg_load_jpeg.o: ./examples/load_jpeg.cpp + $(CXX) -c -o $@ $(LOAD_JPEG_CXXFLAGS) $(CPPDEPS) $< + +multiquery_multiquery.o: ./examples/multiquery.cpp + $(CXX) -c -o $@ $(MULTIQUERY_CXXFLAGS) $(CPPDEPS) $< + +resetdb_resetdb.o: ./examples/resetdb.cpp + $(CXX) -c -o $@ $(RESETDB_CXXFLAGS) $(CPPDEPS) $< + +simple1_simple1.o: ./examples/simple1.cpp + $(CXX) -c -o $@ $(SIMPLE1_CXXFLAGS) $(CPPDEPS) $< + +simple2_simple2.o: ./examples/simple2.cpp + $(CXX) -c -o $@ $(SIMPLE2_CXXFLAGS) $(CPPDEPS) $< + +simple3_simple3.o: ./examples/simple3.cpp + $(CXX) -c -o $@ $(SIMPLE3_CXXFLAGS) $(CPPDEPS) $< + +ssqls1_ssqls1.o: ./examples/ssqls1.cpp + $(CXX) -c -o $@ $(SSQLS1_CXXFLAGS) $(CPPDEPS) $< + +ssqls2_ssqls2.o: ./examples/ssqls2.cpp + $(CXX) -c -o $@ $(SSQLS2_CXXFLAGS) $(CPPDEPS) $< + +ssqls3_ssqls3.o: ./examples/ssqls3.cpp + $(CXX) -c -o $@ $(SSQLS3_CXXFLAGS) $(CPPDEPS) $< + +ssqls4_ssqls4.o: ./examples/ssqls4.cpp + $(CXX) -c -o $@ $(SSQLS4_CXXFLAGS) $(CPPDEPS) $< + +ssqls5_ssqls5.o: ./examples/ssqls5.cpp + $(CXX) -c -o $@ $(SSQLS5_CXXFLAGS) $(CPPDEPS) $< + +store_if_store_if.o: ./examples/store_if.cpp + $(CXX) -c -o $@ $(STORE_IF_CXXFLAGS) $(CPPDEPS) $< + +tquery1_tquery1.o: ./examples/tquery1.cpp + $(CXX) -c -o $@ $(TQUERY1_CXXFLAGS) $(CPPDEPS) $< + +tquery2_tquery2.o: ./examples/tquery2.cpp + $(CXX) -c -o $@ $(TQUERY2_CXXFLAGS) $(CPPDEPS) $< + +tquery3_tquery3.o: ./examples/tquery3.cpp + $(CXX) -c -o $@ $(TQUERY3_CXXFLAGS) $(CPPDEPS) $< + +transaction_transaction.o: ./examples/transaction.cpp + $(CXX) -c -o $@ $(TRANSACTION_CXXFLAGS) $(CPPDEPS) $< + +.PHONY: all clean + + +SHELL := $(COMSPEC) + +# Dependencies tracking: +-include ./*.d ADDED Makefile.simple Index: Makefile.simple ================================================================== --- /dev/null +++ Makefile.simple @@ -0,0 +1,450 @@ +# ========================================================================= +# This makefile was generated by +# Bakefile 0.2.3 (http://www.bakefile.org) +# Do not modify, all changes will be overwritten! +# ========================================================================= + + + +# ------------------------------------------------------------------------- +# These are configurable options: +# ------------------------------------------------------------------------- + +# +AR := ar + +# +RANLIB := ranlib + +# C++ compiler +CXX := g++ + +# Standard flags for C++ +CXXFLAGS := + +# Standard preprocessor flags (common for CC and CXX) +CPPFLAGS := + +# Standard linker flags +LDFLAGS := + +# Type of compiled binaries [debug,release] +BUILD := debug + + + +# ------------------------------------------------------------------------- +# Do not modify the rest of this file! +# ------------------------------------------------------------------------- + +### Variables: ### + +CPPDEPS = -MT$@ -MF`echo $@ | sed -e 's,\.o$$,.d,'` -MD +TEST_CPOOL_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +TEST_CPOOL_OBJECTS = \ + test_cpool_cpool.o +TEST_DATETIME_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +TEST_DATETIME_OBJECTS = \ + test_datetime_datetime.o +TEST_INTTYPES_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +TEST_INTTYPES_OBJECTS = \ + test_inttypes_inttypes.o +TEST_MANIP_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +TEST_MANIP_OBJECTS = \ + test_manip_manip.o +TEST_NULL_COMPARISON_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +TEST_NULL_COMPARISON_OBJECTS = \ + test_null_comparison_null_comparison.o +TEST_QSSQLS_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +TEST_QSSQLS_OBJECTS = \ + test_qssqls_qssqls.o +TEST_QSTREAM_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +TEST_QSTREAM_OBJECTS = \ + test_qstream_qstream.o +TEST_STRING_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +TEST_STRING_OBJECTS = \ + test_string_string.o +TEST_TCP_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +TEST_TCP_OBJECTS = \ + test_tcp_tcp.o +TEST_UDS_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +TEST_UDS_OBJECTS = \ + test_uds_uds.o +TEST_WNP_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +TEST_WNP_OBJECTS = \ + test_wnp_wnp.o +EXCOMMON_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +EXCOMMON_OBJECTS = \ + excommon_cmdline.o \ + excommon_printdata.o +CGI_JPEG_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +CGI_JPEG_OBJECTS = \ + cgi_jpeg_cgi_jpeg.o +CPOOL_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +CPOOL_OBJECTS = \ + cpool_cpool.o +DBINFO_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +DBINFO_OBJECTS = \ + dbinfo_dbinfo.o +DEADLOCK_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +DEADLOCK_OBJECTS = \ + deadlock_deadlock.o +FIELDINF_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +FIELDINF_OBJECTS = \ + fieldinf_fieldinf.o +FOR_EACH_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +FOR_EACH_OBJECTS = \ + for_each_for_each.o +LOAD_JPEG_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +LOAD_JPEG_OBJECTS = \ + load_jpeg_load_jpeg.o +MULTIQUERY_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +MULTIQUERY_OBJECTS = \ + multiquery_multiquery.o +RESETDB_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +RESETDB_OBJECTS = \ + resetdb_resetdb.o +SIMPLE1_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +SIMPLE1_OBJECTS = \ + simple1_simple1.o +SIMPLE2_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +SIMPLE2_OBJECTS = \ + simple2_simple2.o +SIMPLE3_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +SIMPLE3_OBJECTS = \ + simple3_simple3.o +SSQLS1_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +SSQLS1_OBJECTS = \ + ssqls1_ssqls1.o +SSQLS2_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +SSQLS2_OBJECTS = \ + ssqls2_ssqls2.o +SSQLS3_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +SSQLS3_OBJECTS = \ + ssqls3_ssqls3.o +SSQLS4_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +SSQLS4_OBJECTS = \ + ssqls4_ssqls4.o +SSQLS5_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +SSQLS5_OBJECTS = \ + ssqls5_ssqls5.o +STORE_IF_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +STORE_IF_OBJECTS = \ + store_if_store_if.o +TQUERY1_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +TQUERY1_OBJECTS = \ + tquery1_tquery1.o +TQUERY2_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +TQUERY2_OBJECTS = \ + tquery2_tquery2.o +TQUERY3_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +TQUERY3_OBJECTS = \ + tquery3_tquery3.o +TRANSACTION_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \ + -I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS) +TRANSACTION_OBJECTS = \ + transaction_transaction.o + +### Conditionally set variables: ### + +ifeq ($(BUILD),debug) +__DEBUGINFO = -g +endif +ifeq ($(BUILD),release) +__DEBUGINFO = +endif + + +### Targets: ### + +all: test_cpool test_datetime test_inttypes test_manip test_null_comparison test_qssqls test_qstream test_string test_tcp test_uds test_wnp libmysqlpp_excommon.a cgi_jpeg cpool dbinfo deadlock fieldinf for_each load_jpeg multiquery resetdb simple1 simple2 simple3 ssqls1 ssqls2 ssqls3 ssqls4 ssqls5 store_if tquery1 tquery2 tquery3 transaction + +install: all + +uninstall: + +clean: + rm -f ./*.o + rm -f ./*.d + rm -f test_cpool + rm -f test_datetime + rm -f test_inttypes + rm -f test_manip + rm -f test_null_comparison + rm -f test_qssqls + rm -f test_qstream + rm -f test_string + rm -f test_tcp + rm -f test_uds + rm -f test_wnp + rm -f libmysqlpp_excommon.a + rm -f cgi_jpeg + rm -f cpool + rm -f dbinfo + rm -f deadlock + rm -f fieldinf + rm -f for_each + rm -f load_jpeg + rm -f multiquery + rm -f resetdb + rm -f simple1 + rm -f simple2 + rm -f simple3 + rm -f ssqls1 + rm -f ssqls2 + rm -f ssqls3 + rm -f ssqls4 + rm -f ssqls5 + rm -f store_if + rm -f tquery1 + rm -f tquery2 + rm -f tquery3 + rm -f transaction + +test_cpool: $(TEST_CPOOL_OBJECTS) + $(CXX) -o $@ $(TEST_CPOOL_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp -lmysqlclient + +test_datetime: $(TEST_DATETIME_OBJECTS) + $(CXX) -o $@ $(TEST_DATETIME_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp -lmysqlclient + +test_inttypes: $(TEST_INTTYPES_OBJECTS) + $(CXX) -o $@ $(TEST_INTTYPES_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp -lmysqlclient + +test_manip: $(TEST_MANIP_OBJECTS) + $(CXX) -o $@ $(TEST_MANIP_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp -lmysqlclient + +test_null_comparison: $(TEST_NULL_COMPARISON_OBJECTS) + $(CXX) -o $@ $(TEST_NULL_COMPARISON_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp -lmysqlclient + +test_qssqls: $(TEST_QSSQLS_OBJECTS) + $(CXX) -o $@ $(TEST_QSSQLS_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp -lmysqlclient + +test_qstream: $(TEST_QSTREAM_OBJECTS) + $(CXX) -o $@ $(TEST_QSTREAM_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp -lmysqlclient + +test_string: $(TEST_STRING_OBJECTS) + $(CXX) -o $@ $(TEST_STRING_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp -lmysqlclient + +test_tcp: $(TEST_TCP_OBJECTS) + $(CXX) -o $@ $(TEST_TCP_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp -lmysqlclient + +test_uds: $(TEST_UDS_OBJECTS) + $(CXX) -o $@ $(TEST_UDS_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp -lmysqlclient + +test_wnp: $(TEST_WNP_OBJECTS) + $(CXX) -o $@ $(TEST_WNP_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp -lmysqlclient + +libmysqlpp_excommon.a: $(EXCOMMON_OBJECTS) + rm -f $@ + $(AR) rcu $@ $(EXCOMMON_OBJECTS) + $(RANLIB) $@ + +cgi_jpeg: $(CGI_JPEG_OBJECTS) libmysqlpp_excommon.a + $(CXX) -o $@ $(CGI_JPEG_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp_excommon -lmysqlpp -lmysqlclient + +cpool: $(CPOOL_OBJECTS) libmysqlpp_excommon.a + $(CXX) -o $@ $(CPOOL_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp_excommon -lmysqlpp -lmysqlclient + +dbinfo: $(DBINFO_OBJECTS) libmysqlpp_excommon.a + $(CXX) -o $@ $(DBINFO_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp_excommon -lmysqlpp -lmysqlclient + +deadlock: $(DEADLOCK_OBJECTS) libmysqlpp_excommon.a + $(CXX) -o $@ $(DEADLOCK_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp_excommon -lmysqlpp -lmysqlclient + +fieldinf: $(FIELDINF_OBJECTS) libmysqlpp_excommon.a + $(CXX) -o $@ $(FIELDINF_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp_excommon -lmysqlpp -lmysqlclient + +for_each: $(FOR_EACH_OBJECTS) libmysqlpp_excommon.a + $(CXX) -o $@ $(FOR_EACH_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp_excommon -lmysqlpp -lmysqlclient + +load_jpeg: $(LOAD_JPEG_OBJECTS) libmysqlpp_excommon.a + $(CXX) -o $@ $(LOAD_JPEG_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp_excommon -lmysqlpp -lmysqlclient + +multiquery: $(MULTIQUERY_OBJECTS) libmysqlpp_excommon.a + $(CXX) -o $@ $(MULTIQUERY_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp_excommon -lmysqlpp -lmysqlclient + +resetdb: $(RESETDB_OBJECTS) libmysqlpp_excommon.a + $(CXX) -o $@ $(RESETDB_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp_excommon -lmysqlpp -lmysqlclient + +simple1: $(SIMPLE1_OBJECTS) libmysqlpp_excommon.a + $(CXX) -o $@ $(SIMPLE1_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp_excommon -lmysqlpp -lmysqlclient + +simple2: $(SIMPLE2_OBJECTS) libmysqlpp_excommon.a + $(CXX) -o $@ $(SIMPLE2_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp_excommon -lmysqlpp -lmysqlclient + +simple3: $(SIMPLE3_OBJECTS) libmysqlpp_excommon.a + $(CXX) -o $@ $(SIMPLE3_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp_excommon -lmysqlpp -lmysqlclient + +ssqls1: $(SSQLS1_OBJECTS) libmysqlpp_excommon.a + $(CXX) -o $@ $(SSQLS1_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp_excommon -lmysqlpp -lmysqlclient + +ssqls2: $(SSQLS2_OBJECTS) libmysqlpp_excommon.a + $(CXX) -o $@ $(SSQLS2_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp_excommon -lmysqlpp -lmysqlclient + +ssqls3: $(SSQLS3_OBJECTS) libmysqlpp_excommon.a + $(CXX) -o $@ $(SSQLS3_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp_excommon -lmysqlpp -lmysqlclient + +ssqls4: $(SSQLS4_OBJECTS) libmysqlpp_excommon.a + $(CXX) -o $@ $(SSQLS4_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp_excommon -lmysqlpp -lmysqlclient + +ssqls5: $(SSQLS5_OBJECTS) libmysqlpp_excommon.a + $(CXX) -o $@ $(SSQLS5_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp_excommon -lmysqlpp -lmysqlclient + +store_if: $(STORE_IF_OBJECTS) libmysqlpp_excommon.a + $(CXX) -o $@ $(STORE_IF_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp_excommon -lmysqlpp -lmysqlclient + +tquery1: $(TQUERY1_OBJECTS) libmysqlpp_excommon.a + $(CXX) -o $@ $(TQUERY1_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp_excommon -lmysqlpp -lmysqlclient + +tquery2: $(TQUERY2_OBJECTS) libmysqlpp_excommon.a + $(CXX) -o $@ $(TQUERY2_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp_excommon -lmysqlpp -lmysqlclient + +tquery3: $(TQUERY3_OBJECTS) libmysqlpp_excommon.a + $(CXX) -o $@ $(TQUERY3_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp_excommon -lmysqlpp -lmysqlclient + +transaction: $(TRANSACTION_OBJECTS) libmysqlpp_excommon.a + $(CXX) -o $@ $(TRANSACTION_OBJECTS) $(LDFLAGS) $(__DEBUGINFO) -L. -lmysqlpp_excommon -lmysqlpp -lmysqlclient + +test_cpool_cpool.o: ./test/cpool.cpp + $(CXX) -c -o $@ $(TEST_CPOOL_CXXFLAGS) $(CPPDEPS) $< + +test_datetime_datetime.o: ./test/datetime.cpp + $(CXX) -c -o $@ $(TEST_DATETIME_CXXFLAGS) $(CPPDEPS) $< + +test_inttypes_inttypes.o: ./test/inttypes.cpp + $(CXX) -c -o $@ $(TEST_INTTYPES_CXXFLAGS) $(CPPDEPS) $< + +test_manip_manip.o: ./test/manip.cpp + $(CXX) -c -o $@ $(TEST_MANIP_CXXFLAGS) $(CPPDEPS) $< + +test_null_comparison_null_comparison.o: ./test/null_comparison.cpp + $(CXX) -c -o $@ $(TEST_NULL_COMPARISON_CXXFLAGS) $(CPPDEPS) $< + +test_qssqls_qssqls.o: ./test/qssqls.cpp + $(CXX) -c -o $@ $(TEST_QSSQLS_CXXFLAGS) $(CPPDEPS) $< + +test_qstream_qstream.o: ./test/qstream.cpp + $(CXX) -c -o $@ $(TEST_QSTREAM_CXXFLAGS) $(CPPDEPS) $< + +test_string_string.o: ./test/string.cpp + $(CXX) -c -o $@ $(TEST_STRING_CXXFLAGS) $(CPPDEPS) $< + +test_tcp_tcp.o: ./test/tcp.cpp + $(CXX) -c -o $@ $(TEST_TCP_CXXFLAGS) $(CPPDEPS) $< + +test_uds_uds.o: ./test/uds.cpp + $(CXX) -c -o $@ $(TEST_UDS_CXXFLAGS) $(CPPDEPS) $< + +test_wnp_wnp.o: ./test/wnp.cpp + $(CXX) -c -o $@ $(TEST_WNP_CXXFLAGS) $(CPPDEPS) $< + +excommon_cmdline.o: ./examples/cmdline.cpp + $(CXX) -c -o $@ $(EXCOMMON_CXXFLAGS) $(CPPDEPS) $< + +excommon_printdata.o: ./examples/printdata.cpp + $(CXX) -c -o $@ $(EXCOMMON_CXXFLAGS) $(CPPDEPS) $< + +cgi_jpeg_cgi_jpeg.o: ./examples/cgi_jpeg.cpp + $(CXX) -c -o $@ $(CGI_JPEG_CXXFLAGS) $(CPPDEPS) $< + +cpool_cpool.o: ./examples/cpool.cpp + $(CXX) -c -o $@ $(CPOOL_CXXFLAGS) $(CPPDEPS) $< + +dbinfo_dbinfo.o: ./examples/dbinfo.cpp + $(CXX) -c -o $@ $(DBINFO_CXXFLAGS) $(CPPDEPS) $< + +deadlock_deadlock.o: ./examples/deadlock.cpp + $(CXX) -c -o $@ $(DEADLOCK_CXXFLAGS) $(CPPDEPS) $< + +fieldinf_fieldinf.o: ./examples/fieldinf.cpp + $(CXX) -c -o $@ $(FIELDINF_CXXFLAGS) $(CPPDEPS) $< + +for_each_for_each.o: ./examples/for_each.cpp + $(CXX) -c -o $@ $(FOR_EACH_CXXFLAGS) $(CPPDEPS) $< + +load_jpeg_load_jpeg.o: ./examples/load_jpeg.cpp + $(CXX) -c -o $@ $(LOAD_JPEG_CXXFLAGS) $(CPPDEPS) $< + +multiquery_multiquery.o: ./examples/multiquery.cpp + $(CXX) -c -o $@ $(MULTIQUERY_CXXFLAGS) $(CPPDEPS) $< + +resetdb_resetdb.o: ./examples/resetdb.cpp + $(CXX) -c -o $@ $(RESETDB_CXXFLAGS) $(CPPDEPS) $< + +simple1_simple1.o: ./examples/simple1.cpp + $(CXX) -c -o $@ $(SIMPLE1_CXXFLAGS) $(CPPDEPS) $< + +simple2_simple2.o: ./examples/simple2.cpp + $(CXX) -c -o $@ $(SIMPLE2_CXXFLAGS) $(CPPDEPS) $< + +simple3_simple3.o: ./examples/simple3.cpp + $(CXX) -c -o $@ $(SIMPLE3_CXXFLAGS) $(CPPDEPS) $< + +ssqls1_ssqls1.o: ./examples/ssqls1.cpp + $(CXX) -c -o $@ $(SSQLS1_CXXFLAGS) $(CPPDEPS) $< + +ssqls2_ssqls2.o: ./examples/ssqls2.cpp + $(CXX) -c -o $@ $(SSQLS2_CXXFLAGS) $(CPPDEPS) $< + +ssqls3_ssqls3.o: ./examples/ssqls3.cpp + $(CXX) -c -o $@ $(SSQLS3_CXXFLAGS) $(CPPDEPS) $< + +ssqls4_ssqls4.o: ./examples/ssqls4.cpp + $(CXX) -c -o $@ $(SSQLS4_CXXFLAGS) $(CPPDEPS) $< + +ssqls5_ssqls5.o: ./examples/ssqls5.cpp + $(CXX) -c -o $@ $(SSQLS5_CXXFLAGS) $(CPPDEPS) $< + +store_if_store_if.o: ./examples/store_if.cpp + $(CXX) -c -o $@ $(STORE_IF_CXXFLAGS) $(CPPDEPS) $< + +tquery1_tquery1.o: ./examples/tquery1.cpp + $(CXX) -c -o $@ $(TQUERY1_CXXFLAGS) $(CPPDEPS) $< + +tquery2_tquery2.o: ./examples/tquery2.cpp + $(CXX) -c -o $@ $(TQUERY2_CXXFLAGS) $(CPPDEPS) $< + +tquery3_tquery3.o: ./examples/tquery3.cpp + $(CXX) -c -o $@ $(TQUERY3_CXXFLAGS) $(CPPDEPS) $< + +transaction_transaction.o: ./examples/transaction.cpp + $(CXX) -c -o $@ $(TRANSACTION_CXXFLAGS) $(CPPDEPS) $< + +.PHONY: all install uninstall clean + + +# Dependencies tracking: +-include ./*.d DELETED README Index: README ================================================================== --- README +++ /dev/null @@ -1,73 +0,0 @@ -This is C++ API library for MySQL. - -Starting based of 1.2, this is now maintained by sinisa@cytanet.com.cy -as kevinatk@home.com doesn't have time to support this library anymore. - -He has made sinisa@cytanet.com.cy a new official maintainer, which will -continue to keep mysql++ library under LGPL. - - -Original information from kevinatk@home.com: ---------------------------------------------------------------------- - -After several people commented on how my quickie wrapper would be of -little use I decided to go all out and create a full featured -version. - -To my knowledge this library requiures gcc 2.8 or egcc or better and of -course the mysql library. - -To compile the library and modify the file Configure aproprietly -and type make. - -I am working on trying to get this to compile into a library. -However I really don't know what I am doing. If you have some -experense with this please take a look at my makefile and uncomment the -appropriate lines and let me know if I am doing everything right. - -For more information please see the manual. - -I developed it using egcc ver 1.02 (I think) from the Debian hamm -package with kernel 2.0.33 and a Cryix P150+ cpu. I am also using -Mysql 3.21.25 that is in the non-free section of the Debian -distribution. - -Be sure to let me know what you think. I depend on your feedback. - -Thanks, -I can be reached at kevinatk@home.com --------------------------------------------------------------------- -End of original README by Kevin Atkinson - - -Since October 1999, all maintenance has been transferred to Sinisa -Milivojevic (sinisa@cytanet.com.cy) and Michael Widenius (monty@mysql.com). - -Send your feedback to any of these addresses, or even better to the -mailing list mysql-plusplus@lists.mysql.com. - -Since versin 1.1, mysql++ has been prepared to be built with automake and -autoconf. - -This will make compilation and installation much easier. - -You should cd to the root of source directory and run ./configure. - -If you are running it several times, because you have problems, do delete -config.cache. In case of the problem config.log contains more info on -it's whereabouts. - -After configure is run, config.h and Makefiles are generated. - -If you wish to install mysql++ in a root directory other then /usr/local, -you should run configure with --with-prefix=..... - -Configure contains description of other switches available. - -After running configure, run make and make install. Libs will be -installed in prefix/lib and include files in prefix/include/mysql++. - - -Since version 1.3, mysql++ is fully compliant with latest 2.95.xx series -of compilers. - ADDED README-Cygwin.txt Index: README-Cygwin.txt ================================================================== --- /dev/null +++ README-Cygwin.txt @@ -0,0 +1,34 @@ +Prerequisite: Build MySQL +~~~~~~~~~~~~~~~~~~~~~~~~~ + Before you can build MySQL++, you need to build the MySQL client + library from source. This is necessary because Cygwin programs + work best when linked to Cygwin libraries, even though it's + possible to link to some native Windows libraries. You do not + need to build a Cygwin version of the MySQL server; it's still + best to use the native Windows version of that. + + The MySQL client library does not build correctly out of the box. + The best instructions I've found covering the necessary changes + are here: + + http://cygwin.com/ml/cygwin/2004-11/msg00159.html + + I recommend that you use MySQL v4.1.x at this time. Skip the + step changing the pthread stuff in my_thr_init.c, as this change + has already been made in recent versions of MySQL. + + With the changes applied, build and install the client library + like so: + + $ autoreconf --install --verbose --force + $ ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var \ + --infodir=/usr/share/info --mandir=/usr/share/man \ + --disable-shared --without-{debug,readline,libedit,server} + $ make + $ make install + + +Building the Library and Example Programs +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + With that done, you can build MySQL++ just as you would any other + typical Unix program. See README-Unix.txt for details. ADDED README-Mac-OS-X.txt Index: README-Mac-OS-X.txt ================================================================== --- /dev/null +++ README-Mac-OS-X.txt @@ -0,0 +1,76 @@ +OS X is Unix under the hood, so README-Unix.txt covers the generic +bits. I'll just cover a few of the issues specific to OS X here. + + +Prerequisite: Install the MySQL Development Files +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + MySQL++ is built on top of the MySQL C API library, so for MySQL++ + to build, it needs at least that library and its header files + installed. You don't need the server itself installed on your + development machine, though it's often helpful anyway, for testing. + You can get MySQL in at least three different ways for OS X: + + - From Fink: http://finkproject.org/ I mention this first + because it's the method I use to test MySQL++ in development. + If you ask about OS X on the mailing list, you'll get the most + help if you're also using the Fink version of MySQL. Once you + have Fink installed, install the MySQL C API development + files with: + + $ fink install mysql15-dev + + Then, in configuring MySQL++, give the --with-mysql=/sw flag + to the configure script. + + - From MySQL.com. I've not tried the official binaries, + but they're known to work with MySQL++. As I understand it, + they install from a typical Mac GUI installer. I don't know + if it lets you install the development files separately from + the server itself, so be sure to check. The official Windows + installers, for instance, have in the past installed the server + by default but not the development files. + + Once it's installed, the configure script shipped with MySQL++ + v3.0 and up should find the library without any help. + + - From MacPorts, http://macports.org. I have zero information on + this other than that it's theoretically possible for it to work. + If you figure out how to make it work, please post the method + to the mailing list so I can update this document. + + +Making Universal Binaries +~~~~~~~~~~~~~~~~~~~~~~~~~ + The command line build system will generate libraries that + only work with the platform you build MySQL++ on. If you need + to generate a libmysqlpp that works on both Intel and PowerPC + machines, something like this may work: + + $ ./configure CXXFLAGS='-arch ppc -arch i386' --disable-dependency-tracking + + This is untested with MySQL++ in particular, but it's said to work + with other projects. + + Note that with Tiger -- and to a greater extent, Leopard -- + there are really *four* architectures, not two: you have 32-bit + and 64-bit versions of both PowerPC and Intel. I'm not sure + exactly how you'd modify the command above to make a library that + supports all four, but I'll take a wild guess and say you'll need + four -arch flags. Or, you can just avoid the command line build + system, and do it in... + +Xcode +~~~~~ + Until very recently, there's been no official support in MySQL++ + for building on OS X using Xcode. People have gotten it to work + before on their own, but it's not something we felt we could + support directly. + + As of MySQL++ v3.0, we're including Xcode project files. So far, + they're completely untested, but being part of the official + tarball, it obligates us to at least try to support them. :) + If they don't work, see HACKERS.txt for more info on fixing + the source files that generate these project files. We're not + terribly interested in receiving updated project files. They can + be useful for comparison, but ultimately what we care about is + being able to generate them correctly. ADDED README-MinGW.txt Index: README-MinGW.txt ================================================================== --- /dev/null +++ README-MinGW.txt @@ -0,0 +1,103 @@ +Prerequisite: GCC Version +~~~~~~~~~~~~~~~~~~~~~~~~~ + If your MinGW version isn't using at least GCC 3.4.5, it needs + to be updated. Older versions are known to not work with MySQL++. + + +Prerequisite: MySQL C Development Files +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + MySQL++ is built atop MySQL's C API library, so you need to have + MySQL installed on your development system to get the current C API + development files. + + If you do a default installation of MySQL, the development files + probably won't be installed. As of this writing you have to do + either a Complete or Custom install to get these files. (They keep + changing the way the Windows installer works, so this may not be + true any more by the time you read this.) + + The MySQL++ Makefile assumes that you installed MySQL in + + C:\Program Files\MySQL\MySQL Server 5.0\ + + If not, you have two options. + + The simplest is to edit Makefile.mingw. This is a generated + file, but if that's all the only change to MySQL++ you need, + it works fine. + + If you're doing deeper work on MySQL++, you should change the + variable MYSQL_WIN_DIR at the top of mysql++.bkl instead. Then to + generate Makefile.mingw from that file, you will need the Win32 + port of Bakefile from http://bakefile.org/ The command to do + that is: + + bakefile_gen -f mingw + + +Prerequisite: MySQL C API DLL Import Library +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Before you can build MySQL++ with MinGW, you will need to create + a MinGW-compatible import library for MySQL's C API library. + Using the current default install path for MySQL and assuming + MySQL++ is in c:\mysql++, the commands to do this are: + + cd C:\Program Files\MySQL\MySQL Server 5.0\lib\opt + dlltool -k -d c:\mysql++\libmysqlclient.def -l libmysqlclient.a + + +Building the Library and Example Programs +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + With the prerequisites above taken care of, you can build MySQL++ + with this command: + + mingw32-make -f Makefile.mingw + + Notice that we're using the MinGW-specific version of GNU make, not + the Cygwin or MSYS versions. Many things will break otherwise: path + separator handling, shell commands used by the Makefile, etc. + + Speaking of Cygwin and MSYS, if you have either these or any other + Unix emulation environment installed, be sure their executables + aren't in the PATH when building MySQL++. MinGW's version of GNU + make does some funny things if it thinks it's running in the + presence of Unixy tools, which will break the MySQL++ build. + + Once the library is built, you should run the examples. At minimum, + run resetdb and simple1. + + Once you're satisfied that the library is working correctly, you can + run the install.bat file at the project root to automatically + install the library files and headers in subdirectories under + c:\mysql++. + + +Cygwin and MinGW Coexistence +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + It's possible to have both Cygwin and MinGW installed and build with + the MinGW tools without interference from the Cygwin bits. The main + thing you have to take care of is that MinGW's bin directory must + precede the Cygwin bin directory in the PATH, so that its tools are + found first. If you use Cygwin's bash as a command shell in + preference to the DOS-like cmd.exe, you can use this shell script to + temporarily set the environment to "MinGW mode" and make it easy to + get back to "Cygwin mode": + + #!/bin/sh + PATH=/c/mingw/bin:/c/windows:/c/windows/system32:/c/cygwin/bin + echo "Say 'exit' to leave MinGW shell and restore Cygwin environment." + /usr/bin/bash --rcfile ~/.mingwrc + + I recommend having at least this in the ~/.mingwrc file: + + alias make=mingw32-make + PS1='MinGW: \W \$ ' + + The prompt change reminds you that you are in a sub-shell set up for + MinGW. The alias for 'make' ensures you don't accidentally run + Cygwin's make, which won't work with Makefile.mingw. We could just + leave /c/cygwin/bin out of the environment, but there are Cygwin + tools we want access to, like vim. As long as all the MinGW ones + override those Cygwin also provides, we don't need to worry about + having both in the PATH. Besides, having the alias is nice for + those who have 'make' committed to muscle memory. ADDED README-Unix.txt Index: README-Unix.txt ================================================================== --- /dev/null +++ README-Unix.txt @@ -0,0 +1,70 @@ +Building the Library and Example Programs +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + MySQL++ uses GNU autoconf, so you can build it with the standard + commands: + + $ ./configure + $ make + $ su + # make install + + On Linux, you also need to run 'ldconfig' as root after installing + the library. You may need to add the library's installation + directory to /etc/ld.so.conf before you do this, particularly if + you installed to /usr/local. + + +Configure Options +~~~~~~~~~~~~~~~~~ + The configure script takes several interesting options. Say: + + $ ./configure --help + + to get a list. Some of the more interesting flags are: + + --prefix: + + If you wish to install mysql++ in a root directory other than + /usr/local, run configure with --prefix=/some/dir/name + + --with-mysql*: + + If you installed MySQL in an atypical location, the configure + script will not be able to find the library and header + files without help. The simplest way to clue configure into + where MySQL is installed is with the --with-mysql option. + Try something like "--with-mysql=/usr/local/mysql", for + instance. The configure script will then try to guess which + subdirectories under the given directory contain the library + and include files. + + If that doesn't work, it's because the library and header + files aren't in typical locations under the directory you gave + for configure to find them. So, you need to specify them + separately with --with-mysql-include and --with-mysql-lib + instead. As with --with-mysql, configure can often guess + which subdirectory under the given directory contains the + needed files, so you don't necessarily have to give the full + path to these files. + + --enable-thread-check: + + Builds MySQL++ with threading support, if possible. + + This option simply turns on two tests: first, that your + system uses a compatible threading library; and second, + that the thread-safe version of the MySQL C API library + (libmysqlclient_r) is installed and working. If both of + these are true, you get a thread-aware version of MySQL++. + "Thread-aware" means that the library does make an effort to + prevent problems, but we don't guarantee that all possible + uses of MySQL++ are thread-safe. + + Note that this is a suggestion, not a command. If we can't + figure out the system's threading model or can't find the + thread-aware build of the C API library, configure won't fail. + It just reverts to the standard single-thread build. + + See the chapter on threading in the user manual for more + details and advice on creating thread-safe programs with + MySQL++. ADDED README-Visual-C++.txt Index: README-Visual-C++.txt ================================================================== --- /dev/null +++ README-Visual-C++.txt @@ -0,0 +1,218 @@ +Visual C++ Version Compatibility +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + MySQL++ is fully-functional with Visual C++ 2005 and 2008. + + MySQL++ also works with VS 2003, with the exception of the SSQLS + feature. There was partial support for SSQLS in the MySQL++ + v2 series, but a feature we added in MySQL++ v3.0 crashes the + compiler, so we had to remove support for it entirely. You don't + need to change anything to use MySQL++ v3 with Visual C++ 2003. + The SSQLS parts of the library simply don't get built when you + use this compiler. + + Older versions of Visual C++ are basically hopeless when it comes + to having sufficient support for Standard C++ to build MySQL++. + There is an ancient hacked version of MySQL++ on the official + MySQL++ web site that works with Visual C++ 6 and up, but my + advice if you're on so old a compiler is that you're better off + programming straight to the C API, if only because you can still + get support for it. + + There are two sets of .sln and .vcproj files shipped with MySQL++: + one for Visual C++ 2003 in the vc2003 subdirectory, and another + set for VC++ 2005 and newer in vc2005. The only difference + between them is that the VC++ 2003 versions leave out several + things from the build for compatibility reasons. + + +Prerequisites +~~~~~~~~~~~~~ + You need to have the Windows version of the MySQL server installed + on your development system, even if you always access a MySQL + server on a different machine. This is because in addition to + installing the server itself, the official MySQL Windows binaries + also install the client-side development files that MySQL++ + needs in order to communicate with a MySQL server. + + Historically, the Windows version of the MySQL server installer + has sometimes installed the development files by default, and + sometimes not. If you get an error about mysql-version.h or + mysql.h when building MySQL++, you might need to go back and + reinstall the server and select a custom install to enable + installation of the development files. + + If you're getting these header file errors and are certain the + development files are indeed installed, read on in the following + section. + + +Building the Library and Example Programs +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + If you installed the MySQL server somewhere other than + + C:\Program Files\MySQL\MySQL Server 5.0\ + + you need to change the project file settings. If you're willing to + install Bakefile (see below), you can do this quickly by changing + the variable MYSQL_WIN_DIR at the top of the file mysql++.bkl, + then regenerating the project files by running rebake.bat. + Otherwise, you'll need to change the include and library paths + in all of the project files by hand. + + You must build both the Debug and Release versions of the library. + You will need them both because when you build your program in + Release mode, it won't work with a MySQL++ DLL built in Debug mode. + The simplest way to ensure that you're running your program against + the correct DLL is to copy the debug version of the MySQL++ DLL + into your program's Debug build directory, and the same for the + Release directory. + + With the library built, run at least the resetdb and simple1 + examples to ensure that the library is working correctly. + In addition to the other generic examples, there are a few + Visual C++ specific examples that you might want to look at in + examples\vstudio. See README-examples.txt for further details. + + Once you're sure the library is working correctly, you can run + the install.bat file at the project root to automatically install + the library files and headers in subdirectories under c:\mysql++. + + +Using MySQL++ in an MFC Project +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + If you don't already have a project set up, open Visual Studio, say + File::New::Project, then choose Visual C++::MFC::MFC Application. + Go through the wizard setting up the project as you see fit. + + Once you have your project open, right click on your top-level + executable in the Solution Explorer, choose Properties, and make + the following changes. (Where it doesn't specify Debug or Release, + make the change to both configurations.) + + o Append the following to C/C++::General::Additional Include + Directories: + + C:\Program Files\MySQL\MySQL Server 5.0\include, + C:\mysql++\include + + o Under C/C++::Code Generation change "Runtime Library" to + "Multi-threaded Debug DLL (/MDd)" for the Debug + configuration. For the Release configuration, make it + "Multi-threaded DLL (/MD)". + + o Append the following to Linker::General::Additional Library + Directories for the Debug configuration: + + C:\Program Files\MySQL\MySQL Server 5.0\lib\debug, + C:\mysql++\vc\debug + + For the Release configuration, make it the same, but + change the 'debug' directory names to 'opt'. + + o Under Linker::Input add the following to "Additional + Dependencies" for the Debug configuration: + + libmysql.lib wsock32.lib mysqlpp_d.lib + + ...and then for the Release configuration: + + libmysql.lib wsock32.lib mysqlpp.lib + + This difference is because MySQL++'s Debug DLL and import + library have a _d suffix so you can have both installed + without conflicts. + + You may want to study examples\vstudio\mfc\mfc.vcproj to see + this in action. Note that some of the paths will be different, + because it can use relative paths for mysqlpp.dll. + + +Using MySQL++ in a Windows Forms C++/CLI Project +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Before you start work on getting MySQL++ working with your own + program, you need to make some changes to the MySQL++ build + settings. Open mysqlpp.sln, then right-click on the mysqlpp + target and select Properties. Make the following changes for + both the Debug and Release configurations: + + o Under Configuration Properties::General, change "Common + Language Runtime support" to the /clr setting. + + o Under C/C++::Command Line, remove the /EHsc from the + Additional Options section. + + If you have already built MySQL++, be sure to perform a complete + rebuild after changing these options. The compiler will emit + several C4835 warnings after making those changes, which are + harmless when using the DLL with a C++/CLI program, but which warn + of real problems when using it with unmanaged C++. As a result, + it's probably best if you don't install the resulting DLL in a + system level directory. I'd recommend copying it only into the + same directory as the EXE. + + Once you have MySQL++ built with CLR support, open your + program's project. If you don't already have a project set up, + open Visual Studio, say File::New::Project, then choose Visual + C++::CLR::Windows Forms Application. Go through the wizard + setting up the project as you see fit. + + The configuration process isn't much different from that for an + MFC project, so go through the list above first. Then, make the + following changes particular to .NET and C++/CLI: + + o Under Configuration Properties::General change the setting + from /clr:pure to /clr. (You need mixed assembly support + to allow a C++/CLI program to use a plain C++ library + like MySQL++.) + + o For the Linker::Input settings, you don't need wsock32.lib. + The mere fact that you're using .NET takes care of that + dependency for you. + + In the MFC instructions above, it said that you need to build it + using the Multi-threaded DLL version of the C++ Runtime Library. + That's not strictly true for MFC, but it's an absolute requirement + for C++/CLI. See the Remarks in this MSDN article for details: + + http://msdn2.microsoft.com/en-us/library/k8d11d4s.aspx + + You may want to study examples\vstudio\wforms\wforms.vcproj to + see all this in action. Note that some of the paths will be + different, because it can use relative paths for mysqlpp_d.dll + and mysqlpp.dll. + + +Working With Bakefile +~~~~~~~~~~~~~~~~~~~~~ + MySQL++'s Visual Studio project files aren't maintained directly. + Instead, we use a tool called Bakefile (http://bakefile.org/) + to generate many different project file and Makefile types from a + single set of source files. There is a native Windows version of + Bakefile up on that web site. Download that and put the directory + containing bakefile.exe in your Windows PATH. + + Bakefile generates the various project files and Makefiles from + a single source file, mysql++.bkl. This is usually the file you + need to change when you want to submit some change to the MySQL++ + build system. + + While Bakefile's documentation isn't as comprehensive as it + ought to be, you can at least count on it to list all of the + available features. So, if you can't see a way to make Bakefile + do something, it's likely it just can't do it. Bakefile is a + high-level abstraction of build systems in general, so it'll never + support all the particulars of every odd build system out there. + + Once you've made your changes, you can generate the Visual C++ + project files by running rebake.bat, which you can find in the + same directory as this README file. + + +If You Run Into Problems... +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Especially if you have linking problems, make sure your project + settings match the above. Visual C++ is very picky about things + like run time library settings. When in doubt, try running one + of the example programs. If it works, the problem is likely in + your project settings, not in MySQL++. + ADDED README-examples.txt Index: README-examples.txt ================================================================== --- /dev/null +++ README-examples.txt @@ -0,0 +1,185 @@ +Building the Examples +~~~~~~~~~~~~~~~~~~~~~ + If you're installing MySQL++ from the source tarball, the example + programs get built when you build the library. If you change + any example code, just say 'make' to rebuild the examples. + The examples are built against the headers and library in the + lib subdirectory, not against the ones you may have installed + elsewhere on the system. + + If these example files were installed on your system as part of + the -devel RPM, copy all the files to a directory you can write + to, then say 'make' in that directory. This uses a simplified + Makefile, which builds the examples against the headers and + libraries installed in the system directories. + + +Getting Started with the Examples +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + MySQL++ is built as a shared library on most systems, and a DLL + on Windows. Since it isn't built in the same directory as the + examples, this means that your system won't be able to find the + library without help until you install it. Since you generally + want to run the examples _before_ installing the library, to test + that the library actually works, we need a workaround. + + That workaround is the exrun script. There are two versions, + a Bourne shell script called just exrun for POSIX systems, and + exrun.bat for Windows. + + Before running the other examples, you must first create the + sample database. On POSIX systems, you do that like so: + + $ ./exrun resetdb [-s server_addr] [-u user] [-p password] + + On Windows, that would instead be: + + C:\mysql++\> exrun.bat resetdb [-s server] [-u user] [-p pass] + + You don't have to give any of these options. If you don't pass -s, + it assumes the database server is running on the same machine, + and so tries to contact the server over some form of local IPC. + If you don't pass -u, it uses your own user name when logging + into to the database server. If you don't pass -p, it assumes the + database user has an empty password, which hopefully is not true. + + The -s option accepts many different forms of address. The main + one is some sort of TCP/IP address, with an optional port number + or service name. On Unixy systems, you can give a Unix domain + socket name. On Windows, you can give just a period to use named + pipes, if the server supports it. All of these are legal: + + . + localhost + 172.20.0.252:12345 + /var/run/mysqld.sock + my.server.name.com:mysql + + If you give -s but don't give a port number or service name with + it, it assumes the default, port 3306. + + +Running the Other Command Line Examples +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + The following examples use the database set up by resetdb, and + have the same command line format as resetdb: + + simple1: Shows the item names for all records in the sample + stock table. Try this one if you do nothing else. + + simple2: Similar to simple1, but it displays all columns + from the sample stock table, not just the item name. + + simple3: Same as simple2, except that it retrieves the data + with a "use" query instead of a "store" query. See the + user manual for the difference between these methods. + + ssqls1-5: These demonstrate the SSQLS features. Read the + SSQLS sections in the user manual for details about + these examples. + + multiquery: MySQL++ allows you to issue multiple queries at + once, and get the results as separate sets. This shows + that, and also how to use stored procedures, which return + their results in the same way as a multiquery. + + tquery1-3: Shows how to use the template query facility. + + transaction: Shows how to use the Transaction class to create + transaction sets which automatically roll back if not + explicitly committed. + + deadlock: Shows how to handle errors that happen when the + database server detects a deadlock in a transaction set. + Also demonstrates the need for BadQuery::errnum() + + store_if: Demonstrates the Query::store_if() method, which + allows you to store the results of a query in an STL + container conditionally. Think of it as a way to express + rules for selecting records in C++, to be used when SQL's + WHERE clause isn't powerful enough. + + for_each: Demonstrates the Query::for_each() method, which + allows you to execute a query and call a functor on each + returned row. This example uses this to gather statistics + on the sample table's contents. + + cpoolp, cpoolw: Respectively, the POSIX and Windows threads + variants of the ConnectionPool class demonstration. + + load_jpeg: Inserts a JPEG file into the sample database, + for use by the cgi_jpeg example. (See below.) Unlike the + other examples, this one takes anything given on the + command line that isn't a switch to be a JPEG file name. + We've included examples/logo.jpg as a sample, if you want + to use that. + + fieldinf: Shows how to get information about the fields in + a result set. (Types, etc.) + + dbinfo: Dumps a bunch of information about the database + server and some of the data it's managing. + + If you run the load_jpeg example, you should consider also + playing with the other half of the demonstration, cgi_jpeg. + To run it, you'll need to install MySQL++ on a machine with + a web server, then copy the cgi_jpeg program to the server's + CGI directory. For example, on a stock Red Hat type box, + that would be /var/www/cgi-bin. At that point, a request like + http://my.server.com/cgi-bin/cgi_jpeg?id=1 should show the JPEG you + loaded. The ID value to use will be that reported by load_jpeg. + + +Dedicated Windows Examples +~~~~~~~~~~~~~~~~~~~~~~~~~~ + If you're a Visual C++ user, there are two examples specially + created for you: + + examples\vstudio\mfc.vcproj: A GUI replacement for the simple2 + example, it simply logs in and displays the stock table's + contents. Uses good old C++ and MFC. + + examples\vstudio\wforms.vcproj: The same thing, only written in + C++/CLI and using Windows Forms. We needed a second + example for two reasons. First, string handling is quite + different under .NET than in unmanaged C++. Second, many + developers are now using Visual Studio Express, which + doesn't include MFC. Please read README-Visual-C++.txt + before trying to run this example. The MySQL++ build + settings must be modified before it will run correctly. + + Before trying to run these examples, run the updexdll.bat file + in the top MySQL++ directory. This copies the built mysqlpp.dll + files into the Windows examples' EXE output directories so you + can run them before you're ready to formally install the DLL on + your system. + + Open examples\vstudio\mysqlpp_gui_examples.sln to begin working + with these examples. They only work correctly in Visual Studio + 2005 right now. If you want to backport them to VS 2003, it's + probably not hard, and we will accept patches for this. The main + difficulty is that VS 2003 supports Managed C++, which isn't the + same thing as C++/CLI. + + The main justification for these examples is that Unicode is + handled differently in Windows GUI programs than on the POSIX + systems where MySQL++ was born and raised. In earlier versions + of MySQL++, the command line examples had very limited Unicode + support on Windows, but it was unrealistic and confusing. Now the + command line examples don't even try to handle Unicode on Windows, + leaving that up to these new GUI examples. + + +Special exrun Capabilities +~~~~~~~~~~~~~~~~~~~~~~~~~~ + The Bourne shell version of the exrun script has a few features + not avaiable in the Windows batch file version. These features + let you run the examples under various debugging tools. + + You can get simple gdb debugging if you run an example like this: + + $ ./exrun gdb simple1 foo bar qux + + The script also supports valgrind, in memory leak testing mode: + + $ ./exrun valgrind simple1 foo bar qux ADDED README.txt Index: README.txt ================================================================== --- /dev/null +++ README.txt @@ -0,0 +1,125 @@ +What It Is +~~~~~~~~~~ + MySQL++ is a C++ wrapper for MySQL's C API. It is built around STL + principles, to make dealing with the database as easy as dealing + with an STL container. MySQL++ relieves the programmer of dealing + with cumbersome C data structures, generation of repetitive SQL + statements, and manual creation of C++ data structures to mirror + the database schema. + + Its home page is http://tangentsoft.net/mysql++/ + + +Prerequisites +~~~~~~~~~~~~~ + To build MySQL++, you must have the MySQL C API development + files installed. + + On Unixy systems (Linux, Mac OS X, Cygwin, "real" Unix...), + the MySQL development files are installed if you build MySQL + from source. If you installed MySQL as a binary package, then + the development files are often packaged separately from the + MySQL server itself. It's common for the package containing the + development files to be called something like "MySQL-devel". + + If you're building on Windows with Visual C++ or MinGW, you + need to install the native Win32 port of MySQL from mysql.com. + The development files are only included with the "complete" + version of the MySQL installer, and some versions of this + installer won't actually install them unless you do a custom + install. Another pitfall is that MySQL++'s project files assume + that you've installed the current General Availability release of + MySQL (v5.0 right now) and it's installed in the default location. + If you've installed a different version, or if MySQL Inc. changes + the default location (which they seem to do regularly!) you'll have + to adjust the link and include file paths in the project settings. + + +Additional Things to Read +~~~~~~~~~~~~~~~~~~~~~~~~~ + Each major platform we support has a dedicated README-*.txt + file for it containing information specific to that platform. + Please read it. + + For authorship information, see the CREDITS.txt file. + + For license information, see the COPYING.txt file. + + If you want to change MySQL++, see the HACKERS.txt file. + + You should have received a user manual and a reference manual + with MySQL++. If not, you can read a recent version online: + + http://tangentsoft.net/mysql++/doc/ + + Search the MySQL++ mailing list archives if you have more + questions: + + http://lists.mysql.com/plusplus/ + + +Building the Library +~~~~~~~~~~~~~~~~~~~~ + MySQL++ uses Bakefile (http://bakefile.org/) to generate + platform-specific project files and makefiles from a single set + of input files. We currently support these platforms: + + autoconf: + For Unixy platforms, including Linux, Mac OS X, and Cygwin. See + README-Unix.txt for details. Supplementary details for Cygwin + are in README-Cygwin.txt, and for OS X in README-Mac-OS-X.txt. + + MinGW: + We ship Makefile.mingw for MinGW. It currently only builds the + static version of the library for technical reasons. This has + licensing ramifications. See README-MinGW.txt for details. + + Visual C++: + We ship Visual C++ 2003 project files. This is the oldest + version MySQL++ will run on, due to compiler limitations. + See README-Visual-C++.txt for more details. + + Xcode: + We ship an Xcode v2 project file. It hasn't been tested + much yet, since the autoconf method works just fine on OS X. + As a result, we need both success and failure reports on the + mailing list. See README-Mac-OS-X.txt for more information. + + +Example Programs +~~~~~~~~~~~~~~~~ + You may want to try out the programs in the examples subdirectory + to ensure that the MySQL++ API and your MySQL database are both + working properly. Also, these examples give many examples of + the proper use of MySQL++. See README-examples.txt for further + details. + + +Unsupported Compliers +~~~~~~~~~~~~~~~~~~~~~ + If you're on Windows but want to use some other compiler besides + Visual C++ or GCC, you are currently on your own. There have + been past efforts to port MySQL++ to other Windows compilers, + but for one reason or another, all of these ports have died. + + On Unixy systems, GCC still works best. "Native" compilers and + third-party compilers may work, but you're on your own to get + it working. + + We have nothing in particular against these unsupported systems. + We just lack the time and resources to support everything + ourselves. If you are sufficiently motivated to get MySQL++ + working on one of these alternate systems, see the HACKERS.txt + file first for guidance. If you follow the advice in that file, + your patch will be more likely to be accepted. + + +If You Want to Hack on MySQL++... +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + If you intend to change the library or example code, please read + the HACKERS.txt file. + + If you want to change the user manual, read doc/userman/README.txt + + If you want to change the reference manual, see the Doxygen manual: + http://www.stack.nl/~dimitri/doxygen/manual.html ADDED Wishlist Index: Wishlist ================================================================== --- /dev/null +++ Wishlist @@ -0,0 +1,147 @@ +Patches for any of these thoughtfully considered! See the HACKERS.txt +file for instructions on sending patches. + + +Any Version +----------- + o Any time you must hand-roll some SQL code in your program, + consider whether it could be generalized to a widely-useful + API feature. + + +v3.1 Tentative Plan +------------------- + o SSQLS v2: + + - Switch from C macros to a DSL that is translated to .cpp and + .h files by a tool built along with MySQL++ library. Design: + + http://lists.mysql.com/plusplus/6929 + + - Switch per SSQLS that makes it throw an exception when it sees + a mismatch between DB schema and SSQLS definition. Harkens + back to pre v3.0 SSQLS behavior, where you'd get a crash as + it tried to fill out fields by position, and fail. For the + B&D folk who don't like the new "just cope" behavior. + + - Try to design it so as much code as possible resides in + a common base class (SsqlsBase) that all SSQLSes derive from. + Can't do it in v1 because virtually everything is specific + to the structure's type. Study equal_list(), for example. + Do it with an eye toward replacing Query's template methods + taking SSQLSes with concrete methods taking SsqlsBase&. + + - Add truthiness operator to SSQLS to detect an incompletely- + populated object? Or maybe an incomplete() method? + + - Add features to ssqlsxlat to write SSQLSv2 declaration files + from existing schemas extracted from CREATE TABLE statements, + from running databases, and from C++ files containing old + SSQLS v1 declarations. + + - Add table creation ability to SSQLS. It has the schema... + + - Support per-instance table name overrides, instead of just + per SSQLS? Needed if you're going to use a single SSQLS for + many tables with the same structure in a multithreaded program, + so changing it statically isn't safe. + + - Need a way to tag a column as auto-increment so it's left out + of INSERT queries, but still available for data retrieval. + + o Chris Frey's packarray class + + o Create adaptors for std::bitset, for storing binary data in a + MySQL table. Make two options available, one for storing the + return from bitset::to_ulong() in an UNSIGNED INTEGER column, + and another for storing a larger set of bits in a more flexible + way, perhaps as a BLOB. + + o field_list should use backticks to quote its items to handle + spaces and other special characters. Probably also remove all + the manipulator stuff associated with these: no reason to make + it user-settable, as there's only one right way to do it. See: + + http://dev.mysql.com/doc/refman/5.0/en/identifiers.html + + o Add a general-purpose backtick manipulator as well. + + o Define operator<< for Fields, Row, StoreQueryResult, etc. In other + words, there should be a way to get a user-readable version of + received data without a lot of code. CSV format by default, and + mysql(1)-like ASCII grid optionally, perhaps with a manipulator? + There is grid code in examples/multiquery.cpp which we can use + and then make multiquery.cpp a demonstration platform for it. + Maybe dbinfo and fieldinf, too? + + o Has experience with new thread awareness changed our mind on + atomic inc/dec of reference counts in RefCounted*? + + o Create a fixed-point data type for use with SQL's DECIMAL and + related types. Right now, sql_decimal is a typedef for double, + so you lose accuracy in the fractional part. + + o Optional checked conversions in String for numerics: throw + BadConversion on range overflow? + + +v4.0 or Later +------------- + o Database independence: + + - Make DBDriver class purely abstract; move its entire functional + contents to new MysqlDriver. + + - Must create at least two other DBDriver subclasses to + ensure base class is reusable before releasing v4.0. + PostgresDriver and SqlLiteDriver? + + - Templatize all classes that use DBDriver interface with the + DB driver type. This lets you specify the driver type to use + with a Connection and all its children without modifying the + existing method parameter lists. This also lets us worry less + about C API types, as they can be hidden away behind typedefs: + + class MysqlDriver : public DBDriver { ... + typedef MYSQL_ROW row_type; + ... + } + + template + class Connection ... { ... + Query query(); + ... + } + + template + class UseQueryResult { ... + DBD::row_type fetch_raw_row(); + } + + - Tricky bits: + + - Initializing result set objects. + + - type_info module. Extremely closely tied to MySQL C API + right now. Will probably have to turn it into a parallel + class hierarchy to DBDriver, or fold it in with same. + + - Building MySQL++ on systems without autoconf. How to + specify what DB engines are available? Probably default to + supporting MySQL only, and let people turn things on manually + as they need them. Or, maybe make them use Bakefile so they + can fiddle with the options if they want something atypical. + + o Some sort of support for prepared statements. Can we hijack + the template query mechanism? + + o If SSQLSv2 does use a common base class, change Query template + methods taking SSQLS into concrete methods taking SsqlsBase&. + + o Make Query::insert(), replace() and update() execute their + queries immediately. Requires an ABI break, because they'll + have to return SimpleResult. + + o Switch Query's safe bool to overload basic_ios<>::operator + void*() instead. We create an ambiguous conversion in bool + context with some C++ standard libraries otherwise. ADDED bk-deps Index: bk-deps ================================================================== --- /dev/null +++ bk-deps @@ -0,0 +1,105 @@ +#!/bin/sh + +# This script is part of Bakefile (http://www.bakefile.org) autoconf +# script. It is used to track C/C++ files dependencies in portable way. +# +# Permission is given to use this file in any way. + +DEPSMODE=gcc +DEPSDIR=.deps +DEPSFLAG="-MMD" + +mkdir -p $DEPSDIR + +if test $DEPSMODE = gcc ; then + $* ${DEPSFLAG} + status=$? + + # determine location of created files: + while test $# -gt 0; do + case "$1" in + -o ) + shift + objfile=$1 + ;; + -* ) + ;; + * ) + srcfile=$1 + ;; + esac + shift + done + depfile=`basename $srcfile | sed -e 's/\..*$/.d/g'` + depobjname=`echo $depfile |sed -e 's/\.d/.o/g'` + + # if the compiler failed, we're done: + if test ${status} != 0 ; then + rm -f $depfile + exit ${status} + fi + + # move created file to the location we want it in: + if test -f $depfile ; then + sed -e "s,$depobjname:,$objfile:,g" $depfile >${DEPSDIR}/${objfile}.d + rm -f $depfile + else + # "g++ -MMD -o fooobj.o foosrc.cpp" produces fooobj.d + depfile=`basename $objfile | sed -e 's/\..*$/.d/g'` + if test ! -f $depfile ; then + # "cxx -MD -o fooobj.o foosrc.cpp" creates fooobj.o.d (Compaq C++) + depfile="$objfile.d" + fi + if test -f $depfile ; then + sed -e "/^$objfile/!s,$depobjname:,$objfile:,g" $depfile >${DEPSDIR}/${objfile}.d + rm -f $depfile + fi + fi + exit 0 +elif test $DEPSMODE = mwcc ; then + $* || exit $? + # Run mwcc again with -MM and redirect into the dep file we want + # NOTE: We can't use shift here because we need $* to be valid + prevarg= + for arg in $* ; do + if test "$prevarg" = "-o"; then + objfile=$arg + else + case "$arg" in + -* ) + ;; + * ) + srcfile=$arg + ;; + esac + fi + prevarg="$arg" + done + $* $DEPSFLAG >${DEPSDIR}/${objfile}.d + exit 0 +elif test $DEPSMODE = unixcc; then + $* || exit $? + # Run compiler again with deps flag and redirect into the dep file. + # It doesn't work if the '-o FILE' option is used, but without it the + # dependency file will contain the wrong name for the object. So it is + # removed from the command line, and the dep file is fixed with sed. + cmd="" + while test $# -gt 0; do + case "$1" in + -o ) + shift + objfile=$1 + ;; + * ) + eval arg$#=\$1 + cmd="$cmd \$arg$#" + ;; + esac + shift + done + eval "$cmd $DEPSFLAG" | sed "s|.*:|$objfile:|" >${DEPSDIR}/${objfile}.d + exit 0 +else + $* + exit $? +fi ADDED bmark.txt Index: bmark.txt ================================================================== --- /dev/null +++ bmark.txt @@ -0,0 +1,183 @@ +All unit tests passed +---------------- BEGIN resetdb OUTPUT ---------------- +Connecting to database server... +Dropping existing sample data tables... +Creating stock table... +Populating stock table...inserted 4 rows. +Creating empty images table... +Creating deadlock testing tables... +Reinitialized sample database successfully. +================ END resetdb OUTPUT ================ + +---------------- BEGIN simple1 OUTPUT ---------------- +We have: + Nürnberger Brats + Pickle Relish + Hot Mustard + Hotdog Buns +================ END simple1 OUTPUT ================ + +---------------- BEGIN simple2 OUTPUT ---------------- +Item Num Weight Price Date + +Nürnberger Brats 97 1.5 8.79 2005-03-10 +Pickle Relish 87 1.5 1.75 1998-09-04 +Hot Mustard 73 0.95 0.97 1998-05-25 +Hotdog Buns 65 1.1 1.10 1998-04-23 +================ END simple2 OUTPUT ================ + +---------------- BEGIN simple3 OUTPUT ---------------- +Item Num Weight Price Date + +Nürnberger Brats 97 1.5 8.79 2005-03-10 +Pickle Relish 87 1.5 1.75 1998-09-04 +Hot Mustard 73 0.95 0.97 1998-05-25 +Hotdog Buns 65 1.1 1.10 1998-04-23 +================ END simple3 OUTPUT ================ + +---------------- BEGIN store_if OUTPUT ---------------- +Records found: 2 + +Item Num Weight Price Date + +Nürnberger Brats 97 1.5 8.79 2005-03-10 +Hot Mustard 73 0.95 0.97 1998-05-25 +================ END store_if OUTPUT ================ + +---------------- BEGIN for_each OUTPUT ---------------- +There are 322 items weighing 416.85 stone and costing 1147.19 cowrie shells. +================ END for_each OUTPUT ================ + +---------------- BEGIN multiquery OUTPUT ---------------- +Multi-query: +DROP TABLE IF EXISTS test_table; CREATE TABLE test_table(id INT); INSERT INTO test_table VALUES(10); UPDATE test_table SET id=20 WHERE id=10; SELECT * FROM test_table; DROP TABLE test_table +Result set 0 is empty. +Result set 1 is empty. +Result set 2 is empty. +Result set 3 is empty. +Result set 4 has 1 row: + +----+ + | id | + +----+ + | 20 | + +----+ +Result set 5 is empty. +Stored procedure query: +DROP PROCEDURE IF EXISTS get_stock; CREATE PROCEDURE get_stock( i_item varchar(20) ) BEGIN SET i_item = concat('%', i_item, '%'); SELECT * FROM stock WHERE lower(item) like lower(i_item); END; +Result set 0 is empty. +Result set 1 is empty. +Query: CALL get_stock('relish') +Result set 0 has 1 row: + +---------------+-----+--------+-------+------------+-------------+ + | item | num | weight | price | sdate | description | + +---------------+-----+--------+-------+------------+-------------+ + | Pickle Relish | 87 | 1.5 | 1.75 | 1998-09-04 | NULL | + +---------------+-----+--------+-------+------------+-------------+ +Result set 1 is empty. +================ END multiquery OUTPUT ================ + +---------------- BEGIN tquery1 OUTPUT ---------------- +Query: select * from stock +Records found: 4 + +Item Num Weight Price Date + +Nuerenberger Bratwurst 97 1.5 8.79 2005-03-10 +Pickle Relish 87 1.5 1.75 1998-09-04 +Hot Mustard 73 0.95 0.97 1998-05-25 +Hotdog Buns 65 1.1 1.1 1998-04-23 +================ END tquery1 OUTPUT ================ + +---------------- BEGIN resetdb OUTPUT ---------------- +Connecting to database server... +Dropping existing sample data tables... +Creating stock table... +Populating stock table...inserted 4 rows. +Creating empty images table... +Creating deadlock testing tables... +Reinitialized sample database successfully. +================ END resetdb OUTPUT ================ + +---------------- BEGIN tquery2 OUTPUT ---------------- +Query: select * from stock +Records found: 4 + +Item Num Weight Price Date + +Nuerenberger Bratwurst 97 1.5 8.79 2005-03-10 +Pickle Relish 87 1.5 1.75 1998-09-04 +Hot Mustard 73 0.95 0.97 1998-05-25 +Hotdog Buns 65 1.1 1.1 1998-04-23 +================ END tquery2 OUTPUT ================ + +---------------- BEGIN tquery3 OUTPUT ---------------- +Stuff we have a lot of in stock: + Nuerenberger Bratwurst + Pickle Relish +================ END tquery3 OUTPUT ================ + +---------------- BEGIN resetdb OUTPUT ---------------- +Connecting to database server... +Dropping existing sample data tables... +Creating stock table... +Populating stock table...inserted 4 rows. +Creating empty images table... +Creating deadlock testing tables... +Reinitialized sample database successfully. +================ END resetdb OUTPUT ================ + +---------------- BEGIN ssqls1 OUTPUT ---------------- +We have: + Nürnberger Brats + Pickle Relish + Hot Mustard (good American yellow mustard, not that European stuff) + Hotdog Buns +================ END ssqls1 OUTPUT ================ + +---------------- BEGIN ssqls2 OUTPUT ---------------- +Query: INSERT INTO stock (item,num,weight,price,sdate,description) VALUES ('Hot Dogs',100,1.5,1.75,'1998-09-25',NULL) +Query: select * from stock +Records found: 5 + +Item Num Weight Price Date + +Nürnberger Brats 97 1.5 8.79 2005-03-10 +Pickle Relish 87 1.5 1.75 1998-09-04 +Hot Mustard 73 0.95 0.97 1998-05-25 +Hotdog Buns 65 1.1 1.1 1998-04-23 +Hot Dogs 100 1.5 1.75 1998-09-25 +================ END ssqls2 OUTPUT ================ + +---------------- BEGIN ssqls3 OUTPUT ---------------- +Query: UPDATE stock SET item = 'Nuerenberger Bratwurst',num = 97,weight = 1.5,price = 8.7899999999999991,sdate = '2005-03-10',description = NULL WHERE item = 'Nürnberger Brats' +Query: select * from stock +Records found: 5 + +Item Num Weight Price Date + +Nuerenberger Bratwurst 97 1.5 8.79 2005-03-10 +Pickle Relish 87 1.5 1.75 1998-09-04 +Hot Mustard 73 0.95 0.97 1998-05-25 +Hotdog Buns 65 1.1 1.1 1998-04-23 +Hot Dogs 100 1.5 1.75 1998-09-25 +================ END ssqls3 OUTPUT ================ + +---------------- BEGIN ssqls4 OUTPUT ---------------- +Records found: 5 + +Item Num Weight Price Date + +Hot Dogs 100 1.5 1.75 1998-09-25 +Hot Mustard 73 0.95 0.97 1998-05-25 +Hotdog Buns 65 1.1 1.1 1998-04-23 +Nuerenberger Bratwurst 97 1.5 8.79 2005-03-10 +Pickle Relish 87 1.5 1.75 1998-09-04 + +Currently 65 hotdog buns in stock. +================ END ssqls4 OUTPUT ================ + +---------------- BEGIN ssqls5 OUTPUT ---------------- +Custom query: +select * from stock where weight = 1.5 and price = 8.7899999999999991 +================ END ssqls5 OUTPUT ================ + ADDED bootstrap Index: bootstrap ================================================================== --- /dev/null +++ bootstrap @@ -0,0 +1,105 @@ +#!/bin/sh + +ARGS=1 +BF_OPTIONS= +MAINT_FLAGS="--cache-file=config.cache --enable-maintainer-mode" +while [ $ARGS != 0 ] +do + case "$1" in + bat) + cmd /c bootstrap.bat $BF_OPTIONS + exit 0 + ;; + + nodoc) + BF_OPTIONS="-DBUILDDOCS=no $BF_OPTIONS" + shift + ;; + + noex) + BF_OPTIONS="-DBUILDEXAMPLES=no $BF_OPTIONS" + shift + ;; + + nolib) + BF_OPTIONS="-DBUILDLIBRARY=no $BF_OPTIONS" + shift + ;; + + nomaint) + MAINT_FLAGS= + shift + ;; + + noopt) + export CXXFLAGS="-g -O0" + shift + ;; + + pedantic) + export CXXFLAGS="-g -O2 -ansi -pedantic -Wall -W -Wold-style-cast -Wfloat-equal -Wwrite-strings -Wno-overloaded-virtual -Wno-long-long -Wno-variadic-macros -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC" + shift + ;; + + *) + ARGS=0 + ;; + esac +done + +rm -f config.cache + +# Do Bakefile stuff first +set -x && + mkdir -p vc2003 vc2005 && + bakefilize && + bakefile_gen $BF_OPTIONS && + bakefile -f gnu -o Makefile.simple -DBUILDLIBRARY=no mysql++.bkl && + set +x && + success=shonuff + +# Get rid of INSTALL symlink added by bakefilize. We already have +# INSTALL.txt. +rm -f INSTALL + +# If that succeeded, move on to autotools stuff, etc. +set +x +if [ -n "$success" ] +then + mv autoconf_inc.m4 config > /dev/null 2>&1 # don't care if it fails + + # Find location of Bakefile's stock M4 autoconf macros + for d in /usr /usr/local + do + BAKEFILE_M4=$d/share/aclocal + if [ -e $BAKEFILE_M4/bakefile.m4 ] ; then break ; fi + done + if [ ! -e $BAKEFILE_M4/bakefile.m4 ] + then + echo + echo "Failed to find bakefile.m4. Add the directory containing" + echo "this to the bootstrap script." + echo + exit 1 + fi + + success= + set -x && + aclocal -I config -I $BAKEFILE_M4 && + autoheader && + autoconf && + ./configure $MAINT_FLAGS $* && + make lib/querydef.h lib/ssqls.h && + set +x && + success=awyeah +fi + +# Detect failure in any part of above +if [ -z "$success" ] +then + echo + echo BOOTSTRAP FAILED! + echo + exit 1 +fi + ADDED bootstrap.bat Index: bootstrap.bat ================================================================== --- /dev/null +++ bootstrap.bat @@ -0,0 +1,60 @@ +@echo off +if not exist vc2003 mkdir vc2003 +if not exist vc2005 mkdir vc2005 + +bakefile_gen %* +if errorlevel 1 exit +if not exist mysql++.sln goto no_bakefile + +cd lib +perl querydef.pl +if errorlevel 1 exit +if not exist querydef.h goto no_perl +perl ssqls.pl +if errorlevel 1 exit +if not exist ssqls.h goto no_perl + +if not exist mysql++.h goto no_mysqlpp_h +cd .. + +exit + +:no_bakefile +echo. +echo Bakefile doesn't seem to be installed on this system. Download it +echo from http://bakefile.org/ You need version 0.2.3 or newer. +echo. +exit + +:no_perl +echo. +echo You need a Perl interpreter installed on your system, somewhere in +echo the PATH. Any recent version or flavor should work; we don't use +echo any special extensions. The easiest to install on Windows would be +echo ActivePerl, from http://activestate.com/Products/activeperl/ +echo If you're familiar with Unix, you might like Cygwin better instead: +echo http://cygwin.com/setup.exe +echo. +cd .. +exit + +:no_mysqlpp_h +echo. +echo WARNING: Can't make lib/mysql++.h +echo. +echo On Unixy systems, autoconf creates lib/mysql++.h from lib/mysql++.h.in +echo but there is no easy way to do this on Windows. You can do it manually: +echo just copy the file to the new name, and edit the MYSQLPP_HEADER_VERSION +echo definition to put the proper version number parts into the macro. It +echo needs to look something like this: +echo. +echo #define MYSQLPP_HEADER_VERSION MYSQLPP_VERSION(3, 0, 0) +echo. +echo It's important that the three numbers match the actual library version +echo number, or else programs that check this (like resetdb) will fail. +echo. +echo Alternately, if you've also got MySQL++ installed on some Unixy type +echo system, you can let its bootstrap procedure create mysql++.h and then +echo copy it to the Windows machine. +echo. +cd .. ADDED cleanmf Index: cleanmf ================================================================== --- /dev/null +++ cleanmf @@ -0,0 +1,3 @@ +#!/bin/sh +rm -f Makefile* +rm -rf *.xcodeproj vc200? DELETED config.cygwin Index: config.cygwin ================================================================== --- config.cygwin +++ /dev/null @@ -1,104 +0,0 @@ -####### Compiler, tools and options - -CC = g++ -CFLAGS = -DWINDOZE -D_WIN32 -O0 -mno-cygwin -D__cplusplus -Wall --fstrength-reduce -D__WIN32__ -I/cygnus/cygwin-b20/include/g++ -I/cygnus/cygwin-b20/include/g++ -I/my/mysql_src/mysql-3.22.13-beta/include -L/my/mysql_src/mysql-3.22.13-beta/client/.libs -L../sqlplusint -mno-cygwin -#CFLAGS += -fkeep-inline-functions -# If you have problems when with undefined refrences try uncommenting -# the above line when compiling the library. But then recommenting -# it when you compile the examples. -FPIC =# -fPIC -INCPATH = -I/cygnus/cygwin-b20/include/g++ -I/my/mysql_src/mysql-3.22.13-beta/include # make sure you can find mysql.h -LINK = g++ -LFLAGS = -mno-cygwin # make sure you can find mysqlclinet -NLFLAGS = -lmysql++ # this is for the static lib test -SLFLAGS = -lmysql++ # this is for shared lib test -LIBS = -lmysqlclient -mno-cygwin -SOLLIBS = -lnsl -lsocket # extra lib that Solaris needs -ARC = ar rc -CP_R = cp -a -RMDIR = echo -#RMDIR = rmdir -#uncomment the above line if your sure your rmdir does NOT delete non-empty -#directories. If it does make remove could be DISASTORIUS. -INSTLIB = /usr/lib -INSTHEAD = /usr/include -INSTBIN = /usr/bin -PERLPATH = /usr/bin/perl - -#CFLAGS += -D NO_LONG_LONGS - -#TYPE = objs -TYPE = static -#TYPE = shared - -TARGET = linux -#TARGET = solaris -## - -# You should not need to modify anything below this line. If you do -# need to modify something below this line please email me at -# sinisa@cytanet.com.cy with what you did. - -ifeq ($(TARGET), solaris) - LIBS += $(SOLLIBS) -endif - -OBJSINT = coldata.o connection.o datetime.o field_names.o field_types.o \ - manip.o query.o result.o row.o set.o sql_query.o type_info.o vallist.o - -HEADERS = mysql++ mysql++.h mysql++-custom mysql++-custom.h - -HEADSINT = mysql++ defs \ - define_short coldata1.hh \ - type_info1.hh const_string1.hh \ - null1.hh compare1.hh row1.hh \ - resiter1.hh vallist1.hh manip1.hh \ - sql_string1.hh sql_query1.hh \ - sql_query0.hh datetime1.hh \ - stream2string1.hh tiny_int1.hh \ - set1.hh connection1.hh query1.hh \ - result1.hh field_names1.hh \ - tracker.h field_types1.hh \ - fields1.hh connection0.hh \ - convert1.hh coldata2.hh \ - compare2.hh connection2.hh \ - query2.hh const_string2.hh \ - convert2.hh datetime2.hh \ - stream2string2.hh field_names2.hh \ - field_types2.hh fields2.hh \ - manip2.hh null2.hh result2.hh \ - row2.hh set2.hh stream2string3.hh \ - sql_query2.hh sql_string2.hh \ - tiny_int2.hh type_info2.hh \ - vallist2.hh coldata3.hh \ - convert3.hh null3.hh compare3.hh \ - connection3.hh const_string3.hh \ - datetime3.hh field_names3.hh \ - field_types3.hh manip3.hh \ - query3.hh result3.hh row3.hh \ - set3.hh sql_query3.hh \ - sql_string3.hh tiny_int3.hh \ - type_info3.hh vallist3.hh \ - custom.hh custom-macros.hh - -####### Implicit rules - -.SUFFIXES: - -%.o: %.cc - $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $< - -%.o: %.c - $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $< - -%: %.o -ifeq ($(TYPE), objs) - $(CC) $(CFLAGS) $(LIBS) -o $@ ../sqlplusint/*.o $^ -endif -ifeq ($(TYPE), static) - $(CC) $(CFLAGS) $(NLFLAGS) $(LIBS) -o $@ $^ -endif -ifeq ($(TYPE), shared) - $(CC) $(CFLAGS) $(SLFLAGS) $(LIBS) -o $@ $^ -endif Index: config.h.in ================================================================== --- config.h.in +++ config.h.in @@ -1,32 +1,80 @@ -/* config.h.in. Generated automatically from configure.in by autoheader. */ - -/* Define to empty if the keyword does not work. */ -#undef const - -/* Define if you have the ANSI C header files. */ -#undef STDC_HEADERS - -/* Define if you have the strtol function. */ -#undef HAVE_STRTOL - -/* Define if you have the intl library (-lintl). */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define if you have __gnu_cxx:slist container in */ +#undef HAVE_EXT_SLIST + +/* Define if you have ::slist container in */ +#undef HAVE_GLOBAL_SLIST + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `intl' library (-lintl). */ #undef HAVE_LIBINTL -/* Define if you have the mysqlclient library (-lmysqlclient). */ -#undef HAVE_LIBMYSQLCLIENT - -/* Define if you have the nsl library (-lnsl). */ -#undef HAVE_LIBNSL - -/* Define if you have the socket library (-lsocket). */ -#undef HAVE_LIBSOCKET - -/* Name of package */ -#undef PACKAGE - -/* Version number of package */ -#undef VERSION - -/* Define if using the dmalloc debugging malloc package */ -#undef WITH_DMALLOC - +/* Define to 1 if you have the `z' library (-lz). */ +#undef HAVE_LIBZ + +/* Define if you have the localtime_r() facility */ +#undef HAVE_LOCALTIME_R + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define if your MySQL library has SSL functions */ +#undef HAVE_MYSQL_SSL_SET + +/* Define if you have POSIX threads libraries and header files. */ +#undef HAVE_PTHREAD + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define if you have std::slist container in */ +#undef HAVE_STD_SLIST + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYNCH_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ZLIB_H + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to necessary symbol if this constant uses a non-standard name on + your system. */ +#undef PTHREAD_CREATE_JOINABLE + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS ADDED config/acx_pthread.m4 Index: config/acx_pthread.m4 ================================================================== --- /dev/null +++ config/acx_pthread.m4 @@ -0,0 +1,233 @@ +dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) +dnl +dnl This macro figures out how to build C programs using POSIX +dnl threads. It sets the PTHREAD_LIBS output variable to the threads +dnl library and linker flags, and the PTHREAD_CFLAGS output variable +dnl to any special C compiler flags that are needed. (The user can also +dnl force certain compiler flags/libs to be tested by setting these +dnl environment 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 $LIBS +dnl +dnl If you are only building threads programs, you may wish to +dnl use 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 +dnl to 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 +dnl to run it if it is not found. If ACTION-IF-FOUND is not specified, +dnl the default action will define HAVE_PTHREAD. +dnl +dnl Please let the authors know if this macro fails on any platform, +dnl or if you have any other suggestions or comments. This macro was +dnl based on work by SGJ on autoconf scripts for FFTW (www.fftw.org) +dnl (with help from M. Frigo), as well as ac_pthread and hb_pthread +dnl macros posted by Alejandro Forero Cuervo to the autoconf macro +dnl repository. We are also grateful for the helpful feedback of +dnl numerous users. +dnl +dnl @version $Id: acx_pthread.m4 1129 2005-10-04 17:53:10Z wyoung $ +dnl @author Steven G. Johnson + +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 none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt 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) +# 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 -pthread or + # -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="-pthread -pthreads pthread -mt $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;], + [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}) +else + PTHREAD_CC="$CC" +fi + +AC_SUBST(PTHREAD_LIBS) +AC_SUBST(PTHREAD_CFLAGS) +AC_SUBST(PTHREAD_CC) + +# 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 ADDED config/autoconf_inc.m4 Index: config/autoconf_inc.m4 ================================================================== --- /dev/null +++ config/autoconf_inc.m4 @@ -0,0 +1,110 @@ +dnl ### begin block 00_header[./mysql++.bkl] ### +dnl +dnl This macro was generated by +dnl Bakefile 0.2.3 (http://www.bakefile.org) +dnl Do not modify, all changes will be overwritten! + +BAKEFILE_AUTOCONF_INC_M4_VERSION="0.2.3" + +dnl ### begin block 20_COND_BUILD_DEBUG[./mysql++.bkl] ### + COND_BUILD_DEBUG="#" + if test "x$BUILD" = "xdebug" ; then + COND_BUILD_DEBUG="" + fi + AC_SUBST(COND_BUILD_DEBUG) +dnl ### begin block 20_COND_BUILD_RELEASE[./mysql++.bkl] ### + COND_BUILD_RELEASE="#" + if test "x$BUILD" = "xrelease" ; then + COND_BUILD_RELEASE="" + fi + AC_SUBST(COND_BUILD_RELEASE) +dnl ### begin block 20_COND_DEPS_TRACKING_0[./mysql++.bkl] ### + COND_DEPS_TRACKING_0="#" + if test "x$DEPS_TRACKING" = "x0" ; then + COND_DEPS_TRACKING_0="" + fi + AC_SUBST(COND_DEPS_TRACKING_0) +dnl ### begin block 20_COND_DEPS_TRACKING_1[./mysql++.bkl] ### + COND_DEPS_TRACKING_1="#" + if test "x$DEPS_TRACKING" = "x1" ; then + COND_DEPS_TRACKING_1="" + fi + AC_SUBST(COND_DEPS_TRACKING_1) +dnl ### begin block 20_COND_PLATFORM_MACOSX_0_USE_SOVERCYGWIN_0_USE_SOVERSION_1[./mysql++.bkl] ### + COND_PLATFORM_MACOSX_0_USE_SOVERCYGWIN_0_USE_SOVERSION_1="#" + if test "x$PLATFORM_MACOSX" = "x0" -a "x$USE_SOVERCYGWIN" = "x0" -a "x$USE_SOVERSION" = "x1" ; then + COND_PLATFORM_MACOSX_0_USE_SOVERCYGWIN_0_USE_SOVERSION_1="" + fi + AC_SUBST(COND_PLATFORM_MACOSX_0_USE_SOVERCYGWIN_0_USE_SOVERSION_1) +dnl ### begin block 20_COND_PLATFORM_MACOSX_0_USE_SOVERSION_1[./mysql++.bkl] ### + COND_PLATFORM_MACOSX_0_USE_SOVERSION_1="#" + if test "x$PLATFORM_MACOSX" = "x0" -a "x$USE_SOVERSION" = "x1" ; then + COND_PLATFORM_MACOSX_0_USE_SOVERSION_1="" + fi + AC_SUBST(COND_PLATFORM_MACOSX_0_USE_SOVERSION_1) +dnl ### begin block 20_COND_PLATFORM_MACOSX_1[./mysql++.bkl] ### + COND_PLATFORM_MACOSX_1="#" + if test "x$PLATFORM_MACOSX" = "x1" ; then + COND_PLATFORM_MACOSX_1="" + fi + AC_SUBST(COND_PLATFORM_MACOSX_1) +dnl ### begin block 20_COND_PLATFORM_MACOSX_1_USE_SOVERSION_1[./mysql++.bkl] ### + COND_PLATFORM_MACOSX_1_USE_SOVERSION_1="#" + if test "x$PLATFORM_MACOSX" = "x1" -a "x$USE_SOVERSION" = "x1" ; then + COND_PLATFORM_MACOSX_1_USE_SOVERSION_1="" + fi + AC_SUBST(COND_PLATFORM_MACOSX_1_USE_SOVERSION_1) +dnl ### begin block 20_COND_PLATFORM_MAC_0[./mysql++.bkl] ### + COND_PLATFORM_MAC_0="#" + if test "x$PLATFORM_MAC" = "x0" ; then + COND_PLATFORM_MAC_0="" + fi + AC_SUBST(COND_PLATFORM_MAC_0) +dnl ### begin block 20_COND_PLATFORM_MAC_1[./mysql++.bkl] ### + COND_PLATFORM_MAC_1="#" + if test "x$PLATFORM_MAC" = "x1" ; then + COND_PLATFORM_MAC_1="" + fi + AC_SUBST(COND_PLATFORM_MAC_1) +dnl ### begin block 20_COND_PLATFORM_OS2_1[./mysql++.bkl] ### + COND_PLATFORM_OS2_1="#" + if test "x$PLATFORM_OS2" = "x1" ; then + COND_PLATFORM_OS2_1="" + fi + AC_SUBST(COND_PLATFORM_OS2_1) +dnl ### begin block 20_COND_USE_SOSYMLINKS_1[./mysql++.bkl] ### + COND_USE_SOSYMLINKS_1="#" + if test "x$USE_SOSYMLINKS" = "x1" ; then + COND_USE_SOSYMLINKS_1="" + fi + AC_SUBST(COND_USE_SOSYMLINKS_1) +dnl ### begin block 20_COND_USE_SOVERCYGWIN_1_USE_SOVERSION_1[./mysql++.bkl] ### + COND_USE_SOVERCYGWIN_1_USE_SOVERSION_1="#" + if test "x$USE_SOVERCYGWIN" = "x1" -a "x$USE_SOVERSION" = "x1" ; then + COND_USE_SOVERCYGWIN_1_USE_SOVERSION_1="" + fi + AC_SUBST(COND_USE_SOVERCYGWIN_1_USE_SOVERSION_1) +dnl ### begin block 20_COND_USE_SOVERLINUX_1[./mysql++.bkl] ### + COND_USE_SOVERLINUX_1="#" + if test "x$USE_SOVERLINUX" = "x1" ; then + COND_USE_SOVERLINUX_1="" + fi + AC_SUBST(COND_USE_SOVERLINUX_1) +dnl ### begin block 20_COND_USE_SOVERSION_0[./mysql++.bkl] ### + COND_USE_SOVERSION_0="#" + if test "x$USE_SOVERSION" = "x0" ; then + COND_USE_SOVERSION_0="" + fi + AC_SUBST(COND_USE_SOVERSION_0) +dnl ### begin block 20_COND_USE_SOVERSOLARIS_1[./mysql++.bkl] ### + COND_USE_SOVERSOLARIS_1="#" + if test "x$USE_SOVERSOLARIS" = "x1" ; then + COND_USE_SOVERSOLARIS_1="" + fi + AC_SUBST(COND_USE_SOVERSOLARIS_1) +dnl ### begin block 20_COND_WINDOWS_IMPLIB_1[./mysql++.bkl] ### + COND_WINDOWS_IMPLIB_1="#" + if test "x$WINDOWS_IMPLIB" = "x1" ; then + COND_WINDOWS_IMPLIB_1="" + fi + AC_SUBST(COND_WINDOWS_IMPLIB_1) ADDED config/libm.m4 Index: config/libm.m4 ================================================================== --- /dev/null +++ config/libm.m4 @@ -0,0 +1,37 @@ +dnl @synopsis LIB_MATH +dnl +dnl This macro figures out how whether programs using C's math routines +dnl need to link to libm or not. This is common on SysV Unices. +dnl +dnl @category C +dnl @author Warren Young +dnl @version 1.2, 2006-03-06 + +AC_DEFUN([LIB_MATH], +[ + AC_MSG_CHECKING([whether -lm is needed to use C math functions]) + + MYSQLPP_EXTRA_LIBS= + TRY_LIBM=no + AC_TRY_LINK( + [ #include ], + [ floor(0); ], AC_MSG_RESULT(no), TRY_LIBM=yes) + + if test "x$TRY_LIBM" = "xyes" + then + save_LIBS=$LIBS + LIBS="$LIBS -lm" + AC_TRY_LINK( + [ #include ], + [ floor(0); ], + [ + MYSQLPP_EXTRA_LIBS=-lm + AC_MSG_RESULT(yes) + ], + AC_MSG_ERROR([Failed to build program containing math functions!])) + LIBS="$save_LIBS" + fi + + AC_SUBST(MYSQLPP_EXTRA_LIBS) +]) + ADDED config/localtime_r.m4 Index: config/localtime_r.m4 ================================================================== --- /dev/null +++ config/localtime_r.m4 @@ -0,0 +1,30 @@ +dnl @synopsis AX_C_LOCALTIME_R +dnl +dnl This macro determines whether the C runtime library contains +dnl localtime_r(), a thread-safe replacement for localtime(). +dnl +dnl @version 1.0, 2007/02/20 +dnl @author Warren Young +AC_DEFUN([AX_C_LOCALTIME_R], +[ + AC_MSG_CHECKING([for localtime_r()]) + + AC_TRY_RUN([ + #include + int main(void) + { + time_t tt; + struct tm stm; + localtime_r(&tt, &stm); + return 0; + } + ], [localtime_r_found=yes], [localtime_r_found=no], [localtime_r_found=no]) + + AC_MSG_RESULT([$localtime_r_found]) + if test x"$localtime_r_found" = xyes + then + AC_DEFINE(HAVE_LOCALTIME_R, 1, + [Define if you have the localtime_r() facility]) + fi +]) dnl AX_C_LOCALTIME_R + ADDED config/mysql++.m4 Index: config/mysql++.m4 ================================================================== --- /dev/null +++ config/mysql++.m4 @@ -0,0 +1,131 @@ +#-###################################################################### +# mysql++.m4 - Example autoconf macro showing how to find MySQL++ +# library and header files. +# +# Copyright (c) 2004-2008 by Educational Technology Resources, Inc. +# +# This file 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. +# +# 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with MySQL++; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +# USA +#-###################################################################### + +dnl @synopsis MYSQLPP_DEVEL +dnl +dnl This macro tries to find the MySQL++ library and header files. +dnl +dnl We define the following configure script flags: +dnl +dnl --with-mysqlpp: Give prefix for both library and headers, and try +dnl to guess subdirectory names for each. (e.g. tack /lib and +dnl /include onto given dir name, and other common schemes.) +dnl --with-mysqlpp-lib: Similar to --with-mysqlpp, but for library only. +dnl --with-mysqlpp-include: Similar to --with-mysqlpp, but for headers +dnl only. +dnl +dnl This macro depends on having the default compiler and linker flags +dnl set up for building programs against the MySQL C API. The mysql.m4 +dnl macro in this directory fits this bill; run it first. +dnl +dnl @version 1.1, 2008/02/07 +dnl @author Warren Young + +AC_DEFUN([MYSQLPP_DEVEL], +[ +AC_CACHE_CHECK([for MySQL++ devel stuff], ac_cv_mysqlpp_devel, +[ + # + # Set up configure script macros + # + AC_ARG_WITH(mysqlpp, + [ --with-mysqlpp= path containing MySQL++ header and library subdirs], + [MYSQLPP_lib_check="$with_mysqlpp/lib $with_mysqlpp/lib/mysql++" + MYSQLPP_inc_check="$with_mysqlpp/include $with_mysqlpp/include/mysql++"], + [MYSQLPP_lib_check="/usr/local/mysql++/lib /usr/local/lib/mysql++ /opt/mysql++/lib /usr/lib/mysql++ /usr/local/lib /usr/lib" + MYSQLPP_inc_check="/usr/local/mysql++/include /usr/local/include/mysql++ /opt/mysql++/include /usr/local/include/mysql++ /usr/local/include /usr/include/mysql++ /usr/include"]) + AC_ARG_WITH(mysqlpp-lib, + [ --with-mysqlpp-lib= directory path of MySQL++ library], + [MYSQLPP_lib_check="$with_mysqlpp_lib $with_mysqlpp_lib/lib $with_mysqlpp_lib/lib/mysql"]) + AC_ARG_WITH(mysqlpp-include, + [ --with-mysqlpp-include= directory path of MySQL++ headers], + [MYSQLPP_inc_check="$with_mysqlpp_include $with_mysqlpp_include/include $with_mysqlpp_include/include/mysql"]) + + # + # Look for MySQL++ library + # + MYSQLPP_libdir= + for dir in $MYSQLPP_lib_check + do + if test -d "$dir" && \ + ( test -f "$dir/libmysqlpp.so" || + test -f "$dir/libmysqlpp.a" ) + then + MYSQLPP_libdir=$dir + break + fi + done + + if test -z "$MYSQLPP_libdir" + then + AC_MSG_ERROR([Didn't find the MySQL++ library dir in '$MYSQLPP_lib_check']) + fi + + case "$MYSQLPP_libdir" in + /* ) ;; + * ) AC_MSG_ERROR([The MySQL++ library directory ($MYSQLPP_libdir) must be an absolute path.]) ;; + esac + + AC_MSG_RESULT([lib in $MYSQLPP_libdir]) + + case "$MYSQLPP_libdir" in + /usr/lib) ;; + *) LDFLAGS="$LDFLAGS -L${MYSQLPP_libdir}" ;; + esac + + + # + # Look for MySQL++ headers + # + AC_MSG_CHECKING([for MySQL++ header directory]) + MYSQLPP_incdir= + for dir in $MYSQLPP_inc_check + do + if test -d "$dir" && test -f "$dir/mysql++.h" + then + MYSQLPP_incdir=$dir + break + fi + done + + if test -z "$MYSQLPP_incdir" + then + AC_MSG_ERROR([Didn't find the MySQL++ header dir in '$MYSQLPP_inc_check']) + fi + + case "$MYSQLPP_incdir" in + /* ) ;; + * ) AC_MSG_ERROR([The MySQL++ header directory ($MYSQLPP_incdir) must be an absolute path.]) ;; + esac + + AC_MSG_RESULT([$MYSQLPP_incdir]) + + CPPFLAGS="$CPPFLAGS -I${MYSQLPP_incdir}" + + AC_MSG_CHECKING([that we can build MySQL++ programs]) + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([#include ], + [mysqlpp::Connection c(false)])], + ac_cv_mysqlpp_devel=yes, + AC_MSG_ERROR(no)) +])]) dnl End MYSQLPP_DEVEL + ADDED config/mysql_loc.m4 Index: config/mysql_loc.m4 ================================================================== --- /dev/null +++ config/mysql_loc.m4 @@ -0,0 +1,112 @@ +dnl @synopsis MYSQL_API_LOCATION +dnl +dnl This macro tries to find MySQL C API header and library locations. +dnl +dnl We define the following configure script flags: +dnl +dnl --with-mysql: Give prefix for both library and headers, and try +dnl to guess subdirectory names for each. (e.g. Tack /lib and +dnl /include onto given dir name, and other common schemes.) +dnl --with-mysql-lib: Similar to --with-mysql, but for library only. +dnl --with-mysql-include: Similar to --with-mysql, but for headers +dnl only. +dnl +dnl @version 1.2, 2007/02/20 +dnl @author Warren Young +AC_DEFUN([MYSQL_API_LOCATION], +[ + # + # Set up configure script macros + # + AC_ARG_WITH(mysql, + [ --with-mysql= root directory path of MySQL installation], + [MYSQL_lib_check="$with_mysql/lib/mysql $with_mysql/lib" + MYSQL_inc_check="$with_mysql/include $with_mysql/include/mysql"], + [MYSQL_lib_check="/usr/lib64 /usr/lib /usr/lib64/mysql /usr/lib/mysql /usr/local/lib64 /usr/local/lib /usr/local/lib/mysql /usr/local/mysql/lib /usr/local/mysql/lib/mysql /opt/mysql/lib /opt/mysql/lib/mysql" + MYSQL_inc_check="/usr/include/mysql /usr/local/include/mysql /usr/local/mysql/include /usr/local/mysql/include/mysql /opt/mysql/include/mysql"]) + AC_ARG_WITH(mysql-lib, + [ --with-mysql-lib= directory path of MySQL library installation], + [MYSQL_lib_check="$with_mysql_lib $with_mysql_lib/lib64 $with_mysql_lib/lib $with_mysql_lib/lib64/mysql $with_mysql_lib/lib/mysql"]) + AC_ARG_WITH(mysql-include, + [ --with-mysql-include= directory path of MySQL header installation], + [MYSQL_inc_check="$with_mysql_include $with_mysql_include/include $with_mysql_include/include/mysql"]) + + # + # Decide which C API library to use, based on thread support + # + if test "x$acx_pthread_ok" = xyes + then + MYSQL_C_LIB=mysqlclient_r + else + MYSQL_C_LIB=mysqlclient + fi + + # + # Look for MySQL C API library + # + AC_MSG_CHECKING([for MySQL library directory]) + MYSQL_libdir= + for m in $MYSQL_lib_check + do + if test -d "$m" && \ + (test -f "$m/lib$MYSQL_C_LIB.so" || test -f "$m/lib$MYSQL_C_LIB.a") + then + MYSQL_libdir=$m + break + fi + done + + if test -z "$MYSQL_libdir" + then + AC_MSG_ERROR([Didn't find $MYSQL_C_LIB library in '$MYSQL_lib_check']) + fi + + case "$MYSQL_libdir" in + /* ) ;; + * ) AC_MSG_ERROR([The MySQL library directory ($MYSQL_libdir) must be an absolute path.]) ;; + esac + + AC_MSG_RESULT([$MYSQL_libdir]) + + case "$MYSQL_libdir" in + /usr/lib) ;; + *) LDFLAGS="$LDFLAGS -L${MYSQL_libdir}" ;; + esac + + + # + # Look for MySQL C API headers + # + AC_MSG_CHECKING([for MySQL include directory]) + MYSQL_incdir= + for m in $MYSQL_inc_check + do + if test -d "$m" && test -f "$m/mysql.h" + then + MYSQL_incdir=$m + break + fi + done + + if test -z "$MYSQL_incdir" + then + AC_MSG_ERROR([Didn't find the MySQL include dir in '$MYSQL_inc_check']) + fi + + case "$MYSQL_incdir" in + /* ) ;; + * ) AC_MSG_ERROR([The MySQL include directory ($MYSQL_incdir) must be an absolute path.]) ;; + esac + + AC_MSG_RESULT([$MYSQL_incdir]) + + CPPFLAGS="$CPPFLAGS -I${MYSQL_incdir}" + + save_LIBS=$LIBS + LIBS="$LIBS $MYSQLPP_EXTRA_LIBS" + AC_CHECK_LIB($MYSQL_C_LIB, mysql_store_result, [], [ + AC_MSG_ERROR([Could not find working MySQL client library!]) ]) + AC_SUBST(MYSQL_C_LIB) + LIBS=$save_LIBS +]) dnl MYSQL_API_LOCATION + ADDED config/mysql_ssl.m4 Index: config/mysql_ssl.m4 ================================================================== --- /dev/null +++ config/mysql_ssl.m4 @@ -0,0 +1,17 @@ +dnl @synopsis MYSQL_WITH_SSL +dnl +dnl This macro determines whether mysql_ssl_set() API call exists. +dnl Requires at least MySQL 4.0.1. +dnl +dnl @version $Id$, $Date$ +dnl @author Ovidiu Bivolaru +AC_DEFUN([MYSQL_WITH_SSL], +[ + # + # Check for mysql_ssl_set() in libmysqlclient(_r) + # + AC_CHECK_LIB($MYSQL_C_LIB, mysql_ssl_set, [ + AC_DEFINE(HAVE_MYSQL_SSL_SET,, Define if your MySQL library has SSL functions) + ]) dnl AC_CHECK_LIB(mysqlclient, mysql_ssl_set) +]) dnl MYSQL_WITH_SSL + ADDED config/socket_nsl.m4 Index: config/socket_nsl.m4 ================================================================== --- /dev/null +++ config/socket_nsl.m4 @@ -0,0 +1,72 @@ +dnl @synopsis LIB_SOCKET_NSL +dnl +dnl This macro figures out what libraries are required on this platform +dnl to link sockets programs. +dnl +dnl The common cases are not to need any extra libraries, or to need +dnl -lsocket and -lnsl. We need to avoid linking with libnsl unless +dnl we need it, though, since on some OSes where it isn't necessary it +dnl will totally break networking. Unisys also includes gethostbyname() +dnl in libsocket but needs libnsl for socket(). +dnl +dnl @category Misc +dnl @author Warren Young +dnl @version 1.5, 2006-03-06 + +AC_DEFUN([LIB_SOCKET_NSL], +[ + save_LIBS="$LIBS" + + AC_MSG_CHECKING([whether -lsocket is needed]) + TRY_LSOCKET=no + AC_TRY_LINK( + [ + #include + #include + #include + #include + ], + [ socket(AF_INET, SOCK_STREAM, 0); ], + AC_MSG_RESULT(no), TRY_LSOCKET=yes) + + if test "x$TRY_LSOCKET" = "xyes" + then + LIBS="-lsocket $LIBS" + AC_TRY_LINK( + [ + #include + #include + #include + #include + ], + [ socket(AF_INET, SOCK_STREAM, 0); ], + [ + MYSQLPP_EXTRA_LIBS="-lsocket $MYSQLPP_EXTRA_LIBS" + AC_MSG_RESULT(yes) + ], + AC_MSG_ERROR([failed to link using -lsocket!])) + fi + + AC_MSG_CHECKING([whether -lnsl is needed]) + TRY_LNSL=no + AC_TRY_LINK( + [ #include ], + [ gethostbyname("gna.org"); ], + AC_MSG_RESULT(no), TRY_LNSL=yes) + + if test "x$TRY_LNSL" = "xyes" + then + LIBS="-lnsl $LIBS" + AC_TRY_LINK( + [ #include ], + [ gethostbyname("gna.org"); ], + [ + MYSQLPP_EXTRA_LIBS="-lnsl $MYSQLPP_EXTRA_LIBS" + AC_MSG_RESULT(yes) + ], + AC_MSG_ERROR([failed to link using -lnsl!])) + fi + + AC_SUBST(MYSQLPP_EXTRA_LIBS) +]) + ADDED config/stl_slist.m4 Index: config/stl_slist.m4 ================================================================== --- /dev/null +++ config/stl_slist.m4 @@ -0,0 +1,55 @@ +dnl @synopsis STL_SLIST_EXTENSION +dnl +dnl This macro determines whether the local STL implementation includes +dnl a singly-linked list template, slist, and if so, where it is. +dnl +dnl @version 1.2, 2005/07/22 +dnl @author Warren Young +AC_DEFUN([STL_SLIST_EXTENSION], +[ + AC_MSG_CHECKING([for STL slist extension]) + + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [#include ], + [slist l])], + AC_DEFINE(HAVE_GLOBAL_SLIST, 1, + [ Define if you have ::slist container in ]), + TRY_NEXT=yes) + + if test -z "$TRY_NEXT" + then + SLIST_LOC=", global scope" + else + TRY_NEXT="" + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [#include ], + [std::slist l])], + AC_DEFINE(HAVE_STD_SLIST, 1, + [ Define if you have std::slist container in ]), + TRY_NEXT=yes) + + if test -z "$TRY_NEXT" + then + SLIST_LOC=", namespace std" + else + TRY_NEXT="" + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [#include ], + [__gnu_cxx::slist l])], + AC_DEFINE(HAVE_EXT_SLIST, 1, + [ Define if you have __gnu_cxx:slist container in ]), + SLIST_LOC="not found") + + if test -z "$SLIST_LOC" + then + SLIST_LOC=", namespace __gnu_cxx" + fi + fi + fi + + AC_MSG_RESULT([$SLIST_LOC]) +]) dnl STL_SLIST_EXTENSION + ADDED configure.ac Index: configure.ac ================================================================== --- /dev/null +++ configure.ac @@ -0,0 +1,86 @@ +# This file 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. +# +# 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with MySQL++; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +# USA + +# Standard autotools stuff +AC_INIT(mysql++, 3.0.3, plusplus@lists.mysql.com, mysql++) +AC_CONFIG_HEADER(config.h) +AC_DISABLE_STATIC +AC_CANONICAL_SYSTEM + + +# Break package version up into major, minor and bugfix components. +MYSQLPP_VERSION_MAJOR=`echo $PACKAGE_VERSION | cut -f1 -d.` +AC_SUBST(MYSQLPP_VERSION_MAJOR) +MYSQLPP_VERSION_MINOR=`echo $PACKAGE_VERSION | cut -f2 -d.` +AC_SUBST(MYSQLPP_VERSION_MINOR) +MYSQLPP_VERSION_BUGFIX=`echo $PACKAGE_VERSION | cut -f3 -d.` +AC_SUBST(MYSQLPP_VERSION_BUGFIX) + + +# Include Bakefile macros +AC_BAKEFILE([m4_include(config/autoconf_inc.m4)]) + + +# Check for Standard C support +AC_PROG_CC +AC_HEADER_STDC + + +# Figure out whether/how to handle threading support, if available. +AC_ARG_ENABLE(thread-check, + [ --enable-thread-check Check for threads, and use if available. ], + [ thread_check=yes ]) +if test "x$thread_check" = "xyes" +then + ACX_PTHREAD + LIBS="$PTHREAD_LIBS $LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + CC="$PTHREAD_CC" +fi + + +# Checks for libraries and local system features +AC_CHECK_HEADERS(zlib.h, AC_CHECK_LIB(z, gzread, [], + [ AC_MSG_ERROR([zlib is required]) ])) +AC_CHECK_HEADERS(synch.h) +LIB_MATH +LIB_SOCKET_NSL +MYSQL_API_LOCATION +MYSQL_WITH_SSL +AX_C_LOCALTIME_R +AC_CHECK_LIB(intl, main) + + +# If this is Cygwin, add a linker flag to suppress a silly link message. +case "${host}" in + *cygwin*) + LDFLAGS="$LDFLAGS -Wl,--enable-auto-import" + ;; +esac + + +# Check for Standard C++ support, and extensions. This must be near +# the end, because the CPLUSPLUS directive makes autoconf use C++ +# compiler for all subsequent tests! +AC_PROG_CXX +AC_LANG_CPLUSPLUS +STL_SLIST_EXTENSION + + +# +# Configure process complete; write out files generated from *.in. +# +AC_OUTPUT([Makefile mysql++.spec doc/userman/userman.dbx lib/Doxyfile lib/mysql++.h]) + DELETED configure.in Index: configure.in ================================================================== --- configure.in +++ /dev/null @@ -1,58 +0,0 @@ -dnl Process this file with autoconf to produce a configure script. -AC_INIT(sqlplusint/sqlplus.hh) - -VERSION=`cat ${srcdir}/.version` -SQLPLUS_MAJOR_VERSION=[`expr $VERSION : '\([0-9][0-9]*\)'`] -AC_SUBST(SQLPLUS_MAJOR_VERSION) -SQLPLUS_MINOR_VERSION=[`expr $VERSION : '[0-9][0-9]*\.\([0-9][0-9]*\)'`] -AC_SUBST(SQLPLUS_MINOR_VERSION) -SQLPLUS_MICRO_VERSION=[`expr $VERSION : '[0-9][0-9]*\.[0-9][0-9]*\.\([0-9][0-9]*\)'`] -AC_SUBST(SQLPLUS_MICRO_VERSION) -AM_INIT_AUTOMAKE(sqlplus, $VERSION) - -AM_CONFIG_HEADER(config.h) - -AC_PROG_MAKE_SET - -AM_PROG_LIBTOOL - -dnl Initialize maintainer mode -AM_MAINTAINER_MODE - -# -# Location of MySQL installation -# -MYSQL_HOME=/usr/local -if test ! -d "${MYSQL_HOME}/include/mysql" -then - MYSQL_HOME=/usr -fi -AC_CACHE_CHECK([MYSQL_HOME], webbase_cv_mysql_home, -AC_ARG_WITH(mysql, - [ --with-mysql= root directory path of MySQL installation], - [MYSQL_HOME=$with_mysql]) -webbase_cv_mysql_home=${MYSQL_HOME} -) -AC_SUBST(MYSQL_HOME) -LDFLAGS="$LDFLAGS -L${MYSQL_HOME}/lib/mysql" -CPPFLAGS="$CPPFLAGS -I${MYSQL_HOME}/include/mysql" - -AC_PROG_CC -AC_PROG_CXX - -AC_CHECK_LIB(intl, main) -AC_CHECK_LIB(socket, main) -AC_CHECK_LIB(nsl, main) -AC_CHECK_LIB(mysqlclient, mysql_store_result) -AM_WITH_DMALLOC() - -dnl Checks for header files. -AC_HEADER_STDC - -dnl Checks for typedefs, structures, and compiler characteristics. -AC_C_CONST - -dnl Checks for library functions. -AC_CHECK_FUNCS(strtol) - -AC_OUTPUT(Makefile sqlplusint/Makefile examples/Makefile) DELETED doc/Makefile Index: doc/Makefile ================================================================== --- doc/Makefile +++ /dev/null @@ -1,29 +0,0 @@ -# this is a makefile for making a manual - -default: manual - -perlclean: - -rm -f manual.txt manual.html - $(MAKE) -C ../sqlplusint/ perlclean - -manual: - $(MAKE) -C ../sqlplusint/ classref - perl insert-classref.pl - -rm -f -r man-html - -mkdir man-html - perl examples-proc.pl - latex manual.tex - latex manual.tex - latex2html \ - -split 3 \ - -toc_depth 3 \ - -dir man-html \ - -long_titles 2 \ - -local_icons \ - -show_section_numbers \ - manual.tex - - -rm -f -r man-text - -mkdir man-text - perl html2txt.pl - ADDED doc/README-devel-RPM.txt Index: doc/README-devel-RPM.txt ================================================================== --- /dev/null +++ doc/README-devel-RPM.txt @@ -0,0 +1,10 @@ +mysql++-devel RPM installs the files you need when building your own +MySQL++ based programs, as well as documentation and examples that +can help you learn how to use the library. + +The MySQL++ header files are in /usr/include/mysql++, the library +is in /usr/lib, and the example programs' source code is in +/usr/share/doc/mysql++-devel-*/examples. For more information on +the examples, see the README-examples.txt file in the directory +containing the examples. + ADDED doc/README-manuals-RPM.txt Index: doc/README-manuals-RPM.txt ================================================================== --- /dev/null +++ doc/README-manuals-RPM.txt @@ -0,0 +1,5 @@ +For more information about MySQL++, see its home page: + + http://tangentsoft.net/mysql++/ + +See the LICENSE file in this directory for the library's license. DELETED doc/doc-fix.pl Index: doc/doc-fix.pl ================================================================== --- doc/doc-fix.pl +++ /dev/null @@ -1,22 +0,0 @@ -$/ = undef; - -open F, $ARGV[0]; - -$_=; - -s~\\begin_inset LatexCommand \\ref.+ -\\end_inset -(.+) -\\begin_inset LatexDel .+ -\\end_inset -.+ -\\begin_inset LatexDel .+ -\\end_inset -~\\begin_inset LatexCommand \\ref\{$1\} - -\\end_inset -~g; - -open F, ">$ARGV[0]"; -print F $_; - DELETED doc/doc-trim.pl Index: doc/doc-trim.pl ================================================================== --- doc/doc-trim.pl +++ /dev/null @@ -1,11 +0,0 @@ -$/ = undef; - -open F, $ARGV[0]; - -$_=; - -/(\\layout Section.+)\\the_end/s; - -open F, ">$ARGV[0]"; -print F $1; - DELETED doc/doc.tex.tmpl Index: doc/doc.tex.tmpl ================================================================== --- doc/doc.tex.tmpl +++ /dev/null @@ -1,193 +0,0 @@ -#ptags [ ] -[!autolink] - -[foreach class] -\section{[class]} -\label{[filter ref][class dont_filter][endfilter]} - -[if templ]template [endif] \ -[if struct]struct[endif][else][if union]union[endif][else]class[endelse][endelse] \ -\textbf{[class]}[templ] - -[if parents]\textbf{Parents:} [parents][endif] - -[if with_class][if with_class != [class]] - \textbf{Related to:} [with_class] \ - (\ref{[filter ref][with_class dont_filter][endfilter]}) -[endif][endif] - -[if brief]\textit{[brief]}[endif] - -[detail] - -\subsection{Synopses} - -[if public] -\textbf{Public members:} -\begin{itemize} -[foreach public] -\item [if pure]pure [endif][type] \textbf{[mname]} \ - [if func] \ - ([args]) [if const] const [endif] \ - [if throws] throws [throwclass]([throwargs])[endif] \ - [endif] \ - [if enum] [lb][args][rb] [endif] \ - [if detail] (\ref{[filter ref][class dont_filter]::[member dont_filter][endfilter]}) [endif] \ - [if brief] - \textit{[brief]}[endif] \ -[next] - -\end{itemize} -[endif] - -[if protected] -\textbf{Protected members:} -\begin{itemize} - -[foreach protected] -\item [if pure]pure [endif][type] \textbf{[mname]} \ - [if func] \ - ([args]) [if const] const [endif] \ - [if throws] throws [throwclass]([throwargs])[endif] \ - [endif] \ - [if enum] [lb][args][rb] [endif] \ - [if detail] (\ref{[filter ref][class dont_filter]::[member dont_filter][endfilter]}) [endif] \ - [if brief] - \textit{[brief]}[endif] \ -[next] - -\end{itemize} -[endif] - -[nobreak] -[foreach func] -[if with_class == [class]] -[if !l1][def l1] - \textbf{Related Functions} [n] - [n] - \begin{itemize} [n] -[endif] -\item [type] \textbf{[name]} ([args]) - [if throws] throws [throwclass]([throwargs]) [endif] - [if brief] - \textit{[brief]}[endif] [n] -[endif] -[next] -[if l1] [undef l1] - \end{itemize} [n] -[endif] -[endnobreak] - -[nobreak] -[foreach typedef] -[if with_class == [class]] - [if !l1] [def l1] - \textbf{Related Types} [n] - [n] - \begin{itemize} [n] - [endif] -\item [if typedef]typedef [endif][if enum]enum [endif][type] \textbf{[name]} - [if enum] [lb][args][rb] [endif] - [if brief] - \textit{[brief]}[endif] [n] -[endif] -[next] -[if l1] [undef l1] - \end{itemize} [n] -[endif] -[endnobreak] - -[nobreak] -[def pclass [class]] -[foreach class] -[if with_class == [pclass]] [if with_class != [class]] -[if !l1] [def l1] - \textbf{Related Classes} [n] - [n] - \begin{itemize} [n] -[endif] -\item [if templ]template [endif] - [if struct]struct[endif][else][if union]union[endif][else]class[endelse][endelse] - \textbf{[class]}[templ] - (\ref{[filter ref][class dont_escape][endfilter]}) - [if brief] - \textit{[brief]} [endif] [n] -[endif] [endif] -[next] -[if l1] [undef l1] - \end{itemize} [n] -[endif] -[undef pclass] -[endnobreak] - -[foreach public] -[if detail] -\subsection{[member]} -\label{[filter ref][class dont_filter]::[member dont_filter][endfilter]} - - [if pure]pure [endif][type] \textbf{[mname]} \ - [if func] \ - ([args]) [if const] const [endif] \ - [if throws] throws [throwclass]([throwargs])[endif] \ - [endif] \ - [if enum] [lb][args][rb] [endif] - -[if brief]\textit{[brief]}[endif] - -[detail] - -[endif] - -[next] - -[foreach func][if with_class == [class]][// ][if detail] -\subsection{[name]} - -[type] \textbf{[name]} ([args]) \ - [if throws] throws [throwclass]([throwargs]) [endif] - -[if brief]\textit{[brief]}[endif] - -[detail] - -[endif][endif][next] - -[next] - - -\section{Misc Non Members} - -[foreach func][if !with_class] -[if !f1] [def f1] - \textbf{Functions:} - \begin{itemize} -[endif] -\item [type] \textbf{[name]} ([args]) \ - [if throws] throws [throwclass]([throwargs]) [endif] \ - [if brief] - \textit{[brief]}[endif] -[endif][next] -[if f1] [undef f1] -\end{itemize} -[endif] - -[foreach typedef][if !with_class] -[if !tl] [def tl] - \textbf{Types:} - \begin{itemize} -[endif] -\item [if typedef]typedef [endif][if enum]enum [endif][type] \textbf{[name]} - [if enum] [lb][args][rb] [endif] - [if brief] - \textit{[brief]}[endif] -[endif][next] -[if tl] [undef tl] -\end{itemize} -[endif] - -[foreach func] -[if detail][if !with_class] -\subsection{[name]} - -[type] \textbf{[name]} ([args]) \ - [if throws] throws [throwclass]([throwargs]) [endif] - -[if brief]\textit{[brief]}[endif] - -[detail] - -[endif][endif] -[next] DELETED doc/examples-proc.pl Index: doc/examples-proc.pl ================================================================== --- doc/examples-proc.pl +++ /dev/null @@ -1,20 +0,0 @@ - -$/ = undef; -open IN, "manual.tex"; -$_ = ; - -s/\\begin\{comment\}[\n\s]+example:(\S+)[\n\s]*\\end\{comment\}[\n\s]*/${\(&ie($1))}/sg; - -open IN, ">manual.tex"; -print IN; - -sub ie { - my $return; - $return = "\n"; - $return .= "\\begin{verbatim}\n"; - open EIN, "examples/$_[0]"; - local $/ = undef; - $return .= ; - $return .= "\\end{verbatim}\n\n"; - return $return; -} DELETED doc/html2txt.pl Index: doc/html2txt.pl ================================================================== --- doc/html2txt.pl +++ /dev/null @@ -1,7 +0,0 @@ -opendir DIR, "man-html"; - -foreach (readdir(DIR)) { - next unless /(.+?)\.html$/; - print "lynx -dump man-html/$_ > man-text/$1.txt\n" ; - system "lynx -dump man-html/$_ > man-text/$1.txt" ; -} DELETED doc/insert-classref.pl Index: doc/insert-classref.pl ================================================================== --- doc/insert-classref.pl +++ /dev/null @@ -1,22 +0,0 @@ -$/ = undef; - -open F, "manual.tex"; -open CR, "../sqlplusint/doc.tex"; - -$_=; -$classref=; - -s~\\begin{comment}[\s\n]*Begin Class Ref[\s\n]*\\end{comment}.+?\\begin{comment}[\s\n]*End Class Ref[\s\n]*\\end{comment}~ -\\begin{comment} -Begin Class Ref -\\end{comment} -$classref -\\begin{comment} -End Class Ref -\\end{comment} -~s || die "Could not insert classref\n"; - -open F, ">manual.tex"; -print F $_; - - DELETED doc/manual.lyx Index: doc/manual.lyx ================================================================== --- doc/manual.lyx +++ /dev/null @@ -1,13211 +0,0 @@ -#This file was created by Thu Nov 25 16:06:21 1999 -#LyX 0.12 (C) 1995-1998 Matthias Ettrich and the LyX Team -\lyxformat 2.15 -\textclass book -\begin_preamble -\usepackage{html} - -\begin{htmlonly} - -\renewenvironment{lyxcode} - {\begin{list}{}{ - \setlength{\rightmargin}{\leftmargin} - \raggedright - \setlength{\itemsep}{0pt} - \setlength{\parsep}{0pt} - \ttfamily}% - \item[] - \begin{ttfamily}} - {\end{ttfamily} - \end{list} } - -\newenvironment{LyXParagraphIndent}[1]% -{\begin{quote}} -{\end{quote}} - -\end{htmlonly} -\end_preamble -\language default -\inputencoding default -\fontscheme default -\graphics default -\float_placement h -\paperfontsize 11 -\spacing single -\papersize Default -\paperpackage a4 -\use_geometry 1 -\use_amsmath 0 -\paperorientation portrait -\leftmargin 1in -\rightmargin 1in -\secnumdepth 2 -\tocdepth 2 -\paragraph_separation skip -\defskip medskip -\quotes_language english -\quotes_times 2 -\papercolumns 1 -\papersides 1 -\paperpagestyle default - -\layout Title - -Mysql++ -\newline -A C++ API for Mysql -\newline -ver 1.4 -\layout Author - -Kevin Atkinson -\newline -(kevinatk@home.com) -\newline - Sinisa Milivojevic -\newline -(sinisa@cytanet.com.cy) -\newline -Michael Widenius -\newline -(monty@mysql.com) -\layout Standard - - -\begin_inset LatexCommand \tableofcontents - -\end_inset - - -\layout Part* - -Introductory Material -\layout Chapter - -Introduction -\layout Section - -What is Mysql++ -\layout Standard - -Mysql++ is a complex C++ API for Mysql (And other SQL Databases Soon). - The goal of this API is too make working with Queries as easy as working - with other STL Containers. - See the Overview chapter ( -\begin_inset LatexCommand \ref{Overview} - -\end_inset - -) for the components that make up Mysql++. -\layout Section - -Getting Mysql++ -\layout Standard - -The latest version of Mysql++ can be found at the mysql++ web site at http://www. -mysql.com/mysql++. -\layout Section - -Mysql++ Mailing List -\layout Standard - -Instructions for joining the mailing list (and an archive of the mailing - list) can be found off the Mysql++ home page at http://www.mysql.com/mysql++ -\layout Chapter - -Overview -\layout Standard - - -\begin_inset LatexCommand \label{Overview} - -\end_inset - -The Mysql++ API has developed into a very complex and powerful being. - With many different ways to accomplish the same task. - Unfortunately this means that figuring out how to perform a simple task - can be frustrating for new users of my library. - In this section I will attempt to provide an overview of the many different - components of the library. -\layout Standard - -Like working with most other SQL API the process for executing queries is - the same. - 1) You open the connection, 2) You form and execute the queries, 3) You - iterate through the result set. - It not much different in my C++ API. - However there is a lot of extra functionality along each step of the way. -\layout Section* - -The Main Database Handle -\layout Standard - -This is a class that handles the connection to the Mysql server. - You always need at least one of these objects to do anything. - It can either create a separate queries object or directly execute queries. - The separate query object is the recommended way as it gives you far more - power. -\layout Section* - -The Query Object -\layout Standard - -This object is the recommended way of executing queries. - It is subclassed from strstream which means you can write to it like any - other stream to aid in the formation of queries. -\layout Standard - -You can also set up Template queries with this class. - Template queries are a way of setting up queries with replaceable parameters - that you can change throughout your program. -\layout Standard - -You can also use specialized structures and even the dramatic result sets - to aid in creating queries however more on that latter. -\layout Standard - -The Query object returns an object with information about the success of - a query for non-select queries (queries that don't return a result set). -\layout Section* - -The Result Sets -\layout Standard - -For queries that return a result set you have essentially two different - ways of handling the results: in a dramatic result set, or in a static - one. -\layout Subsection* - -The Dramatic Result Set -\layout Standard - -The Dramatic Result set is a result set in which the names of the columns - and the type of information of the columns does not need to be determined - at compile time. - The result set can be completely constant in which the data is returned - to you in a constant string link class, semi-constant in which you can - modify the data one row at a time, or a truly mutable in which in you can - modify the data in any way you like. -\layout Standard - -The constant result set is a result set that is closely bound to the result - set in the C API and is the one that provides the most functionality. - With this result set you can find out detailed information about the type - of information stored in each of the columns. - This is also the fastest because the data does not need to be copied at - all. -\layout Standard - -The semi-constant result set is like the constant result set except you - can modify the data one row at a time. - The data you modify is actually a copy of the data returned by the server. - This means that modifying the data does not change the actual result set - at all. -\layout Standard - -The semi-constant result set is actually the same thing as the constant - result set. - The only difference is that when you request a row from the result set - you specifically declare the row as a mutable one. - This means that you can get some rows back as constant rows and others - as mutable ones. -\layout Standard - -The truly mutable result set is a result set similar to the constant one - except that the data is truly mutable in the sense that you can change - the data in the actual result set. - However unlike the first one this result set is not bound to the C API - result set. - Instead it containers a copy of the data returned by the C API in a two-dimensi -onal vector. - Because of this the detailed information about each of the columns is not - currently available, only the column names and the C++ type that most closely - matches the original SQL type. - Also, because it makes a copy of the data returned from the C API, there - is a little bit of performance penalty to using this one. -\layout Standard - -The rows in all the dramatic result sets are very close to an Standard Template - Library (STL) random access container. - This means that they have an iterator which can be used for STL algorithms. - There is even couple of specialized utility function to aid in the use - of the result sets in STL algorithms. -\layout Standard - -The columns in all the dramatic result are also very close to an STL random - access container. - However, in addition to accessing the columns by there index number you - can also access the columns via there field names. -\layout Standard - -In addition, because both the rows and the columns are STL like containers, - you can also treat the result set as a two- dimensional array. - For example you can get the 5th item on the 2nd row by simply saying result[2][ -5]. - Because you can also use the field names you can substitute the column - number by a field name and say result[2]["price"] to get "price" of the - item on the 2nd row, for example. -\layout Standard - -The actual data that all the dramatic result sets return is stored in a - special string like class that has some additional magic too it. - The magic is that the column data will automatically convert itself into - all of the basic data types as well as some additional types types that - are designed to handle mysql types which includes types for handling dates, - times, sets, and types with a null value. - If there is a problem in the conversion it will either set a warning flag - or throw an exception depending on how it is configured. -\layout Standard - -The drastic result sets can even be used to help form queries with the help - of some additional method. - There is a method for returns: 1) A comma separated list of the data (for - example: 1.5, 10, "Dog, "Brown"), 2) A comma separated list of the field - names (for example: age, weight, what, color), and 3) An equal list (for - example: age = 1.5 AND weight = 10 AND what = "Dog" AND color = "Brown"). -\layout Standard - -Mutable result sets can be created with out an actual query so that you - can take advantage of these methods to aid in inserting data into the database - with out having to first create an unnecessary query. -\layout Subsection* - -The Static Result Sets -\layout Standard - -The results from an query can also be stored statically in what I call a - specialized SQL structure. - These structures are then stored in some STL container such a vector or - list, or even a set or multi-set as the the specialized structures can - also be made less-than-comparable. - Unlike the dramatic result sets it is assumed that the programmer knows - what the result set is going to look like. - Because of this all the information about the columns, including the names, - are lost. -\layout Standard - -These Specialized Structures are exactly that C++ `structs'. - Each member item is stored with a unique name within the structure. - You can in no way use STL algorithms or anything else STL to work with - the individual elements of the structures. - However naturally because these structures are then stored in STL containers - you can use STL algorithms on the containers of these structures. - The containers represent the rows, and the individual elements of the structure - represent the columns. - For example you can access the item named "price" on the second row by - saying result[2].price. - With the dramatic result set you would have probably needed to say result[2]["p -rice"] to accomplish the same result. -\layout Standard - -If there is a problem in converting from the result set returned by the - server to the specialized structures an exception is thrown. -\layout Standard - -To aid in the creating of queries using these specialized structures, the - same query aiding methods are available to use that are available for the - dramatic result sets. - This includes methods for returning a comma separated list of the data, - a comma separated list of the field names, and an equal list. -\layout Section* - -In addition -\layout Standard - -In addition to the material mentioned there are also many generic classes - that can be used with other programs. - Examples of this include a special const string class, a const random access - adapter that will make a random access container out of a class with nothing - but the size() method and the subscript ([]) operator defined and a generic - SQL query class that can be used any SQL C or C++ API. -\layout Chapter - -Important Changes -\layout Standard - -I will try to keep the changes that will break old code to a minimal however - when I do I will document them here. - Once this library goes into alpha testing this section will no longer exist - as I will try very hard not to make changes that will break old code. -\layout Section - -Current Changes -\layout Itemize - -Changed the syntax of equal_list for SSQLS from -\series bold -equal_list (cchar *, Manip, cchar *) -\series default - to -\series bold -equal_list (cchar *, cchar *, Manip) -\series default -. -\layout Itemize - -Mysql++ now runs with egcs. - But -\noun on -beware !, -\noun toggle - do not yet use -O6 -mpentium options are still unsafe for g++, with a heavy - use of constant and static initializers, and especially with C++ exceptions - . - Also, please try to keep all objects as local as possible. - Declare it in the lowest blocks always !! -\layout Itemize - -The -\begin_inset Quotes eld -\end_inset - -connection -\begin_inset Quotes erd -\end_inset - - constructors for -\series bold -Connection -\series default - and -\series bold -Connection::connect -\series default - (formally known as -\series bold -Mysql -\series default -) has changed so that the data base name is the first paremeter. -\layout Itemize - -All new client feature implemented in 3.22.xx as various options on connect - are mplemented in a new constructor and real_connect method -\layout Itemize - -Mysql++ now can be compiled on Win32 with use of Cygwin compiler from Cygnus - Inc. -\layout Itemize - -Autoconf and Automake are fully implemented -\layout Itemize - -The Specialized SQL Structures (formally known as Custom Mysql Structures) - changed from mysql_ to sql_. -\layout Itemize - -Changed all of the functions that return zero (false) on success and non-zero - (true) other wise to bool. - This means that they now return true on success and false on faillier. - This means that you now need to negate your expressions that test the output - of these functions. - -\layout Itemize - -Corrected bugs in sql_query.cc regarding delete versus delete[] and string - length in manip.cc -\layout Itemize - -Almost all methods that returned MysqlString now return a normal string. - Because -\series bold -MysqlString -\series default - objects will convert them selves into string when needed there should not - be a problem with: -\begin_deeper -\layout LyX-Code - -MysqlString s = mysql.host_info -\end_deeper -\layout Itemize - -The data type -\series bold -MysqlRow -\series default - now returns ( -\series bold -MysqlString -\series default - or -\series bold -MysqlColData -\series default -) is now subclassed from a special string class that I wrote to handle working - with a const string in a much more efficient way (ie it doesn't copy it). - Unfortunitlly this data type is also more limited see the section on "const_str -ing" for more info. -\layout Itemize - -All necessary methods pertaining to the administration funcitons have been - added -\layout Section - -Future Changes -\layout Itemize - -The behavior of MysqlString when used with binary operators is going to - change in a future version (if I can figure out how to pull it off) Instead - of converting to the type on the other side of the operator the MysqlString - will it convert to the type the Mysql server said it originally was. - This will be a lot safer and more predictable. -\layout Part* - -Usage -\layout Chapter - -Tutorial by Example -\layout Section - -Introduction -\layout Standard - -This tutorial is meant to give you a jump start into using my API. - My Mysql++ API is a very complicated being with a lot of advance features - that you can due without if all you want to do is execute simple queries. -\layout Section - -Assumptions -\layout Standard - -This tutorial assumes you know C++ fairly well, inparticuler it assumes - you know about the Standard Template Library (STL) and exceptions. -\layout Section - -Running the Examples -\layout Standard - -All of the example code form complete running programs. - However in order to use them you need to first compile them my switching - to the examples directory and typing in -\family typewriter -make -\family default -. - Then you need to set up the database by running reset-db. - The usage of the reset-db program is as follows. -\layout LyX-Code - -reset-db [host [user [password]]] -\layout Standard - -If you leave off host localhost is assumed. - If you leave off user your current username is assumed. - If you leave of the password it is assumed that you don't need one. -\layout Standard - -When you first run the program you need to give it an account with permission - to create databases. - Once the database is created you can use any account that has permission - full permission to the database mysql_cpp_data. - -\layout Standard - -You should also run the reset-db program between examples that modify the - data or else things might not work right. -\layout Section - -The Basics -\layout Subsection - -A Simple Example -\layout Standard - -The following example demonstrates how to open a connection, execute a simple - query, and display the results. - The code can be found in the file -\family typewriter -simple1.cc -\family default - which is located in the examples directory. -\layout Comment - -example:simple1.cc -\layout LyX-Code-Sans - -#include -\newline -#include -\newline -#include -\newline - -\protected_separator - -\newline -int main() { -\newline - -\protected_separator - Connection con("mysql_cpp_data"); -\newline - -\protected_separator - // The full format for the Connection constructor is -\newline - -\protected_separator - // Connection(cchar *db, cchar *host="", -\newline - -\protected_separator - // -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - cchar *user="", cchar *passwd="") -\newline - -\protected_separator - // You may need to specify some of them if the database is not on -\newline - -\protected_separator - // the local machine or you database username is not the same as your -\newline - -\protected_separator - // login name, etc.. -\newline - -\protected_separator - -\newline - -\protected_separator - Query query = con.query(); -\newline - -\protected_separator - // This creates a query object that is bound to con. -\newline - -\protected_separator - -\newline - -\protected_separator - query << "select * from stock"; -\newline - -\protected_separator - // You can write to the query object like you would any other ostrem -\newline - -\protected_separator - -\newline - -\protected_separator - Result res = query.store(); -\newline - -\protected_separator - // Query::store() executes the query and returns the results -\newline - -\protected_separator - -\newline - -\protected_separator - cout << "Query: " << query.preview() << endl; -\newline - -\protected_separator - // Query::preview() simply returns a string with the current query -\newline - -\protected_separator - // string in it. -\newline - -\protected_separator - -\newline - -\protected_separator - cout << "Records Found: " << res.size() << endl << endl; -\newline - -\protected_separator - -\newline - -\protected_separator - Row row; -\newline - -\protected_separator - cout.setf(ios::left); -\newline - -\protected_separator - cout << setw(17) << "Item" -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << setw(4) -\protected_separator - << "Num" -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << setw(7) -\protected_separator - << "Weight" -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << setw(7) -\protected_separator - << "Price" -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << "Date" << endl -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << endl; -\newline - -\protected_separator - -\newline - -\protected_separator - Result::iterator i; -\newline - -\protected_separator - // The Result class has a read-only Random Access Iterator -\newline - -\protected_separator - for (i = res.begin(); i != res.end(); i++) { -\newline - -\protected_separator - -\protected_separator - -\protected_separator - row = *i; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cout << setw(17) << row[0] -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << setw(4) -\protected_separator - << row[1] -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << setw(7) -\protected_separator - << row["weight"] -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - // you can use either the index number or column name when -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - // retrieving the colume data as demonstrated above. -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << setw(7) -\protected_separator - << row[3] -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << row[4] << endl; -\newline - -\protected_separator - } -\newline - -\protected_separator - return 0; -\newline -} -\layout Standard - -Everything here should be fairly obvious. - Take particular notice of how I used an iterator with the result set. -\layout Subsection - -A slightly more complicated example -\layout Standard - -This example is almost like the previous one however it uses exceptions - and the automatic conversion feature of -\series bold -ColData -\series default -. - Pay particular notice to how exceptions are used. - This file for this code is named -\family typewriter -complic1.cc -\family default -. -\layout Comment - -example:complic1.cc -\layout LyX-Code-Sans - -#include -\newline -#include -\newline -#include -\newline - -\protected_separator - -\newline -int main() { -\newline - -\protected_separator - try { // its in one big try block -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - Connection con(use_exceptions); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - con.connect("mysql_cpp_data"); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // Here I broke making the connection into two calls. -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // The first one creates the Connection object with the -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // use exceptions option turned on and the second one -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // makes the connection -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - Query query = con.query(); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - query << "select * from stock"; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - Result res = query.store(); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cout << "Query: " << query.preview() << endl; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cout << "Records Found: " << res.size() << endl << endl; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - Row row; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cout.setf(ios::left); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cout << setw(17) << "Item" -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << setw(4) -\protected_separator - << "Num" -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << setw(7) -\protected_separator - << "Weight" -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << setw(7) -\protected_separator - << "Price" -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << "Date" << endl -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << endl; -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - Result::iterator i; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cout.precision(3); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - for (i = res.begin(); i != res.end(); i++) { -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - row = *i; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - cout << setw(17) << row["item"] << setw(4) << row[1] -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << setw(7) -\protected_separator - << (double)row[2] -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -// This is converting the row to a double so that we -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -// can set the precision of it. -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -// ColData has the nice feature that it will convert to -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -// any of the basic c++ types. -\protected_separator - if there is a problem -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -// in the conversion it will throw an exception (which I -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -// cache below). -\protected_separator - To test it try changing the 2 in row[2] -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -// to row[0] -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << setw(7) << (double)row[3]; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - Date date = row["sdate"]; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - // The ColData is implicitly converted to a date here. -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - cout.setf(ios::right); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - cout.fill('0'); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - cout << setw(2) << date.month << "-" << setw(2) << date.day << endl; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - cout.fill(' '); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - cout.unsetf(ios::right); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - } -\newline - -\protected_separator - -\protected_separator - -\protected_separator - return 0; -\newline - -\protected_separator - } catch (BadQuery er) { // handle any connection or -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - // query errors that may come up -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cerr << "Error: " << er.error << endl; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - return -1; -\newline - -\protected_separator - } catch (BadConversion er) { // handle bad conversions -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cerr << "Error: Tried to convert -\backslash -"" << er.data << " -\backslash -" to a -\backslash -"" -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << er.type_name << " -\backslash -"." << endl; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - return -1; -\newline - -\protected_separator - } -\newline -} -\layout Standard - -Everything should be fairly obvious. - A few notes about exceptions, however: -\layout Enumerate - -When the -\series bold -use_exceptions -\series default - flag is set for a parent object it is also set for all of its children - the it created after the flag is set. - For example when the -\series bold -use_exceptions -\series default - flag is set for the -\family typewriter -con -\family default - object, it is also set for the -\family typewriter -query -\family default - object. - Please note that the -\series bold -use_exceptions -\series default - flag is not linked, it is copied. - This means that when you change the -\series bold -use_exceptions -\series default - flag only its new children are affected, -\emph on -not -\emph default - the ones it already created. -\layout Enumerate - - -\series bold -ColData -\series default - will always throw an exception when it encounters a bad conversion. - A bad conversion is defined as a conversion in which: a) All the charters - from the string are not read in and b) The remaining characters are something - other than whitespace, zeros (0), or periods (.). - This means that when ``1.25'' is converted into an int an exception will - be thrown however not when ``1.00'' is converted into an int as the remaining - characters are the period and the zero. - -\layout Standard - -To see how the exception work try creating an error. - Some good things to try would be misspelling the table name or changing - the double to an int. -\layout Subsection - -Getting Info about the Fields -\layout Standard - -The following example demonstrates how to get some basic information about - the fields, including the name of the field and the SQL type. - The file is called fieldinfo1.cc. -\layout Comment - -example:fieldinf1.cc -\layout LyX-Code-Sans - -#include -\newline -#include -\newline -#include -\newline - -\protected_separator - -\newline -int main() { -\newline - -\protected_separator - try { // its in one big try block -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - Connection con(use_exceptions); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - con.connect("mysql_cpp_data"); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - Query query = con.query(); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - query << "select * from stock"; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - Result res = query.store(); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cout << "Query: " << query.preview() << endl; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cout << "Records Found: " << res.size() << endl << endl; -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cout << "Query Info: -\backslash -n"; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cout.setf(ios::left); -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - for (unsigned int i = 0; i < res.size(); i++) { -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - cout << setw(2) -\protected_separator - << i -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << setw(15) << res.names(i).c_str() -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -// this is the name of the field -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << setw(15) << res.types(i).sql_name() -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -// this is the SQL identifier name -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -// Result::types(unsigned int) returns a mysql_type_info which in many -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -// ways is like type_info except that it has additional sql type -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -// information in it. - (with one of the methods being sql_name()) -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << setw(20) << res.types(i).name() -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -// this is the C++ identifier name which most closely resembles -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -// the sql name (its is implementation defined and often not very readable) -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << endl; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - } -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cout << endl; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - if (res.types(0) == typeid(string)) -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - cout << "Field 'item' is of an sql type which most closely resembles a -\backslash -n" -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << "the c++ string type -\backslash -n"; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // this is demonstrating how a mysql_type_info can be compared with a c++ -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // type_info. -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - if (res.types(1) == typeid(short int)) -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - cout << "Field 'num' is of an sql type which most closely resembles a -\backslash -n" -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << "the c++ short int type -\backslash -n"; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - else if (res.types(1).base_type() == typeid(short int)) -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - cout << "Field 'num' base type is of an sql type which most closely -\backslash -n" -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << "resembles a the c++ short int type -\backslash -n"; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // However you have to be careful as if it can be null the actual type - is -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // Null not TYPE. -\protected_separator - So you should always use the base_type method -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // to get at the underlying type. -\protected_separator - If the type is not null than this base -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // type would be the same as its type. -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - return 0; -\newline - -\protected_separator - } catch (BadQuery er) { -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cerr << "Error: " << er.error << endl; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - return -1; -\newline - -\protected_separator - } catch (BadConversion er) { // handle bad conversions -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cerr << "Error: Tried to convert -\backslash -"" << er.data << " -\backslash -" to a -\backslash -"" -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << er.type_name << " -\backslash -"." << endl; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - return -1; -\newline - -\protected_separator - } -\newline -} -\newline - -\protected_separator - -\layout Section - -Specialized SQL Structures -\layout Subsection - -Retrieving Data -\layout Standard - -The next example demonstrates a fairly interesting concept known as Specialized - SQL Structures (SSQLS). - The file name for this code is -\family typewriter -custom1.cc -\family default -. -\layout Comment - -example:custom1.cc -\layout LyX-Code-Sans - -#include -\newline -#include -\newline -#include -\newline -#include -\newline -#include -\newline - -\protected_separator - -\newline -sql_create_5 (stock, -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -// struct name, -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - 1, 5, -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -// I'll explain these latter -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - string, item, -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -// type, id -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - int, num, -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - double, weight, -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - double, price, -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - Date, sdate) -\newline - -\protected_separator - -\newline -// this is calling a very complex macro which will create a custom -\newline -// struct "stock" which has the variables: -\newline -// -\protected_separator - -\protected_separator - string item -\newline -// -\protected_separator - -\protected_separator - -\protected_separator - int num -\newline -// -\protected_separator - -\protected_separator - -\protected_separator - ... -\newline -// -\protected_separator - -\protected_separator - -\protected_separator - Date sdate -\newline -// defined as well methods to help populate the class from a mysql row -\newline -// among other things that I'll get too in a latter example -\newline - -\protected_separator - -\newline -int main () { -\newline - -\protected_separator - try { -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -// its in one big try block -\newline - -\protected_separator - -\protected_separator - -\protected_separator - Connection con (use_exceptions); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - con.connect ("mysql_cpp_data"); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - Query query = con.query (); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - query << "select * from stock"; -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - vector < stock > res; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - query.storein (res); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // this is storing the results into a vector of the custom struct -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // "stock" which was created my the macro above. -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cout.setf (ios::left); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cout << setw (17) << "Item" -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << setw (4) << "Num" -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << setw (7) << "Weight" -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << setw (7) << "Price" -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << "Date" << endl -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << endl; -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // Now we we iterate through the vector using an iterator and -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // produce output similar to that using Row -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // Notice how we call the actual variables in i and not an index -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // offset. -\protected_separator - This is because the macro at the begging of the file -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // set up an *actual* struct of type stock which contains the -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // variables item, num, weight, price, and data. -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cout.precision(3); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - vector ::iterator i; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - for (i = res.begin (); i != res.end (); i++) { -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - cout << setw (17) << i->item.c_str () -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -// unfortunally the gnu string class does not respond to format -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -// modifers so I have to convert it to a conat char *. -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << setw (4) << i->num -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << setw (7) << i->weight -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << setw (7) << i->price -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << i->sdate -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << endl; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - } -\newline - -\protected_separator - -\protected_separator - -\protected_separator - return 0; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - } catch (BadQuery er){ // handle any connection -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - // or query errors that may come up -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cerr << "Error: " << er.error << endl; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - return -1; -\newline - -\protected_separator - -\newline - -\protected_separator - } catch (BadConversion er) { -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // we still need to cache bad conversions incase something goes -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // wrong when the data is converted into stock -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cerr << "Error: Tried to convert -\backslash -"" << er.data << " -\backslash -" to a -\backslash -"" -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << er.type_name << " -\backslash -"." << endl; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - return -1; -\newline - -\protected_separator - } -\newline -} -\layout Standard - -As you can see. - SSQLS are very powerful things. -\layout Subsection - -Adding Data -\layout Standard - -SSQLS can also be used to add data to a table. - The file name for this code is custom2.cc -\layout Comment - -example:custom2.cc -\layout LyX-Code-Sans - -#include -\newline -#include -\newline -#include -\newline -#include -\newline -#include "util.hh" -\newline -// util.hh/cc contains the print_stock_table function -\newline - -\protected_separator - -\newline -sql_create_5(stock, 1, 5, string, item, int, num, -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - double, weight, double, price, Date, sdate) -\newline - -\protected_separator - -\newline -int main() { -\newline - -\protected_separator - try { // its in one big try block -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - Connection con(use_exceptions); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - con.connect("mysql_cpp_data"); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - Query query = con.query(); -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - stock row; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // create an empty stock object -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - /* -\protected_separator - -\protected_separator - -\protected_separator - row.item = "Hot Dogs"; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - row.num = 100; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - row.weight = 1.5; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - row.price = 1.75; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - row.sdate = "1998-09-25"; */ -\newline - -\protected_separator - -\protected_separator - -\protected_separator - row.set("Hot Dogs", 100, 1.5, 1.75, "1998-09-25"); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // populate stock -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - query.insert(row); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // form the query to insert the row -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // the table name is the name of the struct by default -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cout << "Query : " << query.preview() << endl; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // show the query about to be executed -\newline - -\protected_separator - -\protected_separator - -\protected_separator - query.execute(); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // execute a query that does not return a result set -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - print_stock_table(query); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // now print the new table; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - } catch (BadQuery er) { -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cerr << "Error: " << er.error << endl; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - return -1; -\newline - -\protected_separator - } catch (BadConversion er) { -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cerr << "Error: Tried to convert -\backslash -"" << er.data << " -\backslash -" to a -\backslash -"" -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << er.type_name << " -\backslash -"." << endl; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - return -1; -\newline - -\protected_separator - } -\newline -} -\layout Standard - -That's all there is to it. - Because this example modifies the data you should run -\family typewriter -reset-db -\family default - after running the example code. -\layout Subsection - -Modifying Data -\layout Standard - -And it almost as easy to modify data with SSQLS. - The file name is custom3.cc. -\layout Comment - -example:custom3.cc -\layout LyX-Code-Sans - -#include -\newline -#include -\newline -#include -\newline -#include -\newline -#include "util.hh" -\newline -// util.hh/cc contains the print_stock_table function -\newline - -\protected_separator - -\newline -sql_create_5(stock, 1, 5, string, item, int, num, -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - double, weight, double, price, Date, sdate) -\newline - -\protected_separator - -\newline -int main() { -\newline - -\protected_separator - try { // its in one big try block -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - Connection con(use_exceptions); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - con.connect("mysql_cpp_data"); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - Query query = con.query(); -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - query << "select * from stock where item = -\backslash -"Hotdogs' Buns -\backslash -" "; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - Result res = query.store(); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - if (res.empty()) -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - throw BadQuery("Hotdogs' Buns not found in table, run reset-db"); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // here we are testing if the query was successful, if not throw a bad - query -\newline - -\protected_separator - -\protected_separator - -\protected_separator - stock row = res[0]; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // because there should only be one row in this query we don't -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // need to use a vector. -\protected_separator - Just store the first row directly in -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // "row". -\protected_separator - We can do this because one of the constructors for -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // stock takes a Row as an parameter. -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - stock row2 = row; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // Now we need to create a copy so that the replace query knows -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // what the original values are. -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - row.item = "Hotdog Buns"; // now change item -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - query.update(row2, row); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // form the query to replace the row -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // the table name is the name of the struct by default -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cout << "Query : " << query.preview() << endl; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // show the query about to be executed -\newline - -\protected_separator - -\protected_separator - -\protected_separator - query.execute(); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // execute a query that does not return a result set -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - print_stock_table(query); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // now print the new table; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - } catch (BadQuery er) { -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cerr << "Error: " << er.error << endl; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - return -1; -\newline - -\protected_separator - } catch (BadConversion er) { -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cerr << "Error: Tried to convert -\backslash -"" << er.data << " -\backslash -" to a -\backslash -"" -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << er.type_name << " -\backslash -"." << endl; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - return -1; -\newline - -\protected_separator - } -\newline -} -\layout Standard - -When you run the example you will notice that in the where clause only the - -\emph on -item -\emph default -field is checked for. - This is because SSQLS also also less-than-comparable. -\layout Standard - -Don't forget to run -\family typewriter -reset-db -\family default - after running the example. -\layout Subsection - -Less-Than-Comparable -\layout Standard - -SSQLS are can also be made less-than-comparable. - This means that they can be sorted and stored in sets as demonstrated in - the next example. - The file name is custom4.cc -\layout Comment - -example:custom4.cc -\layout LyX-Code-Sans - -#include -\newline -#include -\newline -#include -\newline -#include -\newline -#include -\newline - -\protected_separator - -\newline -sql_create_5(stock, -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - 1, // This number is used to make a SSQLS less-than-comparable. -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - // If this number is n then if the first n elements are the -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - // same the two SSQLS are the same. -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - // In this case if two two stock's "item" are the same then -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - // the two stock are the same. -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - 5, // this number should generally be the same as the number of -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - // elements in the list unless you have a good reason not to. -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - string,item, -\protected_separator - int,num, -\protected_separator - double,weight, -\protected_separator - double,price, -\protected_separator - Date,sdate) -\newline - -\protected_separator - -\newline -int main() { -\newline - -\protected_separator - try { // its in one big try block -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - Connection con(use_exceptions); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - con.connect("mysql_cpp_data"); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - Query query = con.query(); -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - query << "select * from stock"; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - set res; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - query.storein(res); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // here we are storing the elements in a set not a vector. -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cout.setf (ios::left); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cout << setw (17) << "Item" -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << setw (4) << "Num" -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << setw (7) << "Weight" -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << setw (7) << "Price" -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << "Date" << endl -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << endl; -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // Now we we iterate through the set. -\protected_separator - Since it is a set the list will -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // naturally be in order. -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - set::iterator i; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cout.precision(3); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - for (i = res.begin (); i != res.end (); i++) { -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - cout << setw (17) << i->item.c_str () -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << setw (4) << i->num -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << setw (7) << i->weight -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << setw (7) << i->price -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << i->sdate -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << endl; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - } -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - i = res.find(stock("Hamburger Buns")); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - if (i != res.end()) -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - cout << "Hamburger Buns found. -\protected_separator - Currently " << i->num << " in stock. -\backslash -n"; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - else -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - cout << "Sorry no Hamburger Buns found in stock -\backslash -n"; -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // Now we are using the set's find method to find out how many -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // Hamburger Buns are in stock. -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - return 0; -\newline - -\protected_separator - -\newline - -\protected_separator - } catch (BadQuery er) { -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cerr << "Error: " << er.error << endl; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - return -1; -\newline - -\protected_separator - } catch (BadConversion er) { -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cerr << "Error: Tried to convert -\backslash -"" << er.data << " -\backslash -" to a -\backslash -"" -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << er.type_name << " -\backslash -"." << endl; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - return -1; -\newline - -\protected_separator - } -\newline -} -\layout Subsection - -And There's More -\layout Standard - -This is only scratching the surface of what SSQLS can do for more information - see the chapter on them ( -\begin_inset LatexCommand \ref{SSQLS} - -\end_inset - -). -\layout Section - -Template Queries -\layout Standard - -Another powerful feature of Mysql++ is being able to set up template queries. - The following example demonstrates how to use them. - This code is the actual code used to set up and/or reset the sample database. - It can be found under reset-db.cc. - I hope to come up with some better examples soon. -\layout Comment - -example:reset-db.cc -\layout LyX-Code-Sans - -#include -\newline -#include -\newline - -\protected_separator - -\newline -int main (int argc, char *argv[]) { -\newline - -\protected_separator - Connection connection(use_exceptions); -\newline - -\protected_separator - try { // the entire main block is one big try block; -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - if (argc == 1) connection.connect(""); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - else if (argc == 2) connection.connect("",argv[1]); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - else if (argc == 3) connection.connect("",argv[1],argv[2]); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - else if (argc <= 4) connection.connect("",argv[1],argv[2],argv[3]); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // create a new object and connect based on any (if any) arguments -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // passed to main(); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - try { -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - connection.select_db("mysql_cpp_data"); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - } catch (BadQuery er) { -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - // if it couldn't connect to the database assume that it doesn't exist -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - // and try created it. -\protected_separator - If that does not work exit with an error. -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - connection.create_db("mysql_cpp_data"); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - connection.select_db("mysql_cpp_data"); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - } -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - Query query = connection.query(); -\protected_separator - // create a new query object -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - try { // ignore any errors here -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - // I hope to make this simpler soon -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - query.execute("drop table stock"); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - } catch (BadQuery er) {} -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - query << "create table stock -\protected_separator - (item char(20) not null, num smallint," -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - << "weight double, price double, sdate date)"; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - query.execute(RESET_QUERY); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // send the query to create the table and execute it. -\protected_separator - The -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // RESET_QUERY tells the query object to reset it self after -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // execution -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - query << "insert into %5:table values (%0q, %1q, %2, %3, %4q)"; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - query.parse(); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // set up the template query I will use to insert the data. -\protected_separator - The -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // parse method call is important as it is what lets the query -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // know that this is a template and not a literal string -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - query.def["table"] = "stock"; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // This is setting the parameter named table to stock. -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - query.execute ("Hamburger Buns", 56, 1.25, 1.1, "1998-04-26"); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - query.execute ("Hotdogs' Buns" -\protected_separator - -\protected_separator - ,65, 1.1 , 1.1, "1998-04-23"); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - query.execute ("Dinner Roles" -\protected_separator - , 75, -\protected_separator - .95, .97, "1998-05-25"); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - query.execute ("White Bread" -\protected_separator - -\protected_separator - , 87, 1.5, 1.75, "1998-09-04"); -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // The last parameter "table" is not specified here. -\protected_separator - Thus -\newline - -\protected_separator - -\protected_separator - -\protected_separator - // the default value for "table" is used which is "stock". -\newline - -\protected_separator - -\newline - -\protected_separator - } catch (BadQuery er) { // handle any errors that may come up -\newline - -\protected_separator - -\protected_separator - -\protected_separator - cerr << "Error: " << er.error << endl; -\newline - -\protected_separator - -\protected_separator - -\protected_separator - return -1; -\newline - -\protected_separator - } -\newline -} -\newline - -\protected_separator - -\layout Chapter - -Class Reference -\layout Standard - -This chapter documents all of the classes that are meant to be used. - If it is not documented here -\series bold -don't use it -\series default - because it is a internal method or class meant to only be used by other - related classes. -\layout Comment - -Begin Class Ref -\layout Standard - - -\begin_inset LatexCommand \label{SQLQuery} - -\end_inset - - -\begin_inset LatexCommand \label{SQLQueryParms} - -\end_inset - - -\layout Comment - -End Class Ref -\layout Section - -Manipulators -\layout Standard - -The following manipulators modify only the next item to the right of it - in an -\family typewriter -<< -\family default - chain. - They can be used with any ostream (which includes -\series bold -SQLQuery -\series default - and -\series bold -Query -\series default - because they are also ostreams) or -\series bold -SQLQueryParms -\series default -. - When used with -\series bold -SQLQueryParms -\series default - they will override any settings set by the Template Query for that particular - item. -\layout Description - -quote Quote and escape the next item. - Can be used with -\series bold -ostream -\series default - or -\series bold -SQLQueryParms -\series default -. - -\layout Description - -quote_only Quote but don't escape the next item. - Can be used with -\series bold -ostream -\series default - or -\series bold -SQLQueryParms -\series default -. - -\layout Description - -quote_only_double Quote, but don't escape the next item, with `` instead - of '. - -\layout Description - -escape Escape the next item. - -\layout Description - -do_nothing Does exactly what it says nothing. - Used as a dummy manipulator when you are required to use some manipulator. - When used with -\series bold -SQLQueryParms -\series default - it will make sure that it does not get formatted in any way overriding - any setting set by the template query. - -\layout Description - -ignore Only valid when used with -\series bold -SQLQueryParms -\series default -. - Like -\series bold -do_nothing -\series default - however this one will not override formatting set by the template query, - thus it is ignored. - -\layout Chapter - -Template Queries -\layout Standard - -The idea of template queries is too provide a query with replaceable parameters - that can be changed between query calls with out having to reform the queries. -\layout Section - -Setting Them Up -\layout Standard - -To set up a template query simply enter the query like it is a normal query. - For example: -\layout LyX-Code - -query << "select (%2:field1, %3:field2) from stock where %1:wheref = %q0:what" -\layout Standard - -And then execute the Query::parse() method. - For example: -\layout LyX-Code - -query.parse() -\layout Section - -Template Format -\begin_inset LatexCommand \label{template format} - -\end_inset - - -\layout Standard - -An example template looks like this -\layout LyX-Code - -select (%2:field1, %3:field2) from stock where %1:wheref = %q0:what -\layout Standard - -The numbers represent the element number in -\series bold -SQLQueryParms -\series default - (see the next section). - -\layout Standard - -The format of the substation parameter is: -\layout LyX-Code - -%(modifier)##(:name)(:) -\layout Standard - -Where Modifier can be any one of the following: -\layout Description - -% Print an actual "%" -\layout Description - -"" "" means nothing. - Don't quote or escape no matter what. - -\layout Description - -q This will quote and escape it using mysql_escape_string if it is a string - or char *, or another Mysql specific types that needs to be quoted. - -\layout Description - -Q Quote but don't escape based on the same rules. - This can save a bit of time if you know the strings will never need quoting - -\layout Description - -r Always quote and escape even if it is a number. - -\layout Description - -R Always quote but don't escape even if it is a number. - -\layout Standard - -## represents a number up to two digits -\layout Standard - -``:name'' is for an optional name which aids in filling SQLQueryParms. - Name can contain any alpha-numeric characters or the underscore. - If you use name it must be proceeded by non-alpha-numeric charter. - If this is not the case add a column after the name. - If you need to represent an actual colon after the name follow the name - by two-columns. - The first one will end the name and the second one won't be processed. - -\layout Section - -Setting the Parameters -\layout Standard - -The parameters can either be set when the query is executed or ahead of - time by using default parameters. -\layout Subsection - -At Execution Time -\layout Standard - -To specify the parameters when you want to execute a query simply use -\series bold -Query::store(const SQLString &parm0, [..., const SQLString &parm11]) -\series default - (or -\series bold -Query::use -\series default - or -\series bold -Query::execute -\series default -). - Where -\series bold -parm0 -\series default - corresponds to parameter number 0, etc. - You may specify from 1 to 12 different parameters. - For example: -\layout LyX-Code - -Result res = query.store("Dinner Roles", "item", "item", "price") -\layout Standard - -with the template query provided in section -\begin_inset LatexCommand \ref{template format} - -\end_inset - - would produce: -\layout LyX-Code - -select (item, price) from stock where item = "Dinner Roles" -\layout Standard - -The reason for why I -\emph on -didn't -\emph default - make the template the more logical: -\layout LyX-Code - -select (%0:field1, %1:field2) from stock where %2:wheref = %q3:what -\layout Standard - -will become apparent shortly. -\layout Subsection - -Using Defaults -\layout Standard - -You can also set the parameters one at a time by means of the public data - member -\series bold -def -\series default -. - To change the values of the -\series bold -def -\series default - simply use the subscript operator. - You can refer to the parameters either by number or by name. - For example: -\layout LyX-Code - -query.def[0] = "Dinner Roles"; -\newline -query.def[1] = "item"; -\newline -query.def[2] = "item"; -\newline -query.def[3] = "price"; -\layout Standard - -and -\layout LyX-Code - -query.def["what"] = "Dinner Roles"; -\newline -query.def["wheref"] = "item"; -\newline -query.def["field1"] = "item"; -\newline -query.def["field2"] = "price"; -\layout Standard - -would both have the same effect. -\layout Standard - -Once all the parameters are set simply execute as you would have executed - the query before you knew about template queries. - For example: -\layout LyX-Code - -Result res = query.store() -\layout Subsection - -Combining the Two -\layout Standard - -You can also combine the use of setting the parameters at execution time - and setting them by use of the -\series bold -def -\series default - object by simply using the extended form of -\series bold -Query::store -\series default - (or -\series bold -use -\series default - or -\series bold -execute -\series default -) without all of necessary parameters specified. - For example: -\layout LyX-Code - -query.def["field1"] = "item"; -\newline -query.def["field2"] = "price"; -\newline -Result res1 = query.store("Hamburger Buns", "item"); -\newline -Result res2 = query.store(1.25, "price"); -\layout Standard - -Would store the query: -\layout LyX-Code - -select (item, price) from stock where item = "Hamburger Buns" -\layout Standard - -for -\family typewriter - res1 -\family default -and -\layout LyX-Code - -select (item, price) from stock where price = 1.25 -\layout Standard - -for -\family typewriter -res2 -\family default -. -\layout Standard - -Because the extended form of -\series bold -Query::store -\series default - can only effect the beginning (by number not by location) parameters the - more logical template query: -\layout LyX-Code - -select (%0:field1, %1:field2) from stock where %2:wheref = %q3:what -\layout Standard - -would -\emph on -not -\emph default -of worked in this case. - Thus the more twisted ordering of -\layout LyX-Code - -select (%2:field1, %3:field2) from stock where %1:wheref = %q0:what -\layout Standard - -was needed so that we can specify -\series bold -wheref -\series default - and -\series bold -what -\series default - each time. -\layout Standard - -One thing to watch out for, however, is that -\series bold -Query::store(const char* q) -\series default - is also defined for executing the query -\family typewriter -q -\family default -. - For this reason when you use the -\series bold -Query::store -\series default - (or -\series bold -use -\series default -, or -\series bold -execute -\series default -) with only one item and that item is a -\series bold -const char* -\series default - you need to explicitly convert it into a SQLString. - For example: -\layout LyX-Code - -Result res = query.store(SQLString("Hamburger Buns")). -\layout Subsection - -Error Handling -\layout Standard - -If for some reason you did not specify all the parameters when executing - the query -\emph on -and -\emph default - the remaining parameters do not have there values set via -\family typewriter -def -\family default - the query object will throw a -\series bold -SQLQueryNEParms -\series default - object. - In which case you you can find out what happened by checking the value - of -\series bold -SQLQueryNEParms::string -\series default -. - -\layout Standard - -For example: -\layout LyX-Code - -query.def["field1"] = "item"; -\newline -query.def["field2"] = "price"; -\newline -Result res = query.store(1.25); -\layout Standard - -would throw -\series bold -SQLQueryNEParms -\series default - because the -\family typewriter -wheref -\family default - is not specified. -\layout Standard - -In theory this exception should never be thrown. - If the exception is thrown it probably a logic error on you part. - (Like in the above example) -\layout Subsection - -More Advanced Stuff -\layout Standard - -To be written. - However, for now see the class -\series bold -SQLQuery -\series default - ( -\begin_inset LatexCommand \ref{SQLQuery} - -\end_inset - -) and -\series bold -SQLQueryParms -\series default - ( -\begin_inset LatexCommand \ref{SQLQueryParms} - -\end_inset - -) for more information. -\layout Chapter - -Specialized SQL Structures -\begin_inset LatexCommand \label{SSQLS} - -\end_inset - - -\layout Standard - -The Specialized SQL Structures (SSQLS) allows you create structures to hold - data for mysql queries with extra functionality to make your life easier. - These structures are in no way related to any Standard Template Library - (STL) type of containers. - These structures are exactly that -\series bold -structs -\series default -. - Each member item is stored with a unique name within the structure. - You can in no way use STL algorithms are anything else STL to work with - the individual structures. - However you CAN use these structures as the -\series bold -value_type -\series default - for STL containers. - (They would be pretty useless if you couldn't.) -\layout Section - -sql_create_basic -\layout Standard - -The following command will create a basic mysql query for use with the - sample database. - -\layout LyX-Code - -sql_create_basic_5(stock, -\protected_separator -0, -\protected_separator -0, -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -string, -\protected_separator -item, -\protected_separator -// -\protected_separator -type, -\protected_separator -id, -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -int, -\protected_separator -num, -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -double, -\protected_separator -weight, -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -double, -\protected_separator -price, -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -MysqlDate, -\protected_separator -date) -\protected_separator - -\layout Standard - -This will set up the following structure: -\layout LyX-Code - -struct -\protected_separator -stock -\protected_separator -{ -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator -stock -\protected_separator -() -\protected_separator -{} -\protected_separator - -\newline - -\protected_separator - -\protected_separator -stock -\protected_separator -(const MysqlRow -\protected_separator -&row); -\newline - -\protected_separator - -\protected_separator -set (const MysqlRow &row); -\newline - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator -string -\protected_separator -item; -\protected_separator - -\newline - -\protected_separator - -\protected_separator -int -\protected_separator -num; -\protected_separator - -\newline - -\protected_separator - -\protected_separator -double -\protected_separator -weight; -\protected_separator - -\newline - -\protected_separator - -\protected_separator -double -\protected_separator -price; -\protected_separator - -\newline - -\protected_separator - -\protected_separator -MysqlDate -\protected_separator -date; -\protected_separator - -\newline -}; -\protected_separator - -\layout Standard - -As you can see this is nothing fancy. - The main advantage of this simple structure is the -\series bold -stock (MysqlRow &row) -\series default - constructor which allows you to easily populate a vector of stocks like - so: -\layout LyX-Code - -vector -\protected_separator -result; -\protected_separator - -\protected_separator - -\newline -query.storein(result); -\protected_separator - -\layout Standard - -That's all there is two it. - The requirements are that the query returns elements in the same order - as you specified them in the custom structure. - -\layout Standard - -The general format is: -\layout LyX-Code - -sql_create_basic_#(NAME, -\protected_separator -0, -\protected_separator -0, -\protected_separator -TYPE1, -\protected_separator -ITEM1, -\protected_separator -... -\protected_separator -TYPE#, -\protected_separator -ITEM#) -\protected_separator - -\protected_separator - -\layout Standard - -Where # is the number of valuables in the vector, NAME is the name of the - structure you wish to create, and TYPE1 is the type name for first item - and ITEM1 is the valuables name for the first item etc.. - -\layout Section - -sql_create_basic with compare -\layout Standard - -You can also make the structure comparable by changing the first 0 in the - previous example to a non zero number. - This number, lets call it n, will tell c++ that if the first n number - or the same then the two structures are the same. - -\layout Standard - -For example: -\layout LyX-Code - -sql_create_basic_5(stock, -\protected_separator -1, -\protected_separator -0, -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -string, -\protected_separator -item, -\protected_separator -// -\protected_separator -type, -\protected_separator -id, -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -int, -\protected_separator -num, -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -double, -\protected_separator -weight, -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -double, -\protected_separator -price, -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -MysqlDate, -\protected_separator -date) -\protected_separator - -\layout Standard - -will create a structure where only the item valuable is checked to see if - two different stocks are the same. - It also allows you to compare one structure to another based on the value - of item. - (If n is greater than one it will compare the structures in a Lexicographic - order. - For example if it was 2 it would first compare -\family typewriter -item -\family default - and if item was the same it would then compare -\family typewriter -num -\family default -. - If num was the same it would declare the two structures the same.) -\layout Standard - -In addition what the previous example defines it also defines the following: - -\layout LyX-Code - -struct -\protected_separator -stock -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator -... -\protected_separator - -\newline - -\protected_separator - -\protected_separator -stock -\protected_separator -(const -\protected_separator -string -\protected_separator -&p1); -\newline - -\protected_separator - -\protected_separator -set (const string &p1); -\newline - -\protected_separator - -\protected_separator -bool -\protected_separator -operator -\protected_separator -== -\protected_separator -(const -\protected_separator -stock -\protected_separator -&other) -\protected_separator -const; -\protected_separator - -\newline - -\protected_separator - -\protected_separator -bool -\protected_separator -operator -\protected_separator -!= -\protected_separator -(const -\protected_separator -stock -\protected_separator -&other) -\protected_separator -const; -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator -bool -\protected_separator -operator -\protected_separator -> -\protected_separator -(const -\protected_separator -stock -\protected_separator -&other) -\protected_separator -const; -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator -bool -\protected_separator -operator -\protected_separator -< -\protected_separator -(const -\protected_separator -stock -\protected_separator -&other) -\protected_separator -const; -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator -bool -\protected_separator -operator -\protected_separator ->= -\protected_separator -(const -\protected_separator -stock -\protected_separator -&other) -\protected_separator -const; -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator -bool -\protected_separator -operator -\protected_separator -<= -\protected_separator -(const -\protected_separator -stock -\protected_separator -&other) -\protected_separator -const; -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator -int -\protected_separator -cmp -\protected_separator -(const -\protected_separator -stock -\protected_separator -&other) -\protected_separator -const; -\protected_separator - -\newline - -\protected_separator - -\protected_separator -int -\protected_separator -compare -\protected_separator -(const -\protected_separator -stock -\protected_separator -&other) -\protected_separator -const; -\protected_separator - -\newline -} -\protected_separator - -\newline - -\protected_separator - -\newline -int -\protected_separator -compare -\protected_separator -(const -\protected_separator -stock -\protected_separator -&x, -\protected_separator -const -\protected_separator -stock -\protected_separator -&y); -\protected_separator - -\layout Standard - -int compare (const stock &x, const stock &y) compares x to y and return - <0 if x < y, 0 if x = y, and >0 if x > y. - stock::cmp and stock::compare are the same thing as compare(*this, other). - -\layout Standard - -stock::stock is a constructor that will set item to p1 and leave the other - variables undefined. - This is useful for creating temporary objects to use for comparisons like - x <= stock("Hotdog"). - -\layout Standard - -Because -\series bold -stock -\series default - is now less-then-comparable you can store the query results in a set: -\layout LyX-Code - -set -\protected_separator -result; -\protected_separator - -\protected_separator - -\newline -query.storein(result); -\protected_separator - -\layout Standard - -And you can now use it like any other set, for example: -\layout LyX-Code - -cout -\protected_separator -<< -\protected_separator -result.lower_bound(stock("Hamburger"))->item -\protected_separator -<< -\protected_separator -endl; -\protected_separator - -\protected_separator - -\layout Standard - -will return the first item that begins with Hamburger. - -\layout Standard - -You can also now use it will any STL algorithm that require the values to - be less-then-comparable. - -\layout Standard - -The general format so far is: -\layout LyX-Code - -sql_create_base_#(NAME, -\protected_separator -CMP, -\protected_separator -0, -\protected_separator -TYPE1, -\protected_separator -ITEM1, -\protected_separator -... -\protected_separator -TYPE#, -\protected_separator -ITEM#) -\protected_separator - -\protected_separator - -\layout Standard - -where CMP is that the number that tells c++ that if the first cmp variables - are the same then the two structures are the same. - -\layout Section - -sql_create_basic with Additional Constructor -\layout Standard - -The last zero in the last example if for creating another constructor. - Let this zero be m then it will create a constructor which will populate - the first n variables. - For example: -\layout LyX-Code - -sql_create_basic_5(stock, -\protected_separator -1, -\protected_separator -5, -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -string, -\protected_separator -item, -\protected_separator -// -\protected_separator -type, -\protected_separator -id, -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -int, -\protected_separator -num, -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -double, -\protected_separator -weight, -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -double, -\protected_separator -price, -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -MysqlDate, -\protected_separator -date) -\protected_separator - -\layout Standard - -will also define: -\layout LyX-Code - -struct -\protected_separator -stock -\protected_separator -{ -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator -... -\protected_separator - -\newline - -\protected_separator - -\protected_separator -stock(const -\protected_separator -string&, -\protected_separator -const -\protected_separator -int&, -\protected_separator -const -\protected_separator -double&, -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -const -\protected_separator -double&, -\protected_separator -const -\protected_separator -MysqlDate&); -\protected_separator - -\newline - -\protected_separator - -\protected_separator -set(const -\protected_separator -string&, -\protected_separator -const -\protected_separator -int&, -\protected_separator -const -\protected_separator -double&, -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -const -\protected_separator -double&, -\protected_separator -const -\protected_separator -MysqlDate&); -\protected_separator - -\newline -} -\protected_separator - -\layout Section - -sql_create_basic General Format -\layout Standard - -Thus the general format for sql_create_basic is -\layout LyX-Code - -sql_create_basic_#(NAME, -\protected_separator -CMP, -\protected_separator -CNST, -\protected_separator -TYPE1, -\protected_separator -ITEM1, -\protected_separator -..., -\protected_separator -TYPE#, -\protected_separator -ITEM#) -\protected_separator - -\protected_separator - -\layout Standard - -Where: -\layout Itemize - -# is the number of valuables in the vector -\layout Itemize - -NAME is the name of the structure you wish to create -\layout Itemize - -CMP is the number that tells c++, if not set to 0, that if the first cmp - variables are the same then the two structures are the same. - -\layout Itemize - -CNST is the number, if not set to 0, that will create a constructor which - will populate the first n variables. - -\layout Itemize - -TYPE1 is the type name for first item and ITEM1 is the valuables name for - the first item etc.. - -\layout Section - -sql_create_basic_c_order -\layout Standard - -You can also specify an alternate order for when mysql populates the structure. - For example: -\layout LyX-Code - -sql_create_basic_c_order_5(stock, -\protected_separator -2, -\protected_separator -5, -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -MysqlDate, -\protected_separator -date, -\protected_separator -5, -\protected_separator -// -\protected_separator -type, -\protected_separator -id, -\protected_separator -order -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -double, -\protected_separator -price, -\protected_separator -4, -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -string, -\protected_separator -item, -\protected_separator -1, -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -int, -\protected_separator -num, -\protected_separator -2, -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -double, -\protected_separator -weight, -\protected_separator -3) -\protected_separator - -\layout Standard - -This will create a similar structure as in the previous example except that - that the order of the data items will be different and c++ will use the - first two items to compare with (date, price). - However because a custom order is specified you can use the same query - to populate the set. - It will fill -\family typewriter -date -\family default - with the first 5th item of the query result set, -\family typewriter -price -\family default - with the 4th, etc... - -\layout Section - -sql_create_basic_c_order General Format -\layout Standard - -Thus the general format for sql_create_basic is -\layout LyX-Code - -sql_create_basic_c_order_# -\protected_separator -(NAME, -\protected_separator -CMP, -\protected_separator -CNST, -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -TYPE1, -\protected_separator -ITEM1, -\protected_separator -ORDER1, -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -... -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -TYPE#, -\protected_separator -ITEM#, -\protected_separator -ORDER#) -\protected_separator - -\layout Standard - -Where: -\layout Itemize - -# is the number of valuables in the vector -\layout Itemize - -NAME is the name of the structure you wish to create -\layout Itemize - -CMP is the number that tells c++, if not set to 0, that if the first cmp - variables are the same then the two structures are the same. - -\layout Itemize - -CNST is the number, if not set to 0, that will create a constructor which - will populate the first n variables. - -\layout Itemize - -TYPE1 is the type name for first item, ITEM1 is the valuable name for the - first item, ORDER1 is the order number for the first item ...etc... - -\layout Section - -sql_create -\layout Standard - -In addition to the basic structures you can set up enhanced structures that - also have methods defined to aid in the creation of queries and in the - insertion of data in tables. - -\layout Standard - -For example: -\layout LyX-Code - -sql_create_5(stock, -\protected_separator -1, -\protected_separator -5, -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -string, -\protected_separator -item, -\protected_separator -// -\protected_separator -type, -\protected_separator -id, -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -int, -\protected_separator -num, -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -double, -\protected_separator -weight, -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -double, -\protected_separator -price, -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -MysqlDate, -\protected_separator -date) -\protected_separator - -\layout Standard - -which will, in addition to that which is defined in sql_create_basic with - Additional Constructor, define the equivalent to: -\layout LyX-Code - -struct -\protected_separator -stock -\protected_separator -{ -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator -... -\protected_separator - -\newline - -\protected_separator - -\protected_separator -static -\protected_separator -char -\protected_separator -*names[]; -\protected_separator - -\newline - -\protected_separator - -\protected_separator -static -\protected_separator -char -\protected_separator -*table; -\protected_separator - -\newline - -\protected_separator - -\protected_separator -template -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator -stock_value_list -\protected_separator -value_list(cchar -\protected_separator -*d -\protected_separator -= -\protected_separator -",", -\protected_separator - -\protected_separator -// -\protected_separator -basic -\protected_separator -form -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -Manip -\protected_separator -m -\protected_separator -= -\protected_separator -mysql_quote) -\protected_separator -const; -\protected_separator - -\newline - -\protected_separator - -\protected_separator -template -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator -stock_field_list -\protected_separator -field_list(cchar -\protected_separator -*d -\protected_separator -= -\protected_separator -",", -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -Manip -\protected_separator -m -\protected_separator -= -\protected_separator -mysql_do_nothing) -\protected_separator -const; -\protected_separator - -\newline - -\protected_separator - -\protected_separator -template -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator -stock_equal_list -\protected_separator -equal_list(cchar -\protected_separator -*d -\protected_separator -= -\protected_separator -",", -\layout LyX-Code - - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -cchar *e = " = ", -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -Manip -\protected_separator -m -\protected_separator -= -\protected_separator -mysql_quote, -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -) -\protected_separator -const; -\protected_separator - -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator -template -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -// -\protected_separator -bool -\protected_separator -form -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator -stock_cus_value_list -\protected_separator -value_list([cchar -\protected_separator -*d, -\protected_separator -[Manip -\protected_separator -m,] -\protected_separator -] -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -bool -\protected_separator -i1, -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -bool -\protected_separator -i2 -\protected_separator -= -\protected_separator -false, -\protected_separator -... -\protected_separator -, -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -bool -\protected_separator -i5 -\protected_separator -= -\protected_separator -false) -\protected_separator -const; -\protected_separator - -\newline - -\protected_separator - -\protected_separator -template -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -// -\protected_separator -list -\protected_separator -form -\protected_separator - -\newline - -\protected_separator - -\protected_separator -stock_cus_value_list -\protected_separator -value_list([cchar -\protected_separator -*d, -\protected_separator -[Manip -\protected_separator -m,] -\protected_separator -] -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -stock_enum -\protected_separator -i1, -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -stock_enum -\protected_separator -i2 -\protected_separator -= -\protected_separator -stock_NULL, -\protected_separator -..., -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -stock_enum -\protected_separator -i5 -\protected_separator -= -\protected_separator -stock_NULL) -\protected_separator -const; -\protected_separator - -\newline - -\protected_separator - -\protected_separator -template -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -// -\protected_separator -vector -\protected_separator -form -\protected_separator - -\newline - -\protected_separator - -\protected_separator -stock_cus_value_list -\protected_separator -value_list([cchar -\protected_separator -*d, -\protected_separator -[Manip -\protected_separator -m,] -\protected_separator -] -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -vector -\protected_separator -*i) -\protected_separator -const; -\protected_separator - -\newline - -\protected_separator - -\newline - -\protected_separator - -\protected_separator -...(The -\protected_separator -logical -\protected_separator -equivalent -\protected_separator -for -\protected_separator -field_list -\protected_separator -and -\protected_separator -equal_list)... -\protected_separator - -\newline -}; -\protected_separator - -\layout Standard - - -\series bold -value_list() -\series default - returns a special class that when used with the << operator with an ostream - on the left will return a comma separated list with values properly quoted - and escaped when needed. - -\layout Standard - - -\series bold -field_list() -\series default - return a special class than does the same thing but returns a list of - fields that the structure holds which in this case is the same thing as - the valuable names. - The field names are not escaped or quoted -\layout Standard - - -\series bold -equal_list() -\series default - returns a comma separated list with the format -\series bold -field name = value -\series default -. - The field name is not quoted or escaped and value is escaped or quoted - as needed. - -\layout Standard - -For example: -\layout LyX-Code - -stock -\protected_separator -s("Dinner -\protected_separator -Roles",75,0.95,0.97,"1998-05-25"); -\protected_separator - -\protected_separator - -\newline -cout -\protected_separator -<< -\protected_separator -"Value -\protected_separator -List: -\protected_separator -" -\protected_separator -<< -\protected_separator -s.comma_list() -\protected_separator -<< -\protected_separator -endl; -\protected_separator - -\newline -cout -\protected_separator -<< -\protected_separator -"Field -\protected_separator -List: -\protected_separator -" -\protected_separator -<< -\protected_separator -s.field_list() -\protected_separator -<< -\protected_separator -endl; -\protected_separator - -\newline -cout -\protected_separator -<< -\protected_separator -"Equal -\protected_separator -List: -\protected_separator -" -\protected_separator -<< -\protected_separator -s.equal_list() -\protected_separator -<< -\protected_separator -endl; -\protected_separator - -\layout Standard - -Would return something like (with a little extra hand formating): -\layout LyX-Code - -Value -\protected_separator -List: -\protected_separator -'Dinner -\protected_separator -Roles',75,0.95,0.97,'1998-05-25' -\protected_separator - -\protected_separator - -\newline -Field -\protected_separator -List: -\protected_separator -item,num,weight,price,date -\protected_separator - -\newline -Equal -\protected_separator -List: -\protected_separator -item -\protected_separator -= -\protected_separator -'Dinner -\protected_separator -Roles',num -\protected_separator -= -\protected_separator -75,weight -\protected_separator -= -\protected_separator -0.95, -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -price -\protected_separator -= -\protected_separator -0.97,date -\protected_separator -= -\protected_separator -'1998-05-25' -\protected_separator - -\layout Standard - -A combination of the field and value list can be used for insert or replace - queries. - For example: -\layout LyX-Code - -query -\protected_separator -<< -\protected_separator -"insert -\protected_separator -into -\protected_separator -stock -\protected_separator -(" -\protected_separator -<< -\protected_separator -s.field_list() -\protected_separator -") -\protected_separator -values -\protected_separator -" -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -<< -\protected_separator -s.value_list(); -\protected_separator - -\layout Standard - -will insert -\family typewriter -s -\family default - into table stock. - -\layout Standard - -You can also use SQLQuery::insert or SQLQuery::replace (and thus Query::insert - or Query::replace) as a short cut to accomplish the same task like so: - -\layout LyX-Code - -query.insert(s); -\layout Standard - -It will use s.table for the table name which defaults to the name of the - structure. - -\layout Standard - -You can also specify an different delimiter "d". - If none is specified it defaults to ",". - With this you can use the delimiter " AND " for equal_list to aid in update - and select queries. - For example: -\layout LyX-Code - -stock -\protected_separator -s2 -\protected_separator -= -\protected_separator -s; -\protected_separator - -\protected_separator - -\protected_separator - -\newline -s2.item -\protected_separator -= -\protected_separator -"6 -\protected_separator -Dinner -\protected_separator -Roles"; -\protected_separator - -\newline -query -\protected_separator -<< -\protected_separator -"UPDATE -\protected_separator -TABLE -\protected_separator -stock -\protected_separator -SET -\protected_separator -" -\protected_separator -<< -\protected_separator -s2.equal_list() -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -<< -\protected_separator -" -\protected_separator -WHERE -\protected_separator -" -\protected_separator -<< -\protected_separator -s.equal_list(" -\protected_separator -AND -\protected_separator -"); -\protected_separator - -\layout Standard - -would produce the query: -\layout LyX-Code - -UPDATE -\protected_separator -TABLE -\protected_separator -stock -\protected_separator -SET -\protected_separator -item -\protected_separator -= -\protected_separator -'6 -\protected_separator -Dinner -\protected_separator -Roles',num -\protected_separator -= -\protected_separator -75,weight -\protected_separator -= -\protected_separator -0.95, -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -price -\protected_separator -= -\protected_separator -0.97,date -\protected_separator -= -\protected_separator -'1998-05-25' -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -WHERE -\protected_separator -item -\protected_separator -= -\protected_separator -'Dinner -\protected_separator -Roles' -\protected_separator -AND -\protected_separator -num -\protected_separator -= -\protected_separator -75 -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -AND -\protected_separator -weight -\protected_separator -= -\protected_separator -0.95 -\protected_separator -AND -\protected_separator -price -\protected_separator -= -\protected_separator -0.97 -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -AND -\protected_separator -date -\protected_separator -= -\protected_separator -'1998-05-25' -\protected_separator - -\layout Standard - -which will change the entree in the table so that item is now "6 Dinner - Roles" instead of "Dinner Roles" -\layout Standard - -You can use -\series bold -SQLQuery::update -\series default - (and thus -\series bold -Query::update -\series default -) as a short cut to accomplishing the same task like so: -\layout LyX-Code - -stock -\protected_separator -s2 -\protected_separator -= -\protected_separator -s; -\protected_separator - -\protected_separator - -\protected_separator - -\newline -s2.item -\protected_separator -= -\protected_separator -"6 -\protected_separator -Dinner -\protected_separator -Roles"; -\protected_separator - -\newline -query.update(s,s2); -\protected_separator - -\layout Standard - -Like -\series bold -SQLQuery::insert -\series default -, it will use s.table for the table name which defaults to the name of the - structure. - -\layout Standard - -You can also specify an different manipulator which will effect the way - c++ quotes or escapes the values. - This may be any valid stream manipulator that only effects the item to - the right of manipulator. - -\series bold -value_list -\series default - and -\series bold -equal_list -\series default - defaults to -\series bold -escape -\series default - and -\series bold -field_list -\series default - defaults to -\series bold -do_nothing -\series default -. - For -\series bold -equal_list -\series default - the manipulator only effects the -\series bold -value -\series default - part and not the -\series bold -field name -\series default - part. - -\layout Standard - -This can be useful creating exporting to a file where you don't want quotes - around strings for example. - -\layout LyX-Code - -table_out -\protected_separator -<< -\protected_separator -q.value_list(" -\backslash - -\protected_separator -t", -\protected_separator -mysql_escape) -\protected_separator -<< -\protected_separator -endl; -\layout Standard - -will append data to the file handle table_out. - -\layout Standard - -The three non-basic forms allow you to specify which items are returned. - For example: -\layout LyX-Code - -cout -\protected_separator -<< -\protected_separator -q.value_list(false,false,true,true,false) -\protected_separator -<< -\protected_separator -endl; -\protected_separator -//bool -\protected_separator -form -\protected_separator - -\protected_separator - -\newline -cout -\protected_separator -<< -\protected_separator -q.value_list(stock_weight, -\protected_separator -stock_price) -\protected_separator -<< -\protected_separator -endl; -\protected_separator - -\protected_separator - -\protected_separator -//list -\protected_separator -form -\protected_separator - -\layout Standard - -will both return: -\layout LyX-Code - -0.95,0.97 -\protected_separator - -\protected_separator - -\layout Standard - -The -\shape italic -bool form -\shape default - excepts boolean arguments where each true/false represents an wether to - show a valuable. - False means not to show it while true means to show it. - If you leave of some they are assumed to be false. - For example: -\layout LyX-Code - -cout -\protected_separator -<< -\protected_separator -q.value_list(false,false,true,true) -\protected_separator -<< -\protected_separator -endl; -\protected_separator - -\protected_separator - -\layout Standard - -is the same as the above example. - -\layout Standard - -The -\shape italic -list form -\shape default - allows you to specify which items to show. - An enum values are created for each valuable with the name of struct plus - the underscore character prefixed before it. - For example: item becomes stock_item. - -\layout Standard - -These forms can be useful is select queries. - For example: -\layout LyX-Code - -query -\protected_separator -<< -\protected_separator -"SELECT -\protected_separator -* -\protected_separator -FROM -\protected_separator -stock -\protected_separator -WHERE -\protected_separator -" -\protected_separator - -\layout LyX-Code - - -\protected_separator - -\protected_separator - -\protected_separator - << -\protected_separator -q.equal_list(" -\protected_separator -AND -\protected_separator -",stock_weight,stock_price); -\protected_separator - -\layout Standard - -would produce the query: -\layout LyX-Code - -SELECT -\protected_separator -* -\protected_separator -FROM -\protected_separator -stock -\protected_separator -WHERE -\protected_separator -weight=0.95 -\protected_separator -AND -\protected_separator -price=0.97 -\protected_separator - -\protected_separator - -\layout Standard - -which will select all rows from stock which have the same weight and price - as -\shape italic -q -\shape default -. - -\layout Standard - -The -\shape italic -vector form -\shape default - (not shown above) allows you to pass a boolean vector which is a time saver - if you use the some pattern more than once as it avoids having to create - the vector from the arguments each time. - If -\family typewriter -a -\family default - is a boolean vector then -\family typewriter -a[0] -\family default - will hold wether to include the first variable -\family typewriter -a[1] -\family default - the second etc... - For example: -\layout LyX-Code - -vector -\protected_separator -a; -\protected_separator - -\protected_separator - -\newline -a[0] -\protected_separator -= -\protected_separator -false; -\protected_separator -a[1] -\protected_separator -= -\protected_separator -false; -\protected_separator -a[2] -\protected_separator -= -\protected_separator -true; -\protected_separator -a[3] -\protected_separator -= -\protected_separator -true; -\protected_separator -a[4] -\protected_separator -= -\protected_separator -false; -\protected_separator - -\newline -query -\protected_separator -<< -\protected_separator -"SELECT -\protected_separator -* -\protected_separator -FROM -\protected_separator -stock -\protected_separator -WHERE -\protected_separator -" -\protected_separator -<< -\protected_separator -q.equal_list(" -\protected_separator -AND -\protected_separator -", -\protected_separator -a); -\protected_separator - -\layout Standard - -will produce the same query as in the above example. - -\layout Section - -sql_create_c_names -\layout Standard - -You can also specify alternate field names like so: -\layout LyX-Code - -sql_create_c_names_5(stock, -\protected_separator -1, -\protected_separator -5, -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -string, -\protected_separator -item, -\protected_separator -"item", -\protected_separator -// -\protected_separator -type, -\protected_separator -id, -\protected_separator -column -\protected_separator -name -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -int, -\protected_separator -num, -\protected_separator -"quantity", -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -double, -\protected_separator -weight, -\protected_separator -"weight", -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -double, -\protected_separator -price, -\protected_separator -"price" -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -MysqlDate, -\protected_separator -date, -\protected_separator -"shipment") -\protected_separator - -\layout Standard - -When -\series bold -field_list -\series default - or -\series bold -equal_list -\series default - is used it will use the given field names rather than the variable names - for example: -\layout LyX-Code - -stock -\protected_separator -s("Dinner -\protected_separator -Roles",75,0.95,0.97,"1998-05-25"); -\protected_separator - -\protected_separator - -\newline -cout -\protected_separator -<< -\protected_separator -"Field -\protected_separator -List: -\protected_separator -" -\protected_separator -<< -\protected_separator -s.field_list() -\protected_separator -<< -\protected_separator -endl; -\protected_separator - -\newline -cout -\protected_separator -<< -\protected_separator -"Equal -\protected_separator -List: -\protected_separator -" -\protected_separator -<< -\protected_separator -s.equal_list() -\protected_separator -<< -\protected_separator -endl; -\protected_separator - -\layout Standard - -Would return something like (with a little extra hand formating): -\layout LyX-Code - -Field -\protected_separator -List: -\protected_separator -item,quantity,weight,price,shipment -\protected_separator - -\protected_separator - -\newline -Equal -\protected_separator -List: -\protected_separator -item -\protected_separator -= -\protected_separator -'Dinner -\protected_separator -Roles',quantity -\protected_separator -= -\protected_separator -75,weight -\protected_separator -= -\protected_separator -0.95, -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -price -\protected_separator -= -\protected_separator -0.97,shipment -\protected_separator -= -\protected_separator -'1998-05-25' -\protected_separator - -\layout Section - -sql_create_c_names General Format -\layout Standard - -The general format is: -\layout LyX-Code - -sql_create_c_names_# -\protected_separator -(NAME, -\protected_separator -CMP, -\protected_separator -CNST, -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -TYPE1, -\protected_separator -ITEM1, -\protected_separator -NAME1, -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -... -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -TYPE#, -\protected_separator -ITEM#, -\protected_separator -NAME#) -\protected_separator - -\layout Standard - -where NAME1 is the name of the first field, etc. - Everything else is the same as it is the same as in sql_create_basic_c_order - General Format. - -\layout Section - -sql_create_c_order -\layout Standard - -As in sql_create_basic_c_order you may specify a custom order. - The general from is: -\layout LyX-Code - -sql_create_c_order_# -\protected_separator -(NAME, -\protected_separator -CMP, -\protected_separator -CNST, -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -TYPE1, -\protected_separator -ITEM1, -\protected_separator -ORDER1, -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -... -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -TYPE#, -\protected_separator -ITEM#, -\protected_separator -ORDER#) -\protected_separator - -\layout Standard - -where everything is the same as in sql_create_basic_c_order General Format. - -\layout Section - -sql_create_complete -\layout Standard - -You can also specify both a custom order and custom field names. - The general from is. - -\layout LyX-Code - -sql_create_complete_# -\protected_separator -(NAME, -\protected_separator -CMP, -\protected_separator -CNST, -\protected_separator - -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -TYPE1, -\protected_separator -ITEM1, -\protected_separator -NAME1, -\protected_separator -ORDER1, -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -... -\protected_separator - -\protected_separator - -\newline - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator - -\protected_separator -TYPE#, -\protected_separator -ITEM#, -\protected_separator -NAME#, -\protected_separator -ORDER#) -\protected_separator - -\layout Standard - -Where everything is the same as in sql_create_c_order General Format and - sql_create_c_names General Format. - -\layout Section - -Changing the table name -\layout Standard - -In order to avoid having even more forms I decided not to allow you to specify - a different table name in the actual macro call. - The table name is used by -\series bold -SQLQuery::insert -\series default -, -\series bold -replace -\series default -, and -\series bold -update -\series default -. - However you can easeally change the default table name, which is the same - as the struct name, by changing the reference -\series bold -NAME::table() -\series default - returns to a different -\series bold -const char * -\series default - For example: -\layout LyX-Code - -stock::table() -\protected_separator -= -\protected_separator -"in_stock" -\protected_separator - -\protected_separator - -\layout Standard - -Will change the table name to "in_stock" in the examples used through out - this guide. - -\layout Section - -Seeing the actual code -\layout Standard - -To see the actual code that the macro inserts use sql++pretty. - For example: -\layout LyX-Code - -sql++pretty -\protected_separator -< -\protected_separator -test.cc -\protected_separator -| -\protected_separator -less -\protected_separator - -\protected_separator - -\layout Section - -Adding functionality -\layout Standard - -The best way to add functionality is through inheritance. - Even though you could paste the code outputted from pretty.pl and modify - it this is not recommended because it won't reflect future enhancements. - -\layout Section - -Other notes -\layout Standard - -Macros are defined for structures with up to 25 items. - If you need more modify the underlying perl script custom.pl. - This perl script is used to generate the header file. - It in no way tries to parse C++ code. - -\layout Standard - -The header file that the script custom.pl creates is close to a meg. - However, please note that the 1 meg header file (custom-macros.hh) is NOTHING - but macros. - Therefor the compiler has to do very little work when reading is. - -\layout Standard - -Also, everything included by the macro call is done in such a way that you - can safely include the macro call in a header file and not have to worry - about duplicate function calls or anything of the like. - -\layout Chapter - -Long Names -\layout Standard - -By default the Mysql++ API uses both short names with out the -\series bold - Mysql -\series default - or -\series bold -mysql_ -\series default -prefix and long names with the -\series bold -Mysql -\series default - or -\series bold -mysql_ -\series default -prefix. - If this causes name problems define the macro -\series bold -MYSQL_NO_SHORT_NAMES -\series default - before including -\series bold -mysql++ -\series default -. - This will force the use of long names only. - The short and long names are mapped as follows: -\layout Standard -\added_space_top 0.3cm \added_space_bottom 0.3cm \align center \LyXTable -multicol5 -33 2 0 0 -1 -1 -1 -1 -1 1 0 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -1 0 0 0 -2 1 0 "" "" -2 1 1 "" "" -1 8 1 1 0 0 0 "" "" -1 8 1 1 0 0 0 "" "" -0 2 1 0 0 0 0 "" "" -0 2 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" -0 8 1 0 0 0 0 "" "" - - -\series bold -Short Name -\newline -Long Name -\series default - -\newline -BadQuery -\newline -MysqlBadQuery -\newline -Connection -\newline -MysqlConnection -\newline -ResNSel -\newline -ResNSel -\newline -ResUse -\newline -ResUse MysqlResUse -\newline -Result -\newline -MysqlRes -\newline -Field -\newline -MysqlField -\newline -Fields -\newline -MysqlFields -\newline -ResIter -\newline -MysqlResIter -\newline -ResultIter -\newline -MysqlResIter -\newline -Row -\newline -MysqlRow -\newline -MutableRow -\newline -MysqlMutableRow -\newline -FieldNames -\newline -MysqlFieldNames -\newline -Query -\newline -MysqlQuery -\newline -BadConversion -\newline -MysqlBadConversion -\newline -ColData -\newline -MysqlColData -\newline -MutableColData -\newline -MysqlMutableColData -\newline -quote -\newline -mysql_quote -\newline -quote_only -\newline -mysql_quote_only -\newline -quote_double_only -\newline -mysql_quote_double_only -\newline -escape -\newline -mysql_escape -\newline -do_nothing -\newline -mysql_do_nothing -\newline -ignore -\newline -mysql_ignore -\newline -Date -\newline -MysqDate -\newline -Time -\newline -MysqlTime -\newline -DateTime -\newline -MysqlDateTime -\newline -Set -\newline -MysqlSet -\newline -Null -\newline -MysqlNull -\newline -null_type -\newline -mysql_null_type -\newline -null -\newline -mysql_null -\newline -NullisNull -\newline -MysqlNullisNull -\newline -NullisZero -\newline -MysqlNullisZero -\newline -NullisBlank -\newline -MysqlNullisBlank -\layout Part* - -Appendices -\layout LaTeX - - -\backslash -appendix -\layout Chapter - -Changelog -\layout Section* - -1.4 (Nov 25 1999) Sinisa Milivojevic -\layout Itemize - -Fixed bug in store and storein methods -\layout Itemize - -Fixed one serious memory leak -\layout Itemize - -Fixed a very serious bug generated by gcc 2.95.xx !! -\layout Itemize - -Added robustness in classes, so that e.g. - same query and row objects can be re-used -\layout Itemize - -Changed sinisa_ex example to reflect and demonstrate this stability -\layout Itemize - -Changed Changelog and README -\layout Itemize - -Few other bug fixes and small improvements and speed-ups -\layout Section* - -1.3 (Nov 10 1999) Sinisa Milivojevic -\layout Itemize - -Fixed several erronous definitions -\layout Itemize - -Further changed source to be 2.95.2 compatible -\layout Itemize - -Expunged unused statements, especially dubious ones, like use of pointer_tracker -\layout Itemize - -Corrected bug in example file fieldinf1 -\layout Itemize - -Finally fixed mysql_init in Connection constructor, which provided much - greater stability ! -\layout Itemize - -Added read and get options, so that clients, like mysqlgui can use it -\layout Itemize - -Changed Changelog and README -\layout Itemize - -Many other bug fixes. -\layout Section* - -1.2 (Oct 15 1999) Sinisa Milivojevic -\layout Itemize - -First offical release. - Version 1.0 and 1.1 were releases by Sinisa before I (Kevin Atkinson) made - him the offical maintainer, -\layout Itemize - -Many manual fixes. -\layout Itemize - -Changed README and Changelog -\layout Itemize - -Changed source to be compilable by gcc 2.95.xx, tribute to Kevin Atkinson - -\layout Itemize - -Added methods in Connection class which are necessary for fullfilling administra -tive functions with MySQL -\layout Itemize - -Added many bug fixes in code pertaining to missing class initializers , - as notified by Michael Rendell -\layout Itemize - -Sinisa Milivojevic is now the offical maintainer. -\layout Section* - -1.1 (Aug 2 1999) Sinisa Milivojevic -\layout Itemize - -Added several bug fixes -\layout Itemize - -Fixed memory leak problems and variables overlapping problems. -\layout Itemize - -Added automake and autoconf support by loic@ceic.com -\layout Itemize - -Added Makefile for manual -\layout Itemize - -Added support for cygwin -\layout Itemize - -Added example sinisa_ex (let modesty prevail) which used to crash a lot - when memory allocation, memory leak and overlap problems were present. - Smooth running of this example proves that all those bugs are fixed -\layout Itemize - -Corrected bugs in sql_query.cc regarding delete versus delete[] and string - length in manip.cc -\layout Itemize - -Changed manual -\layout Itemize - -Changed README -\layout Itemize - -Many other smaller things -\layout Section* - -1.0 (June 9 1999) Michael Widenius -\layout Itemize - -Added patches from Orion Poplawski to support the UnixWare - 7.0 compiler -\layout Section* - -.64.1.1a (Sep 27 1998) -\layout Itemize - -Fixed several bugs that caused my library to fail to compile with egcs 1.1. - Hopefully it will still compile with egcs 1.0 however I have not been able - to test it with egcs 1.0. -\layout Itemize - -Removed some problem causing debug output in sql++pretty. -\layout Section* - -.64.1a (Aug 1 1998) -\layout Itemize - -Added an (almost) full guide to using Template Queries. -\layout Itemize - -Fixed it so the SQLQuery will throw an exception when all the template parameter -s are not provided. -\layout Itemize - -Proofread and speedchecked the manual (it really needed it). -\layout Itemize - -Other minor document fixes. -\layout Section* - -.64.0.1a (July 31 1998) -\layout Itemize - -Reworked the Class Reference section a bit. -\layout Itemize - -Minor document fixes -\layout Itemize - -Added more examples for SSQLS. -\layout Itemize - -Changed the syntax of equal_list for SSQLS from equal_list (cchar *, Manip, - cchar *) to (cchar *, cchar *, Manip). -\layout Itemize - -Added set methods to SSQLS. - These new methods do the same thing as there corresponding constructors. -\layout Itemize - -Added methods for creating a mysql_type_info from a C++ type_info. -\layout Section* - -.64.a (July 24 1998) -\layout Itemize - -Changed the names of all the classes so they no longer have to have Mysql - in the begging of it. - However if this creates a problem you can define a macro to -\emph on -only -\emph default - use the old names instead. - -\layout Itemize - -The Specialized SQL Structures (formally known as Custom Mysql Structures) - changed from mysql_ to sql_. -\layout Itemize - -Added the option of using exceptions thoughout the API. -\layout Itemize - -ColData (formally known as MysqlStrings) will now throw an exception if - there is a problem in the conversion. -\layout Itemize - -Added a null adapter. -\layout Itemize - -Added Mutable Result Sets -\layout Itemize - -Added a very basic runtime type identification for SQL types -\layout Itemize - -Changed the document format from POD to LyX . -\layout Itemize - -Am now using a modified version of Perceps to extract the class information - directly from the code to make my life easier. -\layout Itemize - -Added an option of defining a macro to avoid using the automatic conversion - with binary operators. -\layout Itemize - -Other small fixed I probully forgot to mentune. -\layout Section* - -.63.1.a -\layout Itemize - -Added Custom Mysql Structures. -\layout Itemize - -Fixed the Copy constructor of class Mysql -\layout Itemize - -Started adding code so that class Mysql lets it children now when it is - leaving -\layout Itemize - -Attempted to compile it into a library but still need help. - As default it will compile as a regular program. -\layout Itemize - -Other small fixes. -\layout Section* - -.62.a (May 3 1998) -\layout Itemize - -Added Template Queries -\layout Itemize - -Created s separate SQLQuery object that is independent of an SQL connection. -\layout Itemize - -You no longer have to import the data for the test program as the program - creates the database and tables it needs. -\layout Itemize - -Many small bug fixes. -\layout Section* - -.61.1.a (April 28 1998) -\layout Itemize - -Cleaned up the example code in test.cc and included it in the manual. -\layout Itemize - -Added an interface layout plan to the manual. -\layout Itemize - -Added a reverse iterator. -\layout Itemize - -Fixed a bug with row.hh (It wasn't being included because of a typo). -\layout Section* - -.61.0.a -\layout Itemize - -Major interface changes. - I warned you that the interface may change while it is in pre-alpha state - and I wasn't kidding. -\layout Itemize - -Created a new and Separate Query Object. - You can no longer execute queries from the Mysql object instead you have - to create a query object with Mysql::query() and use it to execute queries. -\layout Itemize - -Added the comparison operators to MysqlDate, MysqlTime and MysqlDateTime. - Fixed a few bugs in the MysqlDate... - that effected the stream output and the conversion of them to strings. -\layout Itemize - -Reflected the MysqlDate... - changes in the manual. -\layout Itemize - -Added a new MysqlSet object and a bunch of functions for working with mysql - set strings. - -\layout Section* - -.60.3a (April 24 1998) -\layout Itemize - -Changed strtoq and strtouq to strtoll and strtull for metter compatibility - Minor Manual fix. -\layout Itemize - -Changed makefile to make it more compatible with Solaris (Thanks Chris H) -\layout Itemize - -Fixed bug in comparison functions so that they would compare in he right - direction. -\layout Itemize - -Added some items to the to do list be sure to have a look. -\layout Chapter - -To Do -\layout Standard - -These are in the order I plan on implementing them. -\layout Itemize - -Improve the runtime type identification system for the sql types which will - be needed for the mutable results sets and the binary operators in particular. -\layout Itemize - -Improve the mutable results sets so that they can be assigned types that - are not strings setting the sql type aproprestly. - Also allow the SQLtype to be fixed so that when the programmer assigned - a type to the data field that is not compatible with that sql type it will - through an exception. - For example setting an string to an int. -\layout Itemize - -Change the behavior of MysqlString when used with binary operators. - Instead of converting to the type on the other side of the operator have - it convert to the type the Mysql server said it originally was. -\layout Itemize - -Improve the Null adapters to make them more intelligently. -\layout Itemize - -Be able to store the result set in an assignable container that stores the - results in the format they were originally stored in on the server. - (Not sure what the best way to go about this is. - If you have any ideas let me know.) -\layout Itemize - -Better handling of the destruction of the Mysql class. - Have it first tell all its children that its parent is getting destroys - and have then respond appropreatly. - (Partly implemented as of version .63.1.a) -\layout Itemize - -Create a container to hold Mysql enums and sets as a bit set as opposed - to a list of STL set. - -\layout Itemize - -Have a more intelligent MysqlRes that can reexecute to refresh the data. - -\layout Itemize - -Create full fledged client side cursors -\layout Standard - -If you have anything else you want to see let us know at sinisa@cytanet.com.cy - or monty@mysql.com. - -\layout Chapter - -Credits -\layout Standard - -The following is an informal list of programs and people I would like to - thank. -\layout Itemize - -egcs - for the great compiler (egcs.cygnus.com) -\layout Itemize - -Perl - for making my life in general a lot easier (www.perl.com) -\layout Itemize - -Lyx - as a great tool for helping me with this manual (www.lyx.org) -\layout Itemize - -perceps - As a great tool for extracting documentation from the source (friga.mer. -utexas.edu/mark/perl/perceps/) -\layout Itemize - -latex2html - For making the html version of this document possible (www-dsed.llnl. -gov/files/programs/unix/latex2html/) -\layout Itemize - -lynx - For manking the text version of this document possible. -\layout Itemize - -Mysql - for obvious reasons (www.tcx.se) -\layout Itemize - -Xemacs - the editor of choice -\layout Itemize - -Debian/GNU Linux - The platform I developed this on (www.debian.org) -\layout Itemize - -Chris Halverson - For helping me get it to compile under Solaris. -\layout Itemize - -Fredric Fredricson - For a long talk about automatic conversions. -\layout Itemize - -Michael Widenius - Mysql developer who has been very supportive of my efforts. -\layout Itemize - -Paul J. - Lucas -For the original idea of treating the query object like a stream. -\layout Itemize - -Scott Barron - For helping me with the shared libraries. -\layout Itemize - -Jools Enticknap - For giving me the Template Queries Idea. -\layout Itemize - -M. - S. - Sriram - For a detailed dission of how the Template Queries should be implement -ed, the suggestion to throw exceptions on bad queries, and the idea of having - a back-end independent query object (ie SQLQuery). -\layout Itemize - -Sinisa Milivojevic - For becoming the new offical maintainer. -\layout Standard - -If you fell that I forgot something please let me know. -\layout Chapter - -Copyright -\layout Standard - -The Mysql++ API is copyright 1998 by Kevin Atkinson and 1999 by MySQL and - is released under the LGPL license . -\layout Standard - -The intent of doing this is allow developers to use my library to develop - commercial programs and to allow it be distributed with commercial databases. -\layout Section - -LGPL -\layout Standard -\align center -GNU LIBRARY GENERAL PUBLIC LICENSE -\newline -Version 2, June 1991 -\layout Standard - -Copyright (C) 1991 Free Software Foundation, Inc. - -\layout Quote - -59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -\layout Standard - -Everyone is permitted to copy and distribute verbatim copies of this license - document, but changing it is not allowed. -\layout Standard - -[This is the first released version of the library GPL. - It is numbered 2 because it goes with version 2 of the ordinary GPL.] -\layout Standard -\align center -Preamble -\layout Standard - -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. -\layout Standard - -This license, the Library General Public License, applies to some specially - designated Free Software Foundation software, and to any other libraries - whose authors decide to use it. - You can use it for your libraries, too. -\layout Standard - -When we speak of free software, we are referring to freedom, 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 or use pieces of it in new free programs; - and that you know you can do these things. -\layout Standard - -To protect your rights, we need to make restrictions that forbid anyone - to deny you these rights or to ask you to surrender the rights. - These restrictions translate to certain responsibilities for you if you - distribute copies of the library, or if you modify it. -\layout Standard - -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 a program 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. -\layout Standard - -Our method of protecting your rights has two steps: (1) copyright the library, - and (2) offer you this license which gives you legal permission to copy, - distribute and/or modify the library. -\layout Standard - -Also, for each distributor's protection, we want to make certain that everyone - understands that there is no warranty for this free library. - If the library is modified by someone else and passed on, we want its recipient -s to know that what they have is not the original version, so that any problems - introduced by others will not reflect on the original authors' reputations. -\layout Standard - -Finally, any free program is threatened constantly by software patents. - We wish to avoid the danger that companies distributing free software will - individually obtain patent licenses, thus in effect transforming the program - into proprietary software. - To prevent this, we have made it clear that any patent must be licensed - for everyone's free use or not licensed at all. -\layout Standard - -Most GNU software, including some libraries, is covered by the ordinary - GNU General Public License, which was designed for utility programs. - This license, the GNU Library General Public License, applies to certain - designated libraries. - This license is quite different from the ordinary one; be sure to read - it in full, and don't assume that anything in it is the same as in the - ordinary license. -\layout Standard - -The reason we have a separate public license for some libraries is that - they blur the distinction we usually make between modifying or adding to - a program and simply using it. - Linking a program with a library, without changing the library, is in some - sense simply using the library, and is analogous to running a utility program - or application program. - However, in a textual and legal sense, the linked executable is a combined - work, a derivative of the original library, and the ordinary General Public - License treats it as such. -\layout Standard - -Because of this blurred distinction, using the ordinary General Public License - for libraries did not effectively promote software sharing, because most - developers did not use the libraries. - We concluded that weaker conditions might promote sharing better. -\layout Standard - -However, unrestricted linking of non-free programs would deprive the users - of those programs of all benefit from the free status of the libraries - themselves. - This Library General Public License is intended to permit developers of - non-free programs to use free libraries, while preserving your freedom - as a user of such programs to change the free libraries that are incorporated - in them. - (We have not seen how to achieve this as regards changes in header files, - but we have achieved it as regards changes in the actual functions of the - Library.) The hope is that this will lead to faster development of free - libraries. -\layout Standard - -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, while the latter only - works together with the library. -\layout Standard - -Note that it is possible for a library to be covered by the ordinary General - Public License rather than by this special one. -\layout Standard -\align center -GNU LIBRARY GENERAL PUBLIC LICENSE -\newline -TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION -\layout Standard - -0. - This License Agreement applies to any software library which contains a - notice placed by the copyright holder or other authorized party saying - it may be distributed under the terms of this Library General Public License - (also called "this License"). - Each licensee is addressed as "you". -\layout Standard - -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. -\layout Standard - -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 "modificat -ion".) -\layout Standard - -"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. -\layout Standard - -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. -\layout Standard - -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. -\layout Standard - -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: -\layout Standard -\pextra_type 1 \pextra_width 0.5in - -a) The modified work must itself be a software library. -\layout Standard -\pextra_type 1 \pextra_width 0.5in - -b) You must cause the files modified to carry prominent notices stating - that you changed the files and the date of any change. -\layout Standard -\pextra_type 1 \pextra_width 0.5in - -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. -\layout Standard -\pextra_type 1 \pextra_width 0.5in - -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. -\layout Standard - -(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.) -\layout Standard - -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. -\layout Standard - -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. -\layout Standard - -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. -\layout Standard - -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. -\layout Standard - -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. -\layout Standard - -This option is useful when you wish to copy part of the code of the Library - into a program that is not a library. -\layout Standard - -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. -\layout Standard - -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. -\layout Standard - -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. -\layout Standard - -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. -\layout Standard - -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. -\layout Standard - -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.) -\layout Standard - -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. -\layout Standard - -6. - As an exception to the Sections above, you may also compile 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. -\layout Standard - -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: -\layout Standard -\pextra_type 1 \pextra_width 0.5in - -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 executabl -e 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.) -\layout Standard -\pextra_type 1 \pextra_width 0.5in - -b) 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. -\layout Standard -\pextra_type 1 \pextra_width 0.5in - -c) 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. -\layout Standard -\pextra_type 1 \pextra_width 0.5in - -d) Verify that the user has already received a copy of these materials or - that you have already sent this user a copy. -\layout Standard - -For an executable, the required form of the "work that uses the Library" - must include any data and utility programs needed for reproducing the executabl -e from it. - However, as a special exception, the source code 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. -\layout Standard - -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. -\layout Standard - -7. - You may place library facilities that are a work based on the Library side-by-s -ide 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: -\layout Standard -\pextra_type 1 \pextra_width 0.5in - -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. -\layout Standard -\pextra_type 1 \pextra_width 0.5in - -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. -\layout Standard - -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. -\layout Standard - -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. -\layout Standard - -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 to this - License. -\layout Standard - -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. -\layout Standard - -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. -\layout Standard - -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. -\layout Standard - -This section is intended to make thoroughly clear what is believed to be - a consequence of the rest of this License. -\layout Standard - -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. -\layout Standard - -13. - The Free Software Foundation may publish revised and/or new versions of - the Library 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. -\layout Standard - -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. -\layout Standard - -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. -\layout Standard -\align center -NO WARRANTY -\layout Standard - -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. -\layout Standard - -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. -\layout Standard -\align center -END OF TERMS AND CONDITIONS -\layout Standard -\align center -How to Apply These Terms to Your New Libraries -\layout Standard - -If you develop a new library, and you want it to be of the greatest possible - use to the public, we recommend making it free software that everyone can - redistribute and change. - You can do so by permitting redistribution under these terms (or, alternatively -, under the terms of the ordinary General Public License). -\layout Standard - -To apply these terms, attach the following notices to the library. - It is safest to attach them to the start of each source file to most effectivel -y convey the exclusion of warranty; and each file should have at least the - "copyright" line and a pointer to where the full notice is found. -\layout Quote - - -\newline -Copyright (C) -\layout Quote - -This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published - by the Free Software Foundation; either version 2 of the License, or (at - your option) any later version. -\layout Quote - -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 Library General Public License for more details. -\layout Quote - -You should have received a copy of the GNU Library General Public License - along with this library; if not, write to the Free Foundation, Inc., 59 - Temple Place, Suite 330, Boston, MA 02111-1307 USA -\layout Standard - -Also add information on how to contact you by electronic and paper mail. -\layout Standard - -You should also get your employer (if you work as a programmer) or your - school, if any, to sign a "copyright disclaimer" for the library, if necessary. - Here is a sample; alter the names: -\layout Quote - -Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' - (a library for tweaking knobs) written by James Random Hacker. -\layout Quote - -, 1 April 1990 Ty Coon, President of Vice -\layout Standard - -That's all there is to it! -\layout Chapter - -Feedback -\layout Standard - -Since October 1999, all maintenance has been transferred to Sinisa Milivojevic - (sinisa@cytanet.com.cy) and Michael Widenius (monty@mysql.com). -\layout Standard - -Send your feedback to any of these addresses, or even better to the mailing - list mysql-plusplus@lists.mysql.com. -\the_end DELETED doc/pretty.pl Index: doc/pretty.pl ================================================================== --- doc/pretty.pl +++ /dev/null @@ -1,75 +0,0 @@ -use FileHandle; -use IPC::Open2; - -if ($ARGV[0] =~ /^--command\=(.+)/) { - $command = $1; -} else { - $command = "g++ -E"; -} - -$/ = undef; -$orgcode = ; - -($macro) = $orgcode =~ /(sql_create_.+? *\(.+?\))/s; - -$out = << "---"; - -#include - -$macro - ---- - -$/ = "\n"; - -$temp_dir = -d '/tmp' ? '/tmp' : $ENV{TMP} || $ENV{TEMP}; - -#print $out; - -open OUT, ">$temp_dir/${$}.cc"; -print OUT $out; -close OUT; - -system "$command $temp_dir/${$}.cc > $temp_dir/${$}.ii"; - -open IN, "$temp_dir/${$}.ii"; -while () { - next if /^\#/; - $code .= $_; -} -close IN; - -unlink "$temp_dir/${$}.cc","$temp_dir/${$}.ii"; - -$_ = $code; -s/\s+/ /g; -s/ *public: */public:\n/g; -s/ *private: */public:\n/g; -s/ *\; */\;\n/g; -s/ *\{ */ \{\n/g; -s/ *\} */ \}\n\n/g; -s/ *\n */\n/g; -s/\{\s+}/\{\}/g; -s/\}\s+\;/\}\;\n/g; - -$code = ""; -foreach (split /\n/) { - if (/\}/ && !/\{\}/ ) { - $indent -= 2; - $ind = ' 'x$indent; - } - $code .= "$ind$_\n" unless /\:$/; - $code .= "$_\n" if /\:$/; - if (/\{/ && !/\{\}/ ) { - $indent += 2; - $ind = ' 'x$indent; - } -} - -$orgcode =~ s/(sql_create_.+? *\(.+?\))/\n$code\n/s; - -print $orgcode; - - - - DELETED doc/sql++pretty Index: doc/sql++pretty ================================================================== --- doc/sql++pretty +++ /dev/null @@ -1,75 +0,0 @@ -use FileHandle; -use IPC::Open2; - -if ($ARGV[0] =~ /^--command\=(.+)/) { - $command = $1; -} else { - $command = "g++ -E"; -} - -$/ = undef; -$orgcode = ; - -($macro) = $orgcode =~ /(sql_create_.+? *\(.+?\))/s; - -$out = << "---"; - -#include - -$macro - ---- - -$/ = "\n"; - -$temp_dir = -d '/tmp' ? '/tmp' : $ENV{TMP} || $ENV{TEMP}; - -#print $out; - -open OUT, ">$temp_dir/${$}.cc"; -print OUT $out; -close OUT; - -system "$command $temp_dir/${$}.cc > $temp_dir/${$}.ii"; - -open IN, "$temp_dir/${$}.ii"; -while () { - next if /^\#/; - $code .= $_; -} -close IN; - -unlink "$temp_dir/${$}.cc","$temp_dir/${$}.ii"; - -$_ = $code; -s/\s+/ /g; -s/ *public: */public:\n/g; -s/ *private: */public:\n/g; -s/ *\; */\;\n/g; -s/ *\{ */ \{\n/g; -s/ *\} */ \}\n\n/g; -s/ *\n */\n/g; -s/\{\s+}/\{\}/g; -s/\}\s+\;/\}\;\n/g; - -$code = ""; -foreach (split /\n/) { - if (/\}/ && !/\{\}/ ) { - $indent -= 2; - $ind = ' 'x$indent; - } - $code .= "$ind$_\n" unless /\:$/; - $code .= "$_\n" if /\:$/; - if (/\{/ && !/\{\}/ ) { - $indent += 2; - $ind = ' 'x$indent; - } -} - -$orgcode =~ s/(sql_create_.+? *\(.+?\))/\n$code\n/s; - -print $orgcode; - - - - ADDED doc/ssqls-pretty Index: doc/ssqls-pretty ================================================================== --- /dev/null +++ doc/ssqls-pretty @@ -0,0 +1,83 @@ +#!/usr/bin/perl +use FileHandle; +use IPC::Open2; + +if ($ARGV[0] =~ /^--command\=(.+)/) { + $command = $1; +} else { + $command = "g++ -E -I /usr/include/mysql"; +} + +if (-e 'lib/mysql++.h') { + $command .= " -I lib"; +} +else { + $command .= " -I /usr/include/mysql++/"; +} + +$/ = undef; +$orgcode = ; + +($macro) = $orgcode =~ /(sql_create_.+? *\(.+?\))/s; + +$out = << "---"; + +#include + +$macro + +--- + +$/ = "\n"; + +$temp_dir = -d '/tmp' ? '/tmp' : $ENV{TMP} || $ENV{TEMP}; + +#print $out; + +open OUT, ">$temp_dir/${$}.cc"; +print OUT $out; +close OUT; + +system "$command $temp_dir/${$}.cc > $temp_dir/${$}.ii"; + +open IN, "$temp_dir/${$}.ii"; +while () { + next if /^\#/; + $code .= $_; +} +close IN; + +unlink "$temp_dir/${$}.cc","$temp_dir/${$}.ii"; + +$_ = $code; +s/\s+/ /g; +s/ *public: */public:\n/g; +s/ *private: */public:\n/g; +s/ *\; */\;\n/g; +s/ *\{ */ \{\n/g; +s/ *\} */ \}\n\n/g; +s/ *\n */\n/g; +s/\{\s+}/\{\}/g; +s/\}\s+\;/\}\;\n/g; + +$code = ""; +foreach (split /\n/) { + if (/\}/ && !/\{\}/ ) { + $indent -= 2; + $ind = ' 'x$indent; + } + $code .= "$ind$_\n" unless /\:$/; + $code .= "$_\n" if /\:$/; + if (/\{/ && !/\{\}/ ) { + $indent += 2; + $ind = ' 'x$indent; + } +} + +$orgcode =~ s/(sql_create_.+? *\(.+?\))/\n$code\n/s; + +print $orgcode; + + + + ADDED doc/userman/Makefile Index: doc/userman/Makefile ================================================================== --- /dev/null +++ doc/userman/Makefile @@ -0,0 +1,66 @@ +## ------------------------ +## Input files +## ------------------------ + +HTML_DIR=../html/userman +BASENAME=userman +DOCFILE=$(BASENAME).dbx +PDFFILE=$(BASENAME).pdf +FOFILE=$(BASENAME).fo +COMMON_SS=common.xsl +FO_SS=fo.xsl +HTML_SS=html.xsl +EX_TXT=cgi_jpeg.txt cpool.txt deadlock.txt fieldinf.txt for_each.txt \ + load_jpeg.txt multiquery.txt resetdb.txt simple1.txt \ + simple2.txt simple3.txt ssqls1.txt ssqls2.txt ssqls3.txt \ + ssqls4.txt ssqls5.txt stock.txt store_if.txt tquery1.txt \ + transaction.txt + + +## ------------------------ +## Major output rules +## ------------------------ + +html: $(HTML_DIR)/index.html + +pdf: $(PDFFILE) + + +## ------------------------ +## Standard Makefile targets +## ------------------------ + +# Notice that this is not the first target in the file, as is standard. +# PDF generation takes longer than HTML generation, so to keep the code- +# test-debug-rebuild cycle short, we generate only the HTML manual by +# default. You can explicitly say "make pdf" or "make all" when you're +# sure the DocBook file's contents are correct. +all: html pdf + +clean: + rm -f tags *.fo $(HTML_DIR)/*.html *.log *.out *.pdf *.txt + + +## ------------------------ +## How to make output files +## ------------------------ + +$(PDFFILE): *.dbx *.in $(FO_SS) $(COMMON_SS) + xsltproc --nonet --xinclude $(FO_SS) $(DOCFILE) > $(FOFILE) + ./fo2pdf $(FOFILE) $(PDFFILE) + mkdir -p ../pdf && cp $(PDFFILE) ../pdf + +$(HTML_DIR)/index.html: *.dbx *.in $(EX_TXT) $(HTML_SS) $(COMMON_SS) + @xmllint --nonet --xinclude --postvalid --noent --noout $(DOCFILE) + xsltproc --nonet --xinclude -o $(HTML_DIR)/ $(HTML_SS) $(DOCFILE) + + +## ------------------------ +## Dependency rules +## ------------------------ + +$(EX_TXT): + @./mktxt $@ + +userman.dbx: userman.dbx.in + ( cd ../.. ; ./config.status ) ADDED doc/userman/breakages.dbx Index: doc/userman/breakages.dbx ================================================================== --- /dev/null +++ doc/userman/breakages.dbx @@ -0,0 +1,1122 @@ + + + + + Incompatible Library Changes + + This chapter documents those library changes since the epochal + 1.7.9 release that break end-user programs. You can dig this stuff out + of the ChangeLog, but the ChangeLog focuses more on explaining and + justifying the facets of each change, while this section focuses on + how to migrate your code between these library versions. + + Since pure additions do not break programs, those changes are + still documented only in the ChangeLog. + + + + API Changes + + This section documents files, functions, methods and classes + that were removed or changed in an incompatible way. If your program + uses the changed item, you will have to change something in your + program to get it to compile after upgrading to each of these + versions. + + + v1.7.10 + + Removed Row::operator[]() overloads + except the one for size_type, and added + Row::lookup_by_name() to provide the + “subscript by string” functionality. In practical + terms, this change means that the row["field"] + syntax no longer works; you must use the new + lookup_by_name method instead. + + Renamed the generated library on POSIX systems from + libsqlplus to + libmysqlpp. + + + + + v1.7.19 + + Removed SQLQuery::operator=(), and + the same for its Query subclass. Use the + copy constructor instead, if you need to copy one query to another + query object. + + + + + v1.7.20 + + The library used to have two names for many core classes: a + short one, such as Row and a longer one, + MysqlRow. The library now uses the shorter + names exclusively. + + All symbols within MySQL++ are in the + mysqlpp namespace now if you use the new + mysql++.h header. If you use the older + sqlplus.hh or mysql++.hh + headers, these symbols are hoist up into the global namespace. The + older headers cause the compiler to emit warnings if you use them, + and they will go away someday. + + + + + v2.0.0 + + + Connection class changes + + + Connection::create_db() + and drop_db() return + true on success. They returned + false in v1.7.x! This + change will only affect your code if you have exceptions + disabled. + + Renamed + Connection::real_connect() + to connect(), made several + more of its parameters default, and removed the + old connect() method, as + it’s now a strict subset of the new one. The + only practical consequence is that if your program + was using real_connect(), + you will have to change it to + connect(). + + Replaced + Connection::read_option() with new + set_option() mechanism. In addition + to changing the name, programs using this function will have + to use the new Connection::Option + enumerated values, accept a true + return value as meaning success instead of 0, and + use the proper argument type. Regarding the latter, + read_option() took a const + char* argument, but because it was just a thin wrapper + over the MySQL C API function , the actual value being pointed to could + be any of several types. This new mechanism is properly + type-safe. + + + + + + Exception-related changes + + + Classes Connection, + Query, Result, + ResUse, and Row + now derive from which gives these classes a common + interface for disabling exceptions. In addition, almost all + of the per-method exception-disabling flags were removed. The + preferred method for disabling exceptions on these objects + is to create an instance of the new class on the stack, which disables + exceptions on an OptionalExceptions + subclass as long as the NoExceptions + instance is in scope. You can instead call + disable_exceptions() on any + of these objects, but if you only want them disabled + temporarily, it’s easy to forget to re-enable them + later. + + In the previous version of MySQL++, + those classes that supported optional exceptions that + could create instances of other such classes were + supposed to pass this flag on to their children. That + is, if you created a Connection + object with exceptions enabled, and then asked it to + create a Query object, the + Query object also had exceptions + disabled. The problem is, this didn’t happen in all + cases where it should have in v1.7. This bug is fixed in + v2.0. If your program begins crashing due to uncaught + exceptions after upgrading to v2.0, this is the most likely + cause. The most expeditious fix in this situation is to + use the new NoExceptions feature to + return these code paths to the v1.7 behavior. A better fix + is to rework your program to avoid or deal with the new + exceptions. + + All custom MySQL++ exceptions now derive from + the new interface. + The practical upshot of this is that the variability between + the various exception types has been eliminated. For instance, + to get the error string, the BadQuery + exception had a string member called error + plus a method called what(). Both + did the same thing, and the what() + method is more common, so the error string was dropped + from the interface. None of the example programs had to be + changed to work with the new exceptions, so if your program + handles MySQL++ exceptions the same way they do, your program + won’t need to change, either. + + Renamed + SQLQueryNEParams exception to + BadParamCount to match style of other + exception names. + + Added , , , , , , and exception types, to fix + overuse of BadQuery. Now the + latter is used only for errors on query execution. If + your program has a “catch-all” block taking a + std::exception for each try block + containing MySQL++ statements, you probably won’t + need to change your program. Otherwise, the new exceptions + will likely show up as program crashes due to unhandled + exceptions. + + + + + + Query class changes + + + + In previous versions, + Connection had + a querying interface similar to class + Query’s. These methods were + intended only for Query’s use; no + example ever used this interface directly, so no end-user code + is likely to be affected by this change. + + A more likely problem arising from + the above change is code that tests for query success + by calling the Connection + object’s success() method + or by casting it to bool. This will now give + misleading results, because queries no longer go through + the Connection object. Class + Query has the same success-testing + interface, so use it instead. + + Query now derives + from std::ostream instead of + std::stringstream. + + + + + + + Result/ResUse class changes + + + + Renamed + ResUse::mysql_result() to + raw_result() so it’s database + server neutral. + + Removed + ResUse::eof(), as it wrapped + the deprecated and unnecessary MySQL C API function + . See the + simple3 and usequery + examples to see the proper way to test for the end of a result + set. + + + + + + + Row class changes + + + + Removed “field name” form + of Row::field_list(). It was + pointless. + + Row subscripting + works more like v1.7.9: one can subscript a + Row with a string (e.g. + row["myfield"]), or with + an integer (e.g. row[5]). + lookup_by_name() was + removed. Because row[0] is + ambiguous (0 could mean the first field, or be a null + pointer to const char*), there is now + Row::at(), which can look up any + field by index. + + + + + + + Miscellaneous changes + + + + Where possible, all distributed Makefiles only + build dynamic libraries. (Shared objects on most Unices, DLLs + on Windows, etc.) Unless your program is licensed under the + GPL or LGPL, you shouldn’t have been using the static + libraries from previous versions anyway. + + Removed the backwards-compatibility + headers sqlplus.hh and + mysql++.hh. If you were + still using these, you will have to change to + mysql++.h, which will put all symbols in + namespace mysqlpp. + + Can no longer use arrow operator + (->) on the iterators into the + Fields, Result + and Row containers. + + + + + + + v2.2.0 + + Code like this will have to change: + + +query << "delete from mytable where myfield=%0:myvalue"; +query.parse(); +query.def["myvalue"] = some_value; +query.execute(); + + ...to something more like this: + + +query << "delete from mytable where myfield=%0"; +query.parse(); +query.execute(some_value); + + The first code snippet abuses the default template query + parameter mechanism (Query::def) to fill out + the template instead of using one of the overloaded forms of + execute(), + store() or use() + taking one or more SQLString parameters. + The purpose of Query::def is to allow for + default template parameters over multiple queries. In the first + snippet above, there is only one parameter, so in order to justify + the use of template queries in the first place, it must be + changing with each query. Therefore, it isn’t really a + “default” parameter at all. We did not make this + change maliciously, but you can understand why we are not in any + hurry to restore this “feature”. + + (Incidentally, this change was made to allow better support + for BLOB columns.) + + + + + v2.3.0 + + Connection::set_option() calls now + set the connection option immediately, instead of waiting until + just before the connnection is actually established. Code that + relied on the old behavior could see unhandled exceptions, since + option setting errors are now thrown from a different part of the + code. You want to wrap the actual + set_option() call now, not + Connection::connect() + + FieldNames and + FieldTypes are no longer exported from the + library. If you are using these classes directly from Visual C++ + or MinGW, your code won’t be able to dynamically link to a + DLL version of the library any more. These are internal classes, + however, so no one should be using them directly. + + + + + v3.0.0 + + + Class name changes + + Several classes changed names in this + release: + + + ColData is now + String. + + NullisBlank + is now NullIsBlank. (Note + the capital I.) Similar + changes for NullisNull and + NullisZero. + + ResNSel is now + SimpleResult. + + Result is now + StoreQueryResult. + + ResUse is now + UseQueryResult. + + SQLString is now + SQLTypeAdapter. + + + When first building existing code against this version, + you may find it helpful to define the macro + MYSQLPP_OLD_CLASS_NAMES in your + program’s build options. This will turn on some macros + that set up aliases for the new class names matching their + corresponding old names. Then, when you’ve fixed up any + other issues that may prevent your program from building with + the new MySQL++, you can turn it back off and fix up any class + name differences. + + If you were only using ColData in a + BLOB context, you should use sql_blob or + one of the related typedefs defined in + lib/sql_types.h instead, to insulate your + code from changes like these. + + The SQLString change + shouldn’t affect you, as this class was not designed to be + used by end user code. But, due to the old name and the fact + that it used to derive from std::string, + some might have been tempted to use it as an enhanced + std::string. Such code will undoubtedly + break, but can probably be fixed by just changing it to use + std::string instead. + + + + + Connection class changes + + The option setting mechanism has been redesigned. (Yes, + again.) There used to be an enum in + Connection with a value for each option + we understood, and an overload of + Connection::set_option() for each + argument type we understood. It was possible to pass any option + value to any set_option() overload, and + the problem would only be detected at run time. Now each option + is represented by a class derived from the new + Option abstract base class, and + set_option() simply takes a pointer to + one of these objects. See + examples/multiquery.cpp for the syntax. + Since each Option subclass takes only the + parameter types it actually understands, it’s now + completely type-safe at compile time. + + The new option setting mechanism also has the virtue of + being more powerful so it let us replace several existing things + within Connection with new + options: + + + Replaced + enable_ssl() with + SslOption. + + Replaced the compress + parameter to the Connection + create-and-connect constructor and + Connection::connect() method with + CompressOption. + + Replaced the + connect_timeout parameter with + ConnectTimeoutOption. + + Defined Option + subclasses for each of the flags you would previously set + using the client_flag parameter. There + are about a dozen of these, so instead of listing them, + look in lib/options.h for something + with a similar name. + + + Collapsed Connection’s + host, port, and + socket_name parameters down into a new + combined server parameter which is parsed to + determine what kind of connection you mean. These interfaces are + still compatible with v2.3 and earlier up through the port + parameter. + + Moved + Connection::affected_rows(), + info() and + insert_id() methods to class + Query, as they relate to the most + recently-executed query. + + Changed the return type of + Connection::ping() from + int to bool. If you were calling + ping() in bool context + or using its return value in bool context, + you will need to reverse the sense of the test because the + previous return code used zero to mean success. Now it returns + true to indicate success. + + Renamed several methods: + + + Use client_version() + instead of api_version() or + client_info(). + + Use + ipc_version() instead of + host_info(). + + Use + protocol_version() instead of + proto_info(). + + Use + server_version() instead of + server_info(). + + Use + status() instead of + stat(). + + + Also, removed close() in favor + of disconnect(), which has always + done the same thing. + + + + + Date and Time class changes + + The sql_timestamp typedef is now + an alias for DateTime, not + Time. + + There used to be implicit conversion constructors from + ColData (now + String), + std::string and const char* + for the Date, + DateTime, and Time + classes. It’s still possible to do these conversions, but + only explicitly. (This had to be done to make + Null<T> work in SSQLSes.) + + The most likely place to run into problems as a result + of this change is in code like this: + + +void some_function(const mysqlpp::DateTime& dt); + +some_function("2007-12-22"); + + The function call needs to be changed to: + + +some_function(mysqlpp::DateTime("2007-12-22")); + + + + + Exception changes + + If an error occurs during the processing of a + “use” query (as opposed to the initial execution) we + throw the new UseQueryError exception + instead of BadQuery. + + If you pass bad values to the Row + ctor so that it can’t initialize itself properly, it + throws the ObjectNotInitialized + exception instead of BadQuery. + + Together, these two changes mean that + BadQuery is now used solely to indicate + a problem executing the actual SQL query statement. + + + + + Field and Fields class changes + + Field is now a real C++ class, + not just a typedef for the corresponding C API class. Major + portability impacts are: + + + It has no public data members. Where + sensible, there is a public accessor function of the + same name as the corresponding field in the C API + structure. + + The main exception to this is the + flags data member. This is a bitfield in + the C API data structure and you had to use MySQL-specific + constants to break values out of it. MySQL++’s new + Field class provides a public member + function returning bool for each of these + flags. + + The new class doesn’t include all of the + data members from the C API version. We left out those that + aren’t used within MySQL++ or its examples, or whose + function we couldn’t understand. Basically, if we + couldn’t document a reason to use it, we left it + out. + + + Fields used to be a + std::vector work-alike which + worked with the C API to access fields and return them + as though they were simply contained directly within the + Fields object. Now that we have a + real MySQL++ class to hold information about each field + without reference to the C API, we were able to replace the + Fields class with: + + +typedef std::vector<Field> Fields; + + If anything, this should give a pure superset of the old + functionality, but it’s possible it could break end user + code. + + + + + Query class changes + + If you were using char as an 8-bit integer + in query building, there are several places in MySQL++ v3 where + it will now be treated as a single-character string. MySQL++ + has had the tiny_int class for many + years now specifically to provide a true 8-bit integer without + the semantic confusion surrounding the old C char + type. Either use tiny_int, or + use the SQL type aliases sql_tinyint and + sql_tinyint_unsigned instead. + + The ‘r’ and ‘R’ template query + parameter modifiers were removed. They made the library do + quoting and both quoting and escaping (respectively) regardless + of the data type of the parameter. There are no corresponding + Query stream manipulators, so for + symmetery we had to decide whether to add such manipulators or + remove the tquery modifiers. There should never be a reason to + force quoting or escaping other than to work around a MySQL++ + bug, and it’s better to just fix the bug than work around + it, so removed the tquery modifiers. + + Query::store_next() + and Result::fetch_row() no + longer throw the EndOfResults and + EndOfResultSets exceptions; these + are not exceptional conditions! These methods simply return + false when you hit the end of the result set + now. + + Renamed Query::def to + Query::template_defaults to make its + purpose clearer. + + Removed Query::preview(). The + most direct replacement for this set of overloaded methods is + the parallel set of str() methods, + which were just aliases before. (Chose + str() over + preview() because it’s standard + C++ nomenclature.) But if you’re just looking to get a + copy of a built query string and you aren’t using template + queries, you can now insert the Query + into a stream and get the same result. + + For example, a lot of code in the examples that used to + say things like: + + +cout << query.preview() << endl; + + now looks like this: + + +cout << query << endl; + + + + + Result, ResUse, and ResNSel class changes + + In addition to the class name changes described above, + UseQueryResult is no longer + StoreQueryResult’s base class. + There is a new abstract class called + ResultBase containing much of what used + to be in ResUse, and it is the base of + both of these concrete result set types. This should only affect + your code if you were using ResUse + references to refer to Result + objects. + + Removed a bunch of duplicate methods: + + + Use + num_fields() instead of + columns(). + + Use + field_names() instead of + names(). + + Use + num_rows() instead of + rows(). + + Use + field_types() instead of + types(). + + + Renamed several methods for “grammar” reasons. + For example, some methods returned a single object but had a + “plural” name, implying that it returned a container + of objects. In cases like this, we changed the name to agree + with the return value. Some of these also fall into the + duplicate method category above: + + + Use + field(unsigned int) + instead of fields(unsigned + int). + + Use field_num(const + std::string&) + instead of names(const + std::string&). + + Use + field_name(int) instead of + names(int). + + Use + field_type(int) instead of + types(int). + + + Removed several “smelly” methods: + + + purge(): was an + internal implementation detail, not something for end user + code to call + + raw_result(): end + user code shouldn’t be digging down to the C API data + structures, but if you really need something like this, look + at the implementation of + Query::storein(). Its workings will + probably be educational. + + reset_names(): + no reason to call this, especially now that the field + name list is initialized once at startup and then never + changed + + reset_field_names(): + just an alias for previous + + reset_types(): + same argument as for + reset_names() + + reset_field_types(): + just an alias for previous + + + ResUse::field_num() would + unconditionally throw a BadFieldName + exception when you asked for a field that doesn’t exist. + Now, if exceptions are disabled on the object, it just returns + -1. + + SimpleResult’s member + variables are all now private, and have read-only accessor + functions of the same name. + + Code like this used to work: + + +mysqlpp::Row row; +mysqlpp::Result::size_type i; +for (i = 0; row = res[i]; ++i) { + // Do something with row here +} + + That is, indexing past the end of a “store” + result set would just return an empty row object, which tests as + false in bool context, so it ends the loop. Now + that StoreQueryResult is a + std::vector derivative, this either + crashes your program or causes the standard library to throw an + exception, depending on what debugging features your version of + STL has. The proper technique is: + + +mysqlpp::Row row; +mysqlpp::Result::size_type i; +for (i = 0; i < res.num_rows(); ++i) { + row = res[i]; + // Do something with row here +} + + + + + Row class changes + + Removed Row::raw_data(), + raw_size() and + raw_string(). These were useful with + BLOB data back when MySQL++ didn’t handle embedded null + characters very well, and when copies of + ColData objects were expensive. Neither + is true now, so they have no value any more. Equivalent calls + are: + + +mysqlpp::String s = row[0]; +s.data(); // raw_data() equivalent +s.length(); // raw_size() equivalent +std::string(s.data(), s.length()); // raw_string() equivalent + + Row::operator[](const char*) + would unconditionally throw a + BadFieldName exception when you asked for + a field that doesn’t exist. Now, if exceptions are + disabled on the Row object, it just + returns a reference to an empty String + object. You can tell when this happens because such an object + tests as false in bool context. + + + + + Specialized SQL Structure (SSQLS) changes + + Renamed custom* to + ssqls*. There is a backwards-compatibility + header custom.h which includes + ssqls.h for you, but it will go away in a + future version of MySQL++. + + The only supported macros for creating + SSQLSes now are sql_create_* + and sql_create_complete_*. The + “basic” variants were removed because they’re + less functional than sql_create_*, and + haven’t been used in the examples or documentation for + a long time now. The other two methods were removed because + parameter ordering no longer matters so there’s + no need for macros that let you have custom parameter + ordering. (It’s more complicated than that, actually. See + the ChangeLog for the detailed whys and wherefores.) + + The new Null<T> support in + SSQLSes causes an internal compiler error in Visual C++ 2003. + (VC++ 2005 and newer have no trobule with it.) A poll on the + mailing list says there aren’t many people still stuck on + this version, so we just ifdef’d out the SSQLS mechanism + and all the examples that use it when built with VC++ 2003. If + this affects you, see for + suggestions on ways to cope. + + If you are using types other than MySQL++’s + sql_* ones These typedefs + have been available since MySQL++ v2.1. + in your SSQLSes, code that previously worked may now see + TypeLookupFailed exceptions. (This + can be thrown even if exceptions are otherwise disabled in + MySQL++.) This version of MySQL++ is stricter about mapping + SQL to C++ type information, and vice versa. If the library + can’t find a suitable mapping from one type system + to the other, it throws this exception, because its only + other option would be to crash or raise an assertion. This + typically happens when building SQL queries, so you can + probably handle it the same way as if the subsequent + query excecution failed. If you’re catching the + generic mysqlpp::Exception, your + error handling code might not need to change. If you see + this exception, it does mean you need to look into your + use of data types, though. The table that controls this is + mysql_type_info::types, defined at the top + of lib/type_info.cpp. Every data type in + lib/sql_types.h has a corresponding record + in this table, so if you stick to those types, you’ll + be fine. It’s also okay to use types your C++ compiler + can convert directly to these predefined types. + + The _table static member variable + for each SSQLS is now private. The recommended way to access + this remains unchanged: the table() + static member function. + + table() used to return a modifiable + reference to the table name. Now there are two overloads, + one which returns an unmodifiable pointer to the table name, + and the other which takes const char* so you + can override the default table name. So, the code we used to + recommend for changing the SSQLS’s table name: + + +my_ssqls_type::table() = "MyTableName"; + + now needs to be: + + +my_ssqls_type::table("MyTableName"); + + + + + Miscellaneous changes + + MySQL++ does quoting and escaping much more selectively + now. Basically, if the library can tell you’re not + building a SQL query using one of the standard methods, it + assumes you’re outputting values for human consumption, so + it disables quoting and SQL escaping. If you need to build your + own mechanism to replace this, quoting is easy to do, and + Query::escape_string() can do SQL + escaping for you. + + Removed success() in + Connection, Query + and SimpleResult (neĆ© + ResNSel) and simply made these classes + testable in bool context to get the same + information. An additional change in + Connection is that it used to be + considered “unsuccessful” when the connection was + down. Since the sense of this test is now whether the object is + in a good state, it only returns false when the + connection attempt fails. Call + Connection::is_connected() if you just + want to test whether the connection is up. + + The debug mode build of the library now has a "_d" suffix + for Visual C++, and Xcode. This lets you have both versions + installed without conflict. The release build uses the current + naming scheme. If you have an existing program building against + MySQL++ on these platforms, you’ll need to change your + build options to use the new name in debug mode. + + Renamed NO_LONG_LONGS to + MYSQLPP_NO_LONG_LONGS to avoid a risk of + collision in the global macro namespace. + + + + + + + ABI Changes + + This section documents those library changes that require you + to rebuild your program so that it will link with the new library. + Most of the items in the previous section are also ABI changes, but + this section is only for those items that shouldn’t require + any code changes in your program. + + If you were going to rebuild your program after + installing the new library anyway, you can probably ignore this + section. + + + + v1.7.18 + + The Query classes now subclass from + stringstream instead of the deprecated + strstream. + + + + + v1.7.19 + + Fixed several const-incorrectnesses in the + Query classes. + + + + + v1.7.22 + + Removed “reset query” parameters from several + Query class members. This is not an API + change, because the parameters were given default values, and the + library would ignore any value other than the default. So, any + program that tried to make them take another value wouldn’t + have worked anyway. + + + + + v1.7.24 + + Some freestanding functions didn’t get moved into + namespace mysqlpp when that namespace was + created. This release fixed that. It doesn’t affect the API + if your program’s C++ source files say using + namespace mysqlpp within them. + + + + + v2.0.0 + + Removed Connection::infoo(). + (I’d call this an API change if I thought there were any + programs out there actually using this...) + + Collapsed the Connection constructor + taking a bool (for setting the throw_exceptions flag) and the + default constructor into a single constructor using a default for + the parameter. + + Classes Connection and + Query are now derived from the + Lockable interface, instead of implementing + their own lock/unlock functions. + + In several instances, functions that took objects by + value now take them by const reference, for efficiency. + + Merged SQLQuery class’s members + into class Query. + + Merged RowTemplate class’s + members into class Row. + + Reordered member variable declarations in some classes. The + most common instance is when the private section was declared + before the public section; it is now the opposite way. This + can change the object’s layout in memory, so a program + linking to the library must be rebuilt. + + Simplified the date and time class hierarchy. + used to + derive from mysql_date, + used to derive + from mysql_time, and used to derive from + both of those. All three of these classes used to derive + from mysql_dt_base. All of the + mysql_* classes’ functionality + and data has been folded into the leaf classes, and now the + only thing shared between them is their dependence on the + template. Since the + leaf classes’ interface has not changed and end-user + code shouldn’t have been using the other classes, this + shouldn’t affect the API in any practical way. + + mysql_type_info now always + initializes its private num member. + Previously, this would go uninitialized if you used the default + constructor. Now there is no default ctor, but the ctor taking one + argument (which sets num) has a default. + + + + + v3.0.0 + + Removed reset_query parameters from + Query member functions. None of these have + been honored at least going back to v1.7.9, so this is not an API + change. As of this version, Query now + automatically detects when it can safely reset itself after + executing a query, so it’s not necessary to ask for a reset + except when using template queries. + + Removed overloads of + Query::execute(), + store(), and + use() that take only a const + char*. This is not an API change because there was an + equivalent call chain for this already. This change just snaps + a layer of indirection. + + Query::error() is now + const and returns const char* instead + of a std::string by value. + + Removed Lockable mechanism as it was + conceptually flawed. Connection and + Query consequently no longer derive from + Lockable. Since it was basically useless in + prior versions, it can’t be construed as an API + change. + + + + + v3.0.1 + + Connection::thread_aware(), + thread_start() and + thread_end() are now static methods, so + a program can call them before creating a connection. Ditto for + DBDriver methods of the same name. + + ConnectionPool::release() is now + virtual, so a subclass can override it. + + + + + v3.0.2 + + ConnectionPool::grab() is now + virtual; same reason as above. + + Query can now be tested in + bool context, as was intended for v3.0.0. Had to + change the “safe bool” method signature to make it + happen, so technically it’s an API change, but it’s + still used the same way. + + + ADDED doc/userman/common.xsl Index: doc/userman/common.xsl ================================================================== --- /dev/null +++ doc/userman/common.xsl @@ -0,0 +1,11 @@ + + + + + + + + + + ADDED doc/userman/configuration.dbx Index: doc/userman/configuration.dbx ================================================================== --- /dev/null +++ doc/userman/configuration.dbx @@ -0,0 +1,147 @@ + + + + + Configuring MySQL++ + + The default configuration of MySQL++ is suitable for most + purposes, but there are a few things you can change to make it meet + special needs. + + + The Location of the MySQL Development Files + + MySQL++ is built on top of the MySQL C API. It relies on + this low-level library for all communication with the database + server. Consequently, the build process for MySQL++ may fail if + it can’t find the C API headers and library. + + On platforms that use AutoconfLinux, + Solaris, the BSDs, Mac OS X command line (as opposed to the + Xcode IDE), Cygwin... Basically, Unix or anything that works + like it., the configure + script can usually figure out the location of the C API + development files by itself. It simply tries a bunch of common + installation locations until it finds one that works. If + your MySQL server was installed in a nonstandard location, + you will have to tell the configure + script where these files are with some combination + of the --with-mysql, + --with-mysql-include, and + --with-mysql-lib flags. See + README-Unix.txt for details. + + No other platform allows this sort of auto-discovery, + so the build files for these platforms simply hard-code the + default installation location for the current Generally + Available version of MySQL. For example, the Visual C++ + project files currently assume MySQL is in c:\Program + Files\MySQL\MySQL Server 5.0. If you’re using + some other release of MySQL or you installed it in a nonstandard + location, you will have to modify the build files. How you do + this, exactly, varies based on platform and what tools you have + on hand. See README-Visual-C++.txt, + README-MinGW.txt, or + README-Mac-OS-X.txt, as appropriate. + + + + + The Maximum Number of Columns Allowed + + MySQL++ offers two ways to automatically build SQL + queries at run time: and . There’s a limit on the number + of template query parameters and the number of SSQLS fields, + due to the way these mechanisms work. Both are set to 25, + by default. We arrived at these limits empirically, partly by + looking at good database designs, and by testing compilers to + find their limits. We wanted a limit that doesn’t often + need to be raised without unduly narrowing the list of supported + platforms by exceeding compiler limits. + + If it happens that your database design does need more than + 25 columns or template query parameters, first look to see if + there’s a good way to change the design. It’s usually + a sign of too many unrelated things in one table if you need so + many columns. If you decide the design is good, you can raise these + limits by re-generating the lib/ssqls.h and/or + lib/querydef.h headers using Perl scripts with + the same name, except with a pl extension. + Instructions for this are at the top of each script. + + If you’re on a platform that uses + Autoconfditto, you can change + these scripts like you would any other part of the library. After + making your changes, just say make to rebuild + the library, including these headers. This requires a Perl + interpreter on the system to work, but Perl is nearly ubiquitous + on systems that also use autoconf these days. + + On all other platforms, you’ll have to rebuild + these headers by running Perl by hand. Just say perl + ssqls.pl or perl querydef.pl in the + lib subdirectory of the MySQL++ sources, + then build the library as you normally would. + + + + + Buried MySQL C API Headers + + It’s common these days on Unixy systems to install + the MySQL C API headers in a mysql directory + under some common include directory. If the + C API headers are in /usr/include/mysql, we + say they are “buried” underneath the system’s + main include directory, /usr/include. Since + the MySQL++ headers depend on these C API headers, it can be + useful for MySQL++ to know this fact. + + When MySQL++ includes one of the C API headers, it normally + does so in the obvious way: + + +#include <mysql.h> + + + But, if you define the + MYSQLPP_MYSQL_HEADERS_BURIED macro, it switches + to this style: + + +#include <mysql/mysql.h> + + + In common situations like the + /usr/include/mysql one, this simplifies the + include path options you pass to your compiler. + + + + + Building MySQL++ on Systems Without Complete C99 + Support + + MySQL++ uses the C99 + header stdint.h for portable fixed-size + integer typedefs where possible. The C99 extensions aren’t + yet officially part of the C++ Standard, so there are still + some C++ compilers that don’t offer this header. MySQL++ + works around the lack of this header where it knows it needs + to, but your platform might not be recognized, causing + the build to break. If this happens, you can define the + MYSQLPP_NO_STDINT_H macro to make MySQL++ + use its best guess for suitable integer types instead of relying + on stdint.h. + + MySQL++ also uses C99’s long long + data type where available. MySQL++ has workarounds for platforms + where this is known not to be available, but if you get errors in + common.h about this type, you can define the + macro MYSQLPP_NO_LONG_LONGS to make MySQL++ + fall back to portable constructs. + + ADDED doc/userman/fo.xsl Index: doc/userman/fo.xsl ================================================================== --- /dev/null +++ doc/userman/fo.xsl @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + page + + + + + + + + + + + + + + + + + + + + + + false + + + + + left + + + + + 85% + + + + + ADDED doc/userman/html.xsl Index: doc/userman/html.xsl ================================================================== --- /dev/null +++ doc/userman/html.xsl @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + http://dev.mysql.com/doc/mysql/en/ + + .html + + + () + + + + + + + + + + ../refman/classmysqlpp_1_1 + + .html + + + + + + + + + + + + + + + + + + + ../refman/structmysqlpp_1_1 + + .html + + + + + + + + + + + + + + + + + + + ADDED doc/userman/intro.dbx Index: doc/userman/intro.dbx ================================================================== --- /dev/null +++ doc/userman/intro.dbx @@ -0,0 +1,78 @@ + + + + + Introduction + + MySQL++ is a powerful C++ wrapper for MySQL’s C API. Its + purpose is to make working with queries as easy as working with STL + containers. + + The latest version of MySQL++ can be found at the official web + site. + + Support for MySQL++ can be had on the mailing list. That + page hosts the mailing list archives, and tells you how you can + subscribe. + + + + A Brief History of MySQL++ + + MySQL++ was created in 1998 by Kevin Atkinson. It started out + MySQL-specific, but there were early efforts to try and make it + database-independent, and call it SQL++. This is where the old + library name “sqlplus” came from. This is also why the + old versions prefixed some class names with “Mysql” but + not others: the others were supposed to be the database-independent + parts. + + Then in 1999, Sinisa Milivojevic unofficially took over + maintenance of the library, releasing versions 1.0 and 1.1. (All of + Kevin’s releases were pre-1.0 point releases.) Kevin gave over + maintenance to Sinisa officially with 1.2, and ceased to have any + involvement with the library’s maintenance. Sinisa went on to + maintain the library through 1.7.9, released in mid-2001. Since + Sinisa is an employee of MySQL + AB, it seems to be during this time that the dream of + multiple-database compatibility died. + + With version 1.7.9, MySQL++ went into a period of stasis, + lasting over three years. During this time, Sinisa ran the + MySQL++ mailing list and supported its users, but made no new + releases. There were many patches submitted during this period, + some of which were ignored, others which were just put on the + MySQL++ web site for people to try. A lot of these patches were + mutually-incompatible, and not all of them gave a fully-functional + copy of MySQL++. + + In early August of 2004, the current maintainer (Warren + Young) got fed up with this situation and took over. He released + 1.7.10 later that month. + + + + + If You Have Questions... + + If you want to email someone to ask questions about + this library, we greatly prefer that you send mail to the + MySQL++ mailing + list. The mailing list is archived, so if you have + questions, do a search to see if the question has been asked + before. + + You may find people’s individual email addresses in various + files within the MySQL++ distribution. Please do not send mail + to them unless you are sending something that is inherently + personal. Not all of the principal developers of MySQL++ are still + active in its development; those who have dropped out have no wish + to be bugged about MySQL++. Those of us still active in MySQL++ + development monitor the mailing list, so you aren’t getting any + extra “coverage” by sending messages to additional + email addresses. + + ADDED doc/userman/licenses.dbx Index: doc/userman/licenses.dbx ================================================================== --- /dev/null +++ doc/userman/licenses.dbx @@ -0,0 +1,685 @@ + + + + + Licensing + + The primary copyright holders on the MySQL++ library and its + documentation are Kevin Atkinson (1998), MySQL AB (1999 through 2001) + and Educational Technology Resources, Inc. (2004 through the date of + this writing). There are other contributors, who also retain + copyrights on their additions; see the ChangeLog file in the MySQL++ + distribution tarball for details. + + The MySQL++ library and its Reference Manual are released under + the GNU Lesser General Public License (LGPL), reproduced below. + + The MySQL++ User Manual — excepting some example code from + the library reproduced within it — is offered under a license + closely based on the Linux Documentation Project License (LDPL) v2.0, + included below. (The MySQL++ documentation isn’t actually part + of the Linux Documentation Project, so the main changes are to + LDP-related language. Also, generic language such as + “author’s (or authors’)” has been replaced + with specific language, because the license applies to only this one + document.) + + These licenses basically state that you are free to use, + distribute and modify these works, whether for personal or commercial + purposes, as long as you grant the same rights to those you distribute + the works to, whether you changed them or not. See the licenses below + for full details. + + + + + GNU Lesser General Public License + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 + Temple Place, Suite 330, Boston, MA 02111-1307 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 +
+ + + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the + greatest possible use to the public, we recommend making it free + software that everyone can redistribute and change. You can do so + by permitting redistribution under these terms (or, alternatively, + under the terms of the ordinary General Public License). + + To apply these terms, attach the following notices to the + library. It is safest to attach them to the start of each source + file to most effectively convey the exclusion of warranty; and + each file should have at least the “copyright” line + and a pointer to where the full notice is found. + +
+ <one line to give the library’s name and a brief + idea of what it does.> + + Copyright © <year> <name of + author> + + 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. + + 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., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA +
+ + Also add information on how to contact you by electronic and + paper mail. + + You should also get your employer (if you work as a + programmer) or your school, if any, to sign a “copyright + disclaimer” for the library, if necessary. Here is a + sample; alter the names: + +
+ Yoyodyne, Inc., hereby disclaims all copyright interest in + the library `Frob' (a library for tweaking knobs) written by + James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + + Ty Coon, President of Vice +
+ + That’s all there is to it! +
+
+ + + + + MySQL++ User Manual License + + + I. COPYRIGHT + + The copyright to the MySQL++ User Manual is owned by its + authors. + + + + II. LICENSE + + The MySQL++ User Manual may be reproduced and distributed in + whole or in part, in any medium physical or electronic, provided + that this license notice is displayed in the reproduction. + Commercial redistribution is permitted and encouraged. Thirty days + advance notice via email to the authors of redistribution is + appreciated, to give the authors time to provide updated + documents. + + + A. REQUIREMENTS OF MODIFIED WORKS + + All modified documents, including translations, + anthologies, and partial documents, must meet the following + requirements: + + + The modified version must be labeled as + such. + + The person making the modifications must be + identified. + + Acknowledgement of the original author must be + retained. + + The location of the original unmodified + document be identified. + + The original authors’ names may not be + used to assert or imply endorsement of the resulting document + without the original authors’ + permission. + + + In addition it is requested that: + + + The modifications (including deletions) be + noted. + + The authors be notified by email of the + modification in advance of redistribution, if an email address + is provided in the document. + + + Mere aggregation of the MySQL++ User Manual with other + documents or programs on the same media shall not cause this + license to apply to those other works. + + All translations, derivative documents, or modified + documents that incorporate the MySQL++ User Manual may not have + more restrictive license terms than these, except that you may + require distributors to make the resulting document available in + source format. + + + +
ADDED doc/userman/mktxt Index: doc/userman/mktxt ================================================================== --- /dev/null +++ doc/userman/mktxt @@ -0,0 +1,19 @@ +#!/bin/sh +# Script to convert C++ source files to a text format, with 4 spaces for +# every tab, and with the leading block comment removed. Used to +# reformat the example programs so they can be xincluded directly into +# the DocBook during XSLT processing. + +TXTFILE=$1 +SRCFILE=`echo ../../examples/$TXTFILE | sed -e s/\\\\.txt/.cpp/` +if [ ! -e $SRCFILE ] +then + SRCFILE=`echo ../../examples/$TXTFILE | sed -e s/\\\\.txt/.h/` +fi +CLINE=`grep -n '\*\*/' $SRCFILE |cut -f1 -d:` +LINE=`echo $CLINE + 2 |bc` + +#echo Converting $SRCFILE to $TXTFILE, starting at line $LINE... + +expand -t4 $SRCFILE | tail -n +$LINE > $TXTFILE + ADDED doc/userman/overview.dbx Index: doc/userman/overview.dbx ================================================================== --- /dev/null +++ doc/userman/overview.dbx @@ -0,0 +1,211 @@ + + + + + Overview + + MySQL++ has a lot of complexity and power to cope with the + variety of ways people use databases, but at bottom it doesn’t + work all that differently than other database access APIs. The usage + pattern looks like this: + + + Open the connection + + Form and execute the query + + If successful, iterate through the result + set + + Else, deal with errors + + + Each of these steps corresponds to a MySQL++ class or class + hierarchy. An overview of each follows. + + + + The Connection Object + + A object manages the + connection to the MySQL server. You need at least one of these + objects to do anything. Because the other MySQL++ objects your + program will use often depend (at least indirectly) on the + Connection instance, the + Connection object needs to live at least as + long as all other MySQL++ objects in your program. + + MySQL supports many different types of data connection between + the client and the server: TCP/IP, Unix domain sockets, and Windows + named pipes. The generic Connection class + supports all of these, figuring out which one you mean based on the + parameters you pass to + Connection::connect(). But if you know in + advance that your program only needs one particular connection type, + there are subclasses with simpler interfaces. For example, + there’s if you + know your program will always use a networked database + server. + + + + + The Query Object + + Most often, you create SQL queries using a object created by the + Connection object. + + Query acts as a standard C++ output + stream, so you can write data to it like you would to + std::cout or + std::ostringstream. This is the most C++ish + way MySQL++ provides for building up a query string. The library + includes stream + manipulators that are type-aware so it’s easy to build + up syntactically-correct SQL. + + Query also has a feature called which work something like C’s + printf() function: you set up a fixed query + string with tags inside that indicate where to insert the variable + parts. If you have multiple queries that are structurally similar, + you simply set up one template query, and use that in the various + locations of your program. + + A third method for building queries is to use + Query with + (SSQLS). This feature lets you create C++ structures that mirror + your database schemas. These in turn give + Query the information it needs to build many + common SQL queries for you. It can INSERT, + REPLACE and UPDATE rows in a + table given the data in SSQLS form. It can also generate + SELECT * FROM SomeTable queries and store the + results as an STL collection of SSQLSes. + + + + + Result Sets + + The field data in a result set are stored in a special + std::string-like class called . This class has conversion operators + that let you automatically convert these objects to any of the basic + C data types. Additionally, MySQL++ defines classes like , which you can initialize from a + MySQL DATETIME string. These automatic + conversions are protected against bad conversions, and can either + set a warning flag or throw an exception, depending on how you set + the library up. + + As for the result sets as a whole, MySQL++ has a number of + different ways of representing them: + + + Queries That Do Not Return Data + + Not all SQL queries return data. An example is + CREATE TABLE. For these types of queries, there + is a special result type () that simply reports the state resulting from + the query: whether the query was successful, how many rows it + impacted (if any), etc. + + + + Queries That Return Data: MySQL++ Data Structures + + The most direct way to retrieve a result set is to use + Query::store(). This returns a object, which derives + from std::vector<mysqlpp::Row>, + making it a random-access container of s. In turn, each Row object is + like a std::vector of + String objects, one for each field in the + result set. Therefore, you can treat + StoreQueryResult as a two-dimensional + array: you can get the 5th field on the 2nd row by simply saying + result[1][4]. You can also access row + elements by field name, like this: + result[2]["price"]. + + A less direct way of working with query results is to use + Query::use(), which returns a object. This class acts + like an STL input iterator rather than a + std::vector: you walk through your result + set processing one row at a time, always going forward. You + can’t seek around in the result set, and you can’t + know how many results are in the set until you find the end. In + payment for that inconvenience, you get better memory efficiency, + because the entire result set doesn’t need to be stored in + RAM. This is very useful when you need large result sets. + + + + Queries That Return Data: Specialized SQL + Structures + + Accessing results through MySQL++’s data structures is + a pretty low level of abstraction. It’s better than using + the MySQL C API, but not by much. You can elevate things a little + closer to the level of the problem space by using the (SSQLS) feature. This lets you define C++ + structures that match the table structures in your database + schema. In addition, it’s easy to use SSQLSes with regular + STL containers (and thus, algorithms) so you don’t have to + deal with the quirks of MySQL++’s data structures. + + The advantage of this method is that your program will + require very little embedded SQL code. You can simply execute a + query, and receive your results as C++ data structures, which can + be accessed just as you would any other structure. The results can + be accessed through the Row object, or you can ask the library to + dump the results into an STL container — sequential or + set-associative, it doesn’t matter — for you. Consider + this: + + +vector<stock> v; +query << "SELECT * FROM stock"; +query.storein(v); +for (vector<stock>::iterator it = v.begin(); it != v.end(); ++it) { + cout << "Price: " << it->price << endl; +} + + Isn’t that slick? + + If you don’t want to create SSQLSes to match your + table structures, as of MySQL++ v3 you can now use + Row here instead: + + +vector<mysqlpp::Row> v; +query << "SELECT * FROM stock"; +query.storein(v); +for (vector<mysqlpp::Row>::iterator it = v.begin(); it != v.end(); ++it) { + cout << "Price: " << it->at("price") << endl; +} + + It lacks a certain syntactic elegance, but it has its + uses. + + + + + + Exceptions + + By default, the library throws + whenever it encounters an error. You can ask the library to set + an error flag instead, if you like, but the exceptions carry more + information. Not only do they include a string member telling you + why the exception was thrown, there are several exception types, + so you can distinguish between different error types within a + single try block. + + ADDED doc/userman/section-template.dbx Index: doc/userman/section-template.dbx ================================================================== --- /dev/null +++ doc/userman/section-template.dbx @@ -0,0 +1,9 @@ + + + + + SECTION TITLE + + FIRST PARAGRAPH + ADDED doc/userman/ssqls.dbx Index: doc/userman/ssqls.dbx ================================================================== --- /dev/null +++ doc/userman/ssqls.dbx @@ -0,0 +1,635 @@ + + + + + Specialized SQL Structures + + The Specialized SQL Structure (SSQLS) feature lets you easily + define C++ structures that match the form of your SQL tables. Because + of the extra functionality that this feature builds into these + structures, MySQL++ can populate them automatically when retrieving + data from the database; with queries returning many records, you can + ask MySQL++ to populate an STL container of your SSQLS records with + the results. When updating the database, MySQL++ can use SSQLS + structures to match existing data, and it can insert SSQLS structures + directly into the database. + + You define an SSQLS using one of several macros defined in + ssqls.h. The following sections will discuss each + macro type separately, beginning with the easiest and most generally + useful. + + + + sql_create + + This is the most basic sort of SSQLS declaration: + + +sql_create_6(stock, 1, 6, + mysqlpp::sql_char, item, + mysqlpp::sql_bigint, num, + mysqlpp::sql_double, weight, + mysqlpp::sql_decimal, price, + mysqlpp::sql_date, sdate, + mysqlpp::Null<mysqlpp::sql_mediumtext>, description) + + This creates a C++ structure called + stock containing six member + variables (item, num, + weight, price, + sdate, and description), + along with some constructors and other useful member + functions. + + The parameter before each field name is the C++ data type + that will be used to hold that value in the SSQLS. MySQL++ has + a sql_* typedef for almost every data type MySQL + understands.MySQL++ doesn’t have typedefs + for some of the more exotic data types, like those for the + geospatial types. Patches to correct this will be thoughtfully + considered. While it’s possible to use + some regular C and C++ data types here, it’s safer to use + the ones MySQL++ defines, as they’re likely to be a better + match to the types used by the database server. Plus, if you use + the predefined types, you are assured that MySQL++ knows how to + do the data conversions between the C++ and SQL type systems. If + you use other data types and the C++ compiler can’t convert + it to one MySQL++ already understands, MySQL++ will throw a + exception. The + sql_* types are defined in MySQL++’s + sql_types.h header. The naming scheme is + easy to learn when you know the SQL data type names. + + Another thing you’ll notice above is the type of the + last column. We’ve wrapped it in MySQL++’s template, which enables it to take a + SQL null value in addition to the values the base data type allows. + For more on this topic, see . + + One of the generated constructors takes a reference to + a , allowing you to easily + populate a vector of stocks like so: + + +vector<stock> result; +query.storein(result); + + MySQL++ takes care of mapping result set data to SSQLS + fields. The SSQLS doesn’t have to have the same number + of fields as the result set, and the order of fields in the + result set doesn’t have to match the order of fields in + the SSQLS. Fields in the result set that don’t exist in the + SSQLS are just quietly dropped, and fields in the SSQLS for which + there is no data in the result get set to a default value. + + The general format of this set of macros is: + + +sql_create_#(NAME, COMPCOUNT, SETCOUNT, TYPE1, ITEM1, ... TYPE#, ITEM#) + + Where # is the number of member variables, + NAME is the name of the structure you wish to + create, TYPEx is the type of a member + variable, and ITEMx is that variable’s + name. + + The COMPCOUNT and + SETCOUNT arguments are described in the + next section. + + + + + SSQLS Comparison and Initialization + + sql_create_x adds + member functions and operators to each SSQLS that allow you to + compare one SSQLS instance to another. These functions compare the + first COMPCOUNT fields in the structure. In + the example above, COMPCOUNT is 1, so only + the item field will be checked when comparing two + stock structures. + + This feature works best when your table’s + “key” fields are the first ones in the SSQLS and + you set COMPCOUNT equal to the number + of key fields. That way, a check for equality between two SSQLS + structures in your C++ code will give the same results as a check + for equality in SQL. + + COMPCOUNT must + be at least 1. The current implementation of + sql_create_x cannot create + an SSQLS without comparison member functions. + + Because our stock structure + is less-than-comparable, you can use it in STL algorithms + and containers that require this, such as STL’s associative + containers: + + +std::set<stock> result; +query.storein(result); +cout << result.lower_bound(stock("Hamburger"))->item << endl; + + This will print the first item in the result set that begins + with “Hamburger.” + + The third parameter to + sql_create_x is + SETCOUNT. If this is nonzero, it adds + an initialization constructor and a set() + member function taking the given number of arguments, for setting + the first N fields of the structure. For + example, you could change the above example like so: + + +sql_create_5(stock, 1, 2, + mysqlpp::sql_char, item, + mysqlpp::sql_bigint, num, + mysqlpp::sql_double, weight, + mysqlpp::sql_decimal, price, + mysqlpp::sql_date, sdate) + +stock foo("Hotdog", 52); + + In addition to this 2-parameter constructor, this version + of the stock SSQLS will have a similar + 2-parameter set() member function. + + The COMPCOUNT and + SETCOUNT values cannot be equal. If they + are, the macro will generate two initialization constructors with + identical parameter lists, which is illegal in C++. You might be + asking, why does there need to be a constructor for comparison to + begin with? It’s often convenient to be able to say something + like x == stock("Hotdog"). This requires + that there be a constructor taking COMPCOUNT + arguments to create the temporary stock + instance used in the comparison. + + This limitation is not a problem in practice. If you + want the same number of parameters in the initialization + constructor as the number of fields used in comparisons, + pass 0 for SETCOUNT. This suppresses + the duplicate constructor you’d get if you used the + COMPCOUNT value instead. This is most + useful in very small SSQLSes, since it’s easier for the + number of key fields to equal the number of fields you want to + compare on: + + +sql_create_1(stock_item, 1, 0, mysqlpp::sql_char, item) + + + + + Additional Features of Specialized SQL + Structures + + Up to this point, we haven’t been using all of the + features in the SSQLS structures we’ve been generating. What + else can we do with SSQLSes? Consider this: + + +query.insert(s); + + This does exactly what you think it does: it builds + an INSERT query to insert the contents + of s into the database. You have only to + call query::execute() to actually + insert it. This is possible because SSQLSes have functions that + Query can call to get the list of fields + and such, which it uses to build the INSERT + query. query::update() and + query::replace() also rely on these + features. + + Another feature you might find a use for is changing the + table name MySQL++ uses to build queries involving SSQLSes. By + default, the database server table is assumed to have the same name + as the SSQLS structure type. But if this is inconvenient, you can + globally change the table name used in queries like this: + + +stock::table("MyStockData"); + + It’s also possible to change the name of a table on + a per-instance basis: + + +stock s; +s.instance_table("AlternateTable"); + + This is useful when you have an SSQLS definition that is + compatible with multiple tables, so the table name to use for each + instance is different. The simplest way this can happen is if the + tables all have identical definitions; it saves you from having + to define a separate SSQLS for each table. It is also useful for + mapping a class hierarchy onto a set of table definitions. The + common SSQLS definition is the “superclass” for a + given set of tables. + + Strictly speaking, you only need to use this feature in + multithreaded programs. Changing the static table name before + using each instance is safe if all changes happen within a single + thread. That said, it may still be convenient to change the name of + the table for an SSQLS instance in a single-threaded program if it + gets used for many operations over an extended span of code. + + + + + Using an SSQLS in Multiple Modules + + It’s convenient to define an SSQLS in a header file so + you can use it in multiple modules. You run into a bit of a + problem, though, because each SSQLS includes a few static data + members to hold information common to all structures of that + type. (The table name and the list of field names.) When you + #include that header in more than one module, + you get a multiply-defined symbol error at link time. + + The way around this is to define the preprocessor macro + MYSQLPP_SSQLS_NO_STATICS in all but + one of the modules that use the header definining the + SSQLS. When this macro is defined, it suppresses the static data + members in any SSQLS defined thereafter. + + Imagine we have a file my_ssqls.h which + includes a sql_create_N macro call to define an + SSQLS, and that that SSQLS is used in at least two modules. One + we’ll call foo.cpp, and we’ll say + it’s just a user of the SSQLS; it doesn’t + “own” it. Another of the modules, + my_ssqls.cpp uses the SSQLS more heavily, so + we’ve called it the owner of the SSQLS. If there aren’t + very many modules, this works nicely: + + +// File foo.cpp, which just uses the SSQLS, but doesn't "own" it: +#define MYSQLPP_SSQLS_NO_STATICS +#include "my_ssqls.h" + + +// File my_ssqls.cpp, which owns the SSQLS, so we just #include it directly +#include "my_ssqls.h" + + If there are many modules that need the SSQLS, adding all + those #defines can be a pain. In that case, + it’s easier if you flip the above pattern on its head: + + +// File my_ssqls.h: +#if !defined(EXPAND_MY_SSQLS_STATICS) +# define MYSQLPP_SSQLS_NO_STATICS +#endif +sql_create_X(Y, Z....) // the SSQLS definition + + +// File foo.cpp, a mere user of the SSQLS: +#include "my_ssqls.h" + + +// File my_ssqls.cpp, which owns the SSQLS: +#define EXPAND_MY_SSQLS_STATICS +#include "my_ssqls.h" + + + + + Harnessing SSQLS Internals + + The sql_create macros define several methods + for each SSQLS. These methods are mostly for use within the library, + but some of them are useful enough that you might want to harness + them for your own ends. Here is some pseudocode showing how the most + useful of these methods would be defined for the + stock structure used in all the + ssqls*.cpp examples: + + +// Basic form +template <class Manip> +stock_value_list<Manip> value_list(cchar *d = ",", + Manip m = mysqlpp::quote) const; + +template <class Manip> +stock_field_list<Manip> field_list(cchar *d = ",", + Manip m = mysqlpp::do_nothing) const; + +template <class Manip> +stock_equal_list<Manip> equal_list(cchar *d = ",", + cchar *e = " = ", Manip m = mysqlpp::quote) const; + + +// Boolean argument form +template <class Manip> +stock_cus_value_list<Manip> value_list([cchar *d, [Manip m,] ] + bool i1, bool i2 = false, ... , bool i5 = false) const; + +// List form +template <class Manip> +stock_cus_value_list<Manip> value_list([cchar *d, [Manip m,] ] + stock_enum i1, stock_enum i2 = stock_NULL, ..., + stock_enum i5 = stock_NULL) const; + +// Vector form +template <class Manip> +stock_cus_value_list<Manip> value_list([cchar *d, [Manip m,] ] + vector<bool> *i) const; + +...Plus the obvious equivalents for field_list() and equal_list() + + Rather than try to learn what all of these methods do at + once, let’s ease into the subject. Consider this code: + + +stock s("Dinner Rolls", 75, 0.95, 0.97, sql_date("1998-05-25")); +cout << "Value list: " << s.value_list() << endl; +cout << "Field list: " << s.field_list() << endl; +cout << "Equal list: " << s.equal_list() << endl; + + That would produce something like: + + +Value list: 'Dinner Rolls',75,0.95,0.97,'1998-05-25' +Field list: item,num,weight,price,sdate +Equal list: item = 'Dinner Rolls',num = 75,weight = 0.95, price = 0.97,sdate = '1998-05-25' + + That is, a “value list” is a list of data member + values within a particular SSQLS instance, a “field + list” is a list of the fields (columns) within that SSQLS, and + an “equal list” is a list in the form of an SQL equals + clause. + + Just knowing that much, it shouldn’t surprise you to + learn that Query::insert() is implemented + more or less like this: + + +*this << "INSERT INTO " << v.table() << " (" << v.field_list() << + ") VALUES (" << v.value_list() << ")"; + + where ‘v’ is the SSQLS you’re asking the + Query object to insert into the database. + + Now let’s look at a complete example, which uses one of + the more complicated forms of equal_list(). + This example builds a query with fewer hard-coded strings than the + most obvious technique requires, which makes it more robust in the + face of change. Here is + examples/ssqls5.cpp: + + + + This example uses the list form of + equal_list(). The arguments + stock_weight and stock_price + are enum values equal to the position of these columns within the + stock table. + sql_create_x generates this + enum for you automatically. + + The boolean argument form of that + equal_list() call would look like + this: + + +query << "select * from stock where " << + res[0].equal_list(" and ", false, false, true, true, false); + + It’s a little more verbose, as you can see. And if you want + to get really complicated, use the vector form: + + +vector<bool> v(5, false); +v[stock_weight] = true; +v[stock_price] = true; +query << "select * from stock where " << + res[0].equal_list(" and ", v); + + This form makes the most sense if you are building many other + queries, and so can re-use that vector object. + + Many of these methods accept manipulators and custom + delimiters. The defaults are suitable for building SQL queries, but + if you’re using these methods in a different context, you may + need to override these defaults. For instance, you could use these + methods to dump data to a text file using different delimiters and + quoting rules than SQL. + + At this point, we’ve seen all the major aspects of the + SSQLS feature. The final sections of this chapter look at some of + the peripheral aspects. + + + + + Having Different Field Names in C++ and SQL + + There’s a more advanced SSQLS creation macro, + which all the others are built on top of. Currently, the only + feature it adds over what’s described above is that it + lets you name your SSQLS fields differently from the names + used by the database server. Perhaps you want to use Hungarian + notation in your C++ program without changing the SQL + database schema: + + +sql_create_complete_5(stock, 1, 5, + mysqlpp::sql_char, item, "m_sItem", + mysqlpp::sql_bigint, num, "m_nNum", + mysqlpp::sql_double, weight, "m_fWeight", + mysqlpp::sql_decimal, price, "m_fPrice", + mysqlpp::sql_date, sdate, "m_Date") + + + + + Expanding SSQLS Macros + + If you ever need to see the code that a given + SSQLS declaration expands out to, use the utility + doc/ssqls-pretty, like so: + + +doc/ssqls-pretty < myprog.cpp |less + + This Perl script locates the first SSQLS declaration in that + file, then uses the C++ preprocessor to expand that macro. (The + script assumes that your system’s preprocessor is called + cpp, and that its command line interface + follows Unix conventions.) + + If you run it from the top MySQL++ directory, as shown above, + it will use the header files in the distribution’s + lib subdirectory. Otherwise, it assumes the + MySQL++ headers are in their default location, + /usr/include/mysql++. If you want to use + headers in some other location, you’ll need to change the + directory name in the -I flag at the top of the + script. + + + + + Customizing the SSQLS Mechanism + + The SSQLS header ssqls.h is automatically + generated by the Perl script ssqls.pl. Although + it is possible to change this script to get additional + functionality, most of the time it’s better to just derive a + custom class from the stock SSQLS and add your additional + functionality that way. + + That said, ssqls.pl does have a few + configurables you might want to tweak. + + The first configurable value sets the maximum number of data + members allowed in an SSQLS. It’s 25 out of the box, set by + the $max_data_members variable at the top of + ssqls.pl. Beware, making this value larger + increases the size of ssqls.h exponentially; + this will increase compile time, and can even expose limits in your + compiler. Before you increase this value, take a good, hard look at + your database schema and ask if it’s really the best design. + Almost always, having so many columns is a sign that you need to + refactor the table. + + The second configurable is the default floating point + precision used for comparison. As described above () SSQLSes can be compared for + equality. The only place this is tricky is with floating-point + numbers, since rounding errors can make two “equal” + values compare as distinct. Since exact comparison makes no sense + with floating-point values, MySQL++ lets you specify the precision + you want it to use. If the difference between two values is under a + given threshold, MySQL++ considers the values equal. The default + threshold is 0.00001. This threshold works well for + “human” scale values, but because of the way + floating-point numbers work, it can be wildly inappropriate for very + large or very small quantities like those used in scientific + applications. + + There are actually two ways to change this threshold. If you + need a different system-wide default, edit + ssqls.pl and change the + $fp_min_delta variable at the top of the file, + then rebuild ssqls.h as described below. If you + need different thresholds per file or per project, it’s better + to set the C macro MYSQLPP_FP_MIN_DELTA instead. + The Perl variable sets this macro’s default; if you give a + different value before #including ssqls.h, it + will use that instead. + + To rebuild ssqls.h after changing + ssqls.pl, you’ll need a Perl interpreter. + The only modern Unixy system I’m aware of where Perl + isn’t installed by default is Cygwin, and it’s just a + setup.exe choice away there. You’ll + probably only have to download and install a Perl interpreter if + you’re on Windows and don’t want to use Cygwin. + + If you’re on a system that uses autoconf, building + MySQL++ automatically updates ssqls.h any time + ssqls.pl changes. Otherwise, you’ll need + to run the Perl interpreter by hand: + + c:\mysql++> cd lib +c:\lib> perl ssqls.pl + + + + + SSQLS and BLOB Columns + + It takes special care to use SSQLS with BLOB columns. + It’s safest to declare the SSQLS field as of type + mysqlpp::sql_blob. This is currently a + typedef alias for String, which is the form the data is in just + before the SSQLS mechanism populates the structure. Thus, when the + data is copied from the internal MySQL++ data structures into your + SSQLS, you get a direct copy of the String + object’s contents, without interference. + + Because C++ strings handle binary data just fine, you might + think you can use std::string instead of + sql_blob, but the current design of + String converts to + std::string via a C string. As a result, the + BLOB data is truncated at the first embedded null character during + population of the SSQLS. There’s no way to fix that without + completely redesigning either String or the + SSQLS mechanism. + + The sql_blob typedef may be changed to + alias a different type in the future, so using it instead of + String ensures that your code tracks these + library changes automatically. Besides, + String is only intended to be an internal + mechanism within MySQL++. The only reason the layering is so thin + here is because it’s the only way to prevent BLOB data from + being corrupted while avoiding that looming redesign effort. + + You can see this technique in action in the + cgi_jpeg example: + + + + + + + SSQLS and Visual C++ 2003 + + SSQLS works on all platforms supported by MySQL++ except for + Visual C++ 2003. (Because the rest of MySQL++ works just fine with + Visual C++ 2003, we haven’t removed this platform from the + supported list entirely.) + + If you do need SSQLS and are currently on Visual C++ 2003, you + have these options: + + + The simplest option is to upgrade to a newer + version of Visual C++. The compiler limitations that break SSQLS + are all fixed in Visual C++ 2005 and newer. Visual C++ + Express is free and is apparently here to stay; coupled + with the free wxWidgets + library, it lacks little compared to Visual C++ Professional. A + bonus of using wxWidgets is that it’s cross-platform and + better-supported than MFC. + + If you can’t upgrade your compiler, you may + be able to downgrade to MySQL++ v2.x. The + SSQLS feature in these older versions worked with Visual C++ 2003, + but didn’t let you use a given SSQLS in more than one module + in a program. If you can live with that limitation and have a Perl + interpreter on your system, you can re-generate + lib/ssqls.h to remove the multiple-module + SSQLS support. To do this, you run the command perl + ssqls.pl -v from within MySQL++’s + lib subdirectory before you build and install + the library. + + There’s a + plan to replace the current SSQLS mechanism with an + entirely new code base. Although this is being done primary to get + new features that are too difficult to add within the current + design, it also means we’ll have the chance to test + step-by-step along the way that we don’t reintroduce code + that Visual C++ 2003 doesn’t support. This may happen + without you doing anything, but if there’s someone on the + team who cares about this, that will naturally increase the + chances that it does happen. + + + ADDED doc/userman/threads.dbx Index: doc/userman/threads.dbx ================================================================== --- /dev/null +++ doc/userman/threads.dbx @@ -0,0 +1,323 @@ + + + + + Using MySQL++ in a Multithreaded Program + + MySQL++ is not “thread safe” in any + meaningful sense. MySQL++ contains very little code that + actively prevents trouble with threads, and all of it is + optional. We have done some work in MySQL++ to make thread + safety achievable, but it doesn’t come + for free. + + The main reason for this is that MySQL++ is + generally I/O-bound, not processor-bound. That is, if + your program’s bottleneck is MySQL++, the ultimate + cause is usually the I/O overhead of using a client-server + database. Doubling the number of threads will just let your + program get back to waiting for I/O twice as fast. Since threads + are evil and generally can’t help MySQL++, the only + optional thread awareness features we turn on in the shipping + version of MySQL++ are those few that have no practical negative + consequences. Everything else is up to you, the programmer, to + evaluate and enable as and when you need it. + + We’re going to assume that you either agree with these + views but find yourself needing to use threads for some other + reason, or are foolishly disregarding these facts and are going to + use threads anyway. Our purpose here is limited to setting down + the rules for avoiding problems with MySQL++ in a multi-threaded + program. We won’t go into the broader issues of thread safety + outside the scope of MySQL++. You will need a grounding in threads + in general to get the full value of this advice. + + + Build Issues + + Before you can safely use MySQL++ with threads, there are + several things you must do to get a thread-aware build: + + + + Build MySQL++ itself with thread awareness + turned on. + + On Linux, Cygwin and Unix (OS X, *BSD, Solaris...), + pass the --enable-thread-check + flag to the configure script. Beware, this + is only a request to the configure script + to look for thread support on your system, not a requirement + to do or die: if the script doesn’t find what it needs + to do threading, MySQL++ will just get built without thread + support. See README-Unix.txt for more + details. + + On Windows, if you use the Visual C++ project files or + the MinGW Makefile that comes with the MySQL++ distribution, + threading is always turned on, due to the nature of + Windows. + + If you build MySQL++ in some other way, such as with + Dev-Cpp (based on MinGW) you’re on your own to enable + thread awareness. + + + + Link your program to a thread-aware build of the + MySQL C API library. + + If you use a binary distribution of MySQL on Unixy + systems, you usually get two different versions of the MySQL + C API library, one with thread support and one without. These + are typically called libmysqlclient and + libmysqlclient_r, the latter being the + thread-safe one. (The “_r” + means reentrant.) + + If you’re using the Windows binary distribution of + MySQL, there are two versions of the client library, but both + are thread aware. One just has debugging symbols, and the other + doesn’t. See README-Visual-C++.txt + or README-MinGW.txt for details. + + If you build MySQL from source, you might only get + one version of the MySQL C API library, and it can have + thread awareness or not, depending on your configuration + choices. This is the case with Cygwin, where you currently + have no choice but to build the C API library from source. (See + README-Cygwin.txt.) + + + + Enable threading in your program’s build + options. + + This is different for every platform, but it’s + usually the case that you don’t get thread-aware builds + by default. Depending on the platform, you might need to change + compiler options, linker options, or both. See your development + environment’s documentation, or study how MySQL++ itself + turns on thread-aware build options when requested. + + + + + + + Connection Management + + The MySQL C API underpinning MySQL++ does not allow multiple + concurrent queries on a single connection. You can run into this + problem in a single-threaded program, too, which is why we cover the + details elsewhere, in . + It’s a thornier problem when using threads, though. + + The simple fix is to just create a separarate object for each thread + that needs to make database queries. This works well if you + have a small number of threads that need to make queries, and + each thread uses its connection often enough that the server + doesn’t time out waiting for queries.By + default, current MySQL servers have an 8 hour idle timeout on + connections. It’s a configuration option, though, so your + server may be set differently. + + If you have lots of threads or the frequency of queries is + low, the connection management overhead will be excessive. To avoid + that, we created the + class. It manages a pool of Connection + objects like library books: a thread checks one out, uses it, + and then returns it to the pool as soon as it’s done with + it. This keeps the number of active connections low. + + ConnectionPool has three + methods that you need to override in a subclass to + make it concrete: create(), + destroy(), and + max_idle_time(). These overrides let + the base class delegate operations it can’t successfully do + itself to its subclass. The ConnectionPool + can’t know how to create() + the Connection objects, because that + depends on how your program gets login parameters, server + information, etc. ConnectionPool + also makes the subclass destroy() + the Connection objects it created; it + could assume that they’re simply allocated on the heap + with new, but it can’t be sure, + so the base class delegates destruction, too. Finally, the base + class can’t know what the connection idle timeout policy + in the client would make the most sense, so it asks its subclass + via the max_idle_time() method. + + ConnectionPool also allows you to + override release(), if needed. For simple + uses, it’s not necessary to override this. + + In designing your ConnectionPool + derivative, you might consider making it a Singleton (see Gamma + et al.), since there should only be one pool in a program. + + Here is an example showing how to use connection pools with + threads: + + + + The example works with both Windows native + threads and with POSIX threads.The file + examples/threads.h contains a few macros and + such to abstract away the differences between the two threading + models. Because thread-enabled builds are only + the default on Windows, it’s quite possible for this program + to do nothing on other platforms. See above for instructions on + enabling a thread-aware build. + + If you write your code without checks for thread support + like you see in the code above and link it to a build of MySQL++ + that isn’t thread-aware, it will still try to run. The + threading mechanisms fall back to a single-threaded mode when + threads aren’t available. A particular danger is that the + mutex lock mechanism used to keep the pool’s internal data + consistent while multiple threads access it will just quietly + become a no-op if MySQL++ is built without thread support. We do + it this way because we don’t want to make thread support + a MySQL++ prerequisite. And, although it would be of limited + value, this lets you use ConnectionPool + in single-threaded programs. + + You might wonder why we don’t just work around + this weakness in the C API transparently in MySQL++ instead of + suggesting design guidelines to avoid it. We’d like to do + just that, but how? + + If you consider just the threaded case, you could argue for + the use of mutexes to protect a connection from trying to execute + two queries at once. The cure is worse than the disease: it turns a + design error into a performance sap, as the second thread is blocked + indefinitely waiting for the connection to free up. Much better to + let the program get the “Commands out of sync” error, + which will guide you to this section of the manual, which tells you + how to avoid the error with a better design. + + Another option would be to bury + ConnectionPool functionality within MySQL++ + itself, so the library could create new connections at need. + That’s no good because the above example is the most complex + in MySQL++, so if it were mandatory to use connection pools, the + whole library would be that much more complex to use. The whole + point of MySQL++ is to make using the database easier. MySQL++ + offers the connection pool mechanism for those that really need it, + but an option it must remain. + + + + + Helper Functions + + Connection has several thread-related + static methods you might care about when using MySQL++ with + threads. + + You can call + Connection::thread_aware() to + determine whether MySQL++ and the underlying C API library + were both built to be thread-aware. Again, I stress that thread + awareness is not the same thing as thread + safety: it’s still up to you to + make your code thread-safe. If this method returns true, it + just means it’s possible to achieve + thread-safety. + + If your program’s connection-management strategy allows + a thread to use a Connection object that + another thread created before it creates a connection of its own, + you must call Connection::thread_start() + from that thread before it does anything with MySQL++. If a + thread creates a new connection before it uses a connection + created by another thread, though, it doesn’t need to call + Connection::thread_start() because the + per-thread resources this allocates are implicitly created upon + creation of a connection if necessary. + + This is why the simple + Connection-per-thread strategy + works: each thread that uses MySQL++ creates a connection + in that thread, implicitly allocating the per-thread + resources at the same time. You never need to call + Connection::thread_start() in this + instance. It’s not harmful to call this function, just + unnecessary. + + A good counterexample is using + ConnectionPool: you probably do need + to call Connection::thread_start() + at the start of each worker thread because you can’t + usually tell whether you’re getting a new connection + from the pool, or reusing one that another thread returned + to the pool after allocating it. It’s possible to + conceive of situations where you can guarantee that each pool + user always allocates a fresh connection the first time it + calls ConnectionPool::grab(), + but thread programming is complex enough that + it’s best to take the safe path and always call + Connection::thread_start() early in each + worker thread. + + Finally, there’s the complementary method, + Connection::thread_end(). Strictly + speaking, it’s not necessary to call + this. The per-thread memory allocated by the C API is small, + it doesn’t grow over time, and a typical thread is going + to need this memory for its entire run time. Memory debuggers + aren’t smart enough to know all this, though, so they will + gripe about a memory leak unless you call this from each thread + that uses MySQL++ before that thread exits. + + Although its name suggests otherwise, + Connection::thread_id() has nothing to + do with anything in this chapter. + + + + + Sharing MySQL++ Data Structures + + We’re in the process of making it safer to share + MySQL++’s data structures across threads. + + By way of illustration, let me explain a problem we had up + until MySQL++ v3.0. When you issue a database query that returns + rows, you also get information about the columns in each row. Since + the column information is the same for each row in the result set, + older versions of MySQL++ kept this information in the result set + object, and each kept a pointer + back to the result set object that created it so it could access + this common data at need. This was fine as long as each result set + object outlived the Row objects it returned. + It required uncommon usage patterns to run into trouble in this area + in a single-threaded program, but in a multi-threaded program it was + easy. For example, there’s frequently a desire to let one + connection do the queries, and other threads process the results. + You can see how avoiding lifetime problems here would require a + careful locking strategy. + + We got around this in MySQL++ v3.0 by giving these shared data + structures a lifetime independent of the result set object that + intitially creates it. These shared data structures stick around + until the last object needing them gets destroyed. + + Although this is now a solved problem, I bring it up because + there are likely other similar lifetime and sequencing problems + waiting to be discovered inside MySQL++. If you would like to help + us find these, by all means, share data between threads willy-nilly. + We welcome your crash reports on the MySQL++ mailing list. But if + you’d prefer to avoid problems, it’s better to keep all + data about a query within a single thread. Between this and the + previous section’s advice, you should be able to use threads + with MySQL++ without trouble. + + ADDED doc/userman/tquery.dbx Index: doc/userman/tquery.dbx ================================================================== --- /dev/null +++ doc/userman/tquery.dbx @@ -0,0 +1,224 @@ + + + + + Template Queries + + Another powerful feature of MySQL++ is being able to set up + template queries. These are kind of like C’s + printf() facility: you give MySQL++ a string + containing the fixed parts of the query and placeholders for the + variable parts, and you can later substitute in values into those + placeholders. + + The following program demonstrates how to use this feature. This + is examples/tquery1.cpp: + + + + The line just before the call to + query.parse() sets the template, and the + parse call puts it into effect. From that point on, you can re-use + this query by calling any of several Query member functions that + accept query template parameters. In this example, we’re using + Query::execute(). + + Let’s dig into this feature a little deeper. + + + + Setting up Template Queries + + To set up a template query, you simply insert it into the + Query object, using numbered placeholders wherever you want to be + able to change the query. Then, you call the parse() function to + tell the Query object that the query string is a template query, + and it needs to parse it: + + +query << "select (%2:field1, %3:field2) from stock where %1:wheref = %0q:what"; +query.parse(); + + The format of the placeholder is: + + +%###(modifier)(:name)(:) + + Where “###” is a number up to three digits. It is + the order of parameters given to a object, starting from 0. + + “modifier” can be any one of the following: + +
+ + + + + + % + + Print an actual “%” + + + + "" + + Don’t quote or escape no matter what. + + + + q + + This will escape the item using the MySQL C API + function + and add single quotes around it as necessary, depending on + the type of the value you use. + + + + Q + + Quote but don’t escape based on the same rules as + for “q”. This can save a bit of processing time if + you know the strings will never need quoting + + + + +
+ + “:name” is for an optional name which aids in + filling SQLQueryParms. Name can contain any alpha-numeric characters + or the underscore. You can have a trailing colon, which will be + ignored. If you need to represent an actual colon after the name, + follow the name with two colons. The first one will end the name and + the second one won’t be processed. +
+ + + + Setting the Parameters at Execution Time + + To specify the parameters when you want to execute a query + simply use Query::store(const SQLString &parm0, + [..., const SQLString &parm11]). This type of + multiple overload also exists for + Query::storein(), + Query::use() and + Query::execute(). “parm0” + corresponds to the first parameter, etc. You may specify up to 25 + parameters. For example: + + +StoreQueryResult res = query.store("Dinner Rolls", "item", "item", "price") + + with the template query provided above would produce: + + +select (item, price) from stock where item = "Dinner Rolls" + + The reason we didn’t put the template parameters in + numeric order... + + +select (%0:field1, %1:field2) from stock where %2:wheref = %3q:what + + ...will become apparent shortly. + + + + + Default Parameters + + The template query mechanism allows you to set default + parameter values. You simply assign a value for the parameter to the + appropriate position in the + Query::template_defaults array. You can refer to + the parameters either by position or by name: + + +query.template_defaults[1] = "item"; +query.template_defaults["wheref"] = "item"; + + Both do the same thing. + + This mechanism works much like C++’s default function + parameter mechanism: if you set defaults for the parameters at the + end of the list, you can call one of + Query’s query execution methods without + passing all of the values. If the query takes four parameters and + you’ve set defaults for the last three, you can execute the + query using as little as just one explicit parameter. + + Now you can see why we numbered the template query parameters + the way we did a few sections earlier. We ordered them so that the + ones less likely to change have higher numbers, so we don’t + always have to pass them. We can just give them defaults and take + those defaults when applicable. This is most useful when some + parameters in a template query vary less often than other + parameters. For example: + + +query.template_defaults["field1"] = "item"; +query.template_defaults["field2"] = "price"; +StoreQueryResult res1 = query.store("Hamburger Buns", "item"); +StoreQueryResult res2 = query.store(1.25, "price"); + + This stores the result of the following queries in + res1 and res2, + respectively: + + +select (item, price) from stock where item = "Hamburger Buns" +select (item, price) from stock where price = 1.25 + + Default parameters are useful in this example because we have + two queries to issue, and parameters 2 and 3 remain the same for + both, while parameters 0 and 1 vary. + + Some have been tempted into using this mechanism as a way to + set all of the template parameters in a query: + + +query.template_defaults["what"] = "Hamburger Buns"; +query.template_defaults["wheref"] = "item"; +query.template_defaults["field1"] = "item"; +query.template_defaults["field2"] = "price"; +StoreQueryResult res1 = query.store(); + + This can work, but it is not designed to. + In fact, it’s known to fail horribly in one common case. You + will not get sympathy if you complain on the mailing list about it + not working. If your code doesn’t actively reuse at least one + of the parameters in subsequent queries, you’re abusing + MySQL++, and it is likely to take its revenge on you. + + + + + Error Handling + + If for some reason you did not specify all the parameters when + executing the query and the remaining parameters do not have their + values set via Query::template_defaults, the + query object will throw a object. If this happens, you can get an + explanation of what happened by calling + BadParamCount::what(), like so: + + +query.template_defaults["field1"] = "item"; +query.template_defaults["field2"] = "price"; +StoreQueryResult res = query.store(1.25); + + This would throw BadParamCount because + the wheref is not specified. + + In theory, this exception should never be thrown. If the + exception is thrown it probably a logic error in your + program. + +
ADDED doc/userman/tutorial.dbx Index: doc/userman/tutorial.dbx ================================================================== --- /dev/null +++ doc/userman/tutorial.dbx @@ -0,0 +1,1269 @@ + + + + + Tutorial + + This tutorial is meant to give you a jump start in using + MySQL++. While it is a very complicated and powerful library, + it’s possible to make quite functional programs without tapping + but a fraction of its power. This section will introduce you to the + most useful fraction. + + This tutorial assumes you know C++ fairly well, in particular + the Standard Template Library (STL) and exceptions. + + + + Running the Examples + + All of the examples are complete running programs. If you + built the library from source, the examples should have been built + as well. If you use RPMs instead, the example programs’ source + code and a simplified Makefile are in the + mysql++-devel package. They are typically + installed in + /usr/share/doc/mysql++-devel-*/examples, but it + can vary on different Linuxes. + + Before you get started, please read through any of the + README* files included with the MySQL++ + distribution that are relevant to your platform. We won’t + repeat all of that here. + + Most of the examples require a test database, created by + resetdb. You can run it like so: + + resetdb [-s server_addr] [-u user] [-p password] + + Actually, there’s a problem with that. It assumes that + the MySQL++ library is already installed in a directory that the + operating system’s dynamic linker can find. (MySQL++ is almost + never built statically.) Unless you’re installing from RPMs, + you’ve had to build the library from source, and you should + run at least a few of the examples before installing the library to + be sure it’s working correctly. Since your operating + system’s dynamic linkage system can’t find the MySQL++ + libraries without help until they’re installed, we’ve + created a few helper scripts to help run the examples. + + MySQL++ comes with the exrun shell script + for Unixy systems, and the exrun.bat batch file + for Windows. You pass the example program and its arguments to the + exrun helper, which sets up the library search + path so that it will find the as-yet uninstalled version of the + MySQL++ library first. So on a Unixy system, the above command + becomes: + + ./exrun resetdb [-s server_addr] [-u user] [-p password] + + See README.examples for more + details. + + All of the program arguments are optional. + + If you don’t give , the underlying + MySQL C API assumes the server is on the local machine. Depending + on how the C API library and the server are configured, it can use + any of several different IPC methods to contact the server. You can + instead specify how to contact the server yourself, with the method + depending on the value you give for the server address: + + + + localhost — this is the + default; it doesn’t buy you anything + + + + On Windows, a simple period tells the underlying MySQL C + API to use named pipes, if it’s available. + + + + 172.20.0.252:12345 + — this would connect to IP address + 172.20.0.252 on TCP port + 12345. + + + + my.server.name:svc_name — this + would first look up TCP service name + svc_name in your system’s + network services database (/etc/services on + Unixy systems, and something like + c:\windows\system32\drivers\etc\services on + modern Windows variants). If it finds an entry for the service, + it then tries to connect to that port on the domain name + given. + + + + You can mix symbolic host and service names in any + combination. If the name doesn’t contain a colon, it uses the + default port, 3306. + + If you don’t give , it assumes your + user name on the local machine is the same as your user name on the + database server. + + If you don’t give , it will assume + the MySQL user doesn’t have a password, which had better not + be the case. It’s a wild world out there; play safe, + kids. + + A typical invocation is: + + exrun.bat resetdb -u mydbuser -p nunyabinness + + For resetdb, the user name needs to be + for an account with permission to create databases. Once the + database is created, you can use any account that has read and write + permissions for the sample database, + mysql_cpp_data. + + You may also have to re-run resetdb + after running some of the other examples, as they change the + database. + + + + + A Simple Example + + The following example demonstrates how to open a connection, + execute a simple query, and display the results. This is + examples/simple1.cpp: + + + + This example simply gets the entire "item" column from the + example table, and prints those values out. + + Notice that MySQL++’s derives from + std::vector, and provides an interface that makes it a + vector work-alike. This means you can access + elements with subscript notation, walk through them with iterators, + run STL algorithms on them, etc. + + Row provides a little more in this area + than a plain old vector: you can also access + fields by name using subscript notation. + + The only thing that isn’t explicit in the code above is + that we delegate command line argument parsing to + parse_command_line() in the + excommon module. This function exists to give + the examples a consistent interface, not to hide important details. + You can treat it like a black box: it takes argc + and argv as inputs and sends back database + connection parameters. + + + + + A More Complicated Example + + The simple1 example above was pretty + trivial. Let’s get a little deeper. Here is + examples/simple2.cpp: + + + + The main point of this example is that we’re accessing + fields in the row objects by name, instead of index. This is slower, + but obviously clearer. We’re also printing out the entire + table, not just one column. + + + + + #including MySQL++ Headers + + You’ll notice above that we’re including + mysql++.h in the examples. There are many + headers in MySQL++, but this brings in all but one of them for you. + MySQL++ has a pretty cohesive design: it doesn’t have very + many pieces that are truly independent of the others. So, + there’s not much advantage in including the few headers you + think you need individually: you’re likely to also drag in all + the rest indirectly. + + The one header that mysql++.h + doesn’t + bring in for you is ssqls.h, which is only + useful if you use the optional + feature. + + By default on Unixy systems, MySQL++ installs its headers into + a mysql++ subdirectory of one of the main + system include directories, either /usr/include + or /usr/local/include. Since it’s typical + for either or both of these directories to be in your + program’s include path already, you might be wondering if you + can include the main MySQL++ header like this: + + #include <mysql++/mysql++.h> + + The answer is, yes you can. You don’t need to do anything + special to make it work. + + Since MySQL is usually installed in much the same way + (/usr/include/mysql is common, for example), + you might then ask if you can get away without having the MySQL C + API header directory to your program’s include path. You can, + but mysql++.h requires a little help from your + program to find the C API headers when you do this: + + #define MYSQLPP_MYSQL_HEADERS_BURIED +#include <mysql++/mysql++.h> + + This tells it to prefix all includes for C API headers with + mysql/. + + + + + Exceptions + + By default, MySQL++ uses exceptions to signal errors. Most + of the examples have a full set of exception handlers. This is + worthy of emulation. + + All of MySQL++’s custom exceptions + derive from a common base class, . That in turn derives from Standard C++’s + std::exception class. Since the library + can indirectly cause exceptions to come from the Standard + C++ Library, it’s possible to catch all exceptions from + MySQL++ by just catching std::exception. + However, it’s better to have individual catch blocks + for each of the concrete exception types that you expect, and + add a handler for either Exception + or std::exception to act as a + “catch-all” for unexpected exceptions. + + Most of these exceptions are optional. When exceptions + are disabled on a MySQL++ object, it signals errors in some + other way, typically by returning an error code or setting + an error flag. Classes that support this feature derive from + . Moreover, + when such an object creates another object that also derives from + this interface, it passes on its exception flag. Since everything + flows from the object, + disabling exceptions on it at the start of the program disables + all optional exceptions. You can see this technique at work in + the simple[1-3] examples, which keeps them, + well, simple. + + Real-world code typically can’t afford to lose + out on the additional information and control offered by + exceptions. But at the same time, it is still sometimes useful + to disable exceptions temporarily. To do this, put the section + of code that you want to not throw exceptions inside a block, + and create a object + at the top of that block. When created, it saves the exception + flag of the OptionalExceptions derivative + you pass to it, and then disables exceptions on it. When the + NoExceptions object goes out of scope + at the end of the block, it restores the exceptions flag to its + previous state: + + mysqlpp::Connection con(...); // exceptions enabled + +{ + mysqlpp::NoExceptions ne(con); + if (!con.select_db("a_db_that_might_not_exist_yet")) { + // Our DB doesn't exist yet, so create and select it here; no need + // to push handling of this case way off in an exception handler. + } +} + + When one OptionalExceptions derivative + passes its exceptions flag to another such object, it is only + passing a copy; the two objects’ flags operate independently. + There’s no way to globally enable or disable this flag on + existing objects in a single call. If you’re using the + NoExceptions feature and you’re + still seeing optional exceptions thrown, you disabled exceptions + on the wrong object. The exception thrower could be unrelated to + the object you disabled exceptions on, it could be its parent, + or it could be a child created before you disabled optional + exceptions. + + MySQL++ throws some exceptions unconditionally: + + + The largest set of non-optional exceptions are + those from the Standard C++ Library. For instance, if your code + said “row[21]” on a row containing + only 5 fields, the std::vector underlying + the row object will throw an exception. (It will, that is, if it + conforms to the standard.) You might consider wrapping your + program’s main loop in a try block catching + std::exceptions, just in case you trigger + one of these exceptions. + + will always + throw when you ask it + to do an improper type conversion. For example, you’ll get + an exception if you try to convert “1.25” to + int, but not when you convert “1.00” to + int. In the latter case, MySQL++ knows that it can + safely throw away the fractional part. + + If you use template queries and don’t pass + enough parameters when instantiating the template, + Query will throw a exception. + + If you use a C++ data type in a query + that MySQL++ doesn’t know to convert to SQL, MySQL++ + will throw a + exception. It typically happens with , + especially when using data types other than the ones defined + in lib/sql_types.h. + + + It’s educational to modify the examples to force + exceptions. For instance, misspell a field name, use an out-of-range + index, or change a type to force a String + conversion error. + + + + + Quoting and Escaping + + SQL syntax often requires certain data to be quoted. Consider + this query: + + +SELECT * FROM stock WHERE item = 'Hotdog Buns' + + Because the string “Hotdog Buns” contains a space, + it must be quoted. With MySQL++, you don’t have to add these + quote marks manually: + + +string s = "Hotdog Buns"; +query << "SELECT * FROM stock WHERE item = " << quote_only << s; + + That code produces the same query string as in the previous + example. We used the MySQL++ quote_only manipulator, + which causes single quotes to be added around the next item inserted + into the stream. This works for any type of data that can be + converted to MySQL++’s SQLTypeAdapter type, plus the template. + also use these manipulators internally. + + Quoting is pretty simple, but SQL syntax also often requires + that certain characters be “escaped”. Imagine if the + string in the previous example was “Frank's Brand Hotdog + Buns” instead. The resulting query would be: + + +SELECT * FROM stock WHERE item = 'Frank's Brand Hotdog Buns' + + That’s not valid SQL syntax. The correct syntax is: + + +SELECT * FROM stock WHERE item = 'Frank''s Brand Hotdog Buns' + + As you might expect, MySQL++ provides that feature, too, + through its escape manipulator. But here, we want both + quoting and escaping. That brings us to the most widely useful + manipulator: + + +string s = "Frank's Brand Hotdog Buns"; +query << "SELECT * FROM stock WHERE item = " << quote << s; + + The quote manipulator both quotes strings and + escapes any characters that are special in SQL. + + MySQL++ provides other manipulators as well. See the manip.h page in the reference manual. + + It’s important to realize that MySQL++’s quoting + and escaping mechanism is type-aware. Manipulators have no effect + unless you insert the manipulator into a + Query or SQLQueryParms stream. + SQLQueryParms is used as a + stream only as an implementation detail within the library. End user + code simply sees it as a std::vector + derivative. Also, values are only quoted and/or + escaped if they are of a data type that may need it. For example, + Date must be quoted but + never needs to be escaped, and integer types need neither quoting + nor escaping. Manipulators are suggestions to the library, not + commands: MySQL++ will ignore these suggestions if it knows it + won’t result in syntactically-incorrect SQL. + + It’s also important to realize that quoting and escaping + in Query streams and template queries is + never implicit.By contrast, the + Query methods that take do add quotes and escape + strings implicitly. It can do this because SSQLS knows all the SQL + code and data types, so it never has to guess whether quoting or + escaping is appropriate. You must use manipulators + and template query flags as necessary to tell MySQL++ where quoting + and escaping is necessary. It would be nice if MySQL++ could do + quoting and escaping implicitly based on data type, but this + isn’t possible in all cases.Unless you’re smarter than I am, you + don’t immediately see why explicit manipulators are necessary. + We can tell when quoting and escaping is not + appropriate based on type, so doesn’t that mean we know when + it is appropriate? Alas, no. For most data + types, it is possible to know, or at least make an awfully good + guess, but it’s a complete toss-up for C strings, const + char*. A C string could be either a literal string of SQL + code, or it can be a value used in a query. Since there’s no + easy way to know and it would damage the library’s usability + to mandate that C strings only be used for one purpose or the other, + the library requires you to be explicit. Since + MySQL++ can’t reliably guess when quoting and escaping is + appropriate, and the programmer doesn’t need + toOne hopes the programmer + knows., MySQL++ makes you + tell it. + + + + + Specialized SQL Structures + + + Retrieving data + + The next example introduces one of the most powerful + features of MySQL++: Specialized SQL Structures (SSQLS). This is + examples/ssqls1.cpp: + + + + Here is the stock.h header used by that example, and + many others: + + + + This example produces the same output as + simple1.cpp (see ), + but it uses higher-level data structures paralleling the + database schema instead of MySQL++’s lower-level + generic data structures. It also uses MySQL++’s for error handling instead of doing + everything inline. For small example programs like these, the + overhead of SSQLS and exceptions doesn’t pay off very + well, but in a real program, they end up working much better + than hand-rolled code. + + Notice that we are only pulling a single column from the + stock table, but we are storing the rows in a + std::vector<stock>. It may strike you as + inefficient to have five unused fields per record. It’s + easily remedied by defining a subset SSQLS: + + +sql_create_1(stock_subset, + 1, 0, + string, item) + +vector<stock_subset> res; +query.storein(res); +// ...etc... + + MySQL++ is flexible about populating + SSQLSes.This is a new development in MySQL++ + v3.0. Programs built against older versions of MySQL++ would + crash at almost any mismatch between the database schema and + the SSQLS definition. This is a serious problem when the design + of the client programs and the database can’t be kept + in lock-step. It works much like the Web, + a design that’s enabled the development of the largest + distributed system in the world. Just as a browser ignores + tags and attributes it doesn’t understand, you can + populate an SSQLS from a query result set containing columns + that don’t exist in the SSQLS. And as a browser uses + sensible defaults when the page doesn’t give explicit + values, you can have an SSQLS with more fields defined than + are in the query result set, and these SSQLS fields will get + default values. (Zero for numeric types, false + for bool, and a type-specific default for anything + more complex, like mysqlpp::DateTime.) + + In more concrete terms, the example above is able to + populate the stock objects using as + much information as it has, and leave the remaining fields at + their defaults. Conversely, you could also stuff the results + of SELECT * FROM stock into + the stock_subset SSQLS declared above; + the extra fields would just be ignored. + + We're trading run-time efficiency for flexibility here, + usually the right thing in a distributed system. Since MySQL is + a networked database server, many uses of it will qualify as + distributed systems. You can't count on being able to update + both the server(s) and all the clients at the same time, so + you have to make them flexible enough to cope with differences + while the changes propagate. As long as the new database schema + isn’t too grossly different from the old, your programs + should continue to run until you get around to updating them + to use the new schema. + + There’s a danger that this quiet coping behavior + may mask problems, but considering that the previous behavior + was for the program to crash when the database schema got out + of synch with the SSQLS definition, it’s likely to be + taken as an improvement. + + + + + Adding data + + SSQLS can also be used to add data to a table. This is + examples/ssqls2.cpp: + + + + That’s all there is to it! + + There is one subtlety: MySQL++ automatically quotes and + escapes the data when building SQL queries using SSQLS structures. + It’s efficient, too: MySQL++ is smart enough to apply + quoting and escaping only for those data types that actually + require it. + + Because this example modifies the sample database, you + may want to run resetdb after running this program. + + + + + Modifying data + + It almost as easy to modify data with SSQLS. This is + examples/ssqls3.cpp: + + + + Don’t forget to run resetdb after running the + example. + + + + + Less-than-comparable + + SSQLS structures can be sorted and stored in STL associative + containers as demonstrated in the next example. This is + examples/ssqls4.cpp: + + + + The find() call works because + of the way the SSQLS was declared. It’s properly covered + elsewhere, but suffice it to say, the "1" in the declaration + of stock above tells it that only the + first field needs to be checked in comparing two SSQLSes. In + database terms, this makes it the primary key. Therefore, when + searching for a match, our exemplar only had to have its first + field populated. + + For more details on the SSQLS feature, see . + + + + + + C++ Equivalents of SQL Column Types + + The sql_types.h header declares typedefs + for all MySQL column types. These typedefs all begin with + sql_ and end with a lowercase version of the standard + SQL type name. For instance, the MySQL++ typedef corresponding to + TINYINT UNSIGNED is + mysqlpp::sql_tinyint_unsigned. You do not + have to use these typedefs; in this particular case, you might get + away with using something as loose as int. + + The most obivious reason to use these typedefs is clarity. + Someone reading code that uses these typedefs can’t be + confused about what the corresponding SQL type is. + + There’s also a correctness aspect to using these + typedefs. The definitions of these types have changed over time as + new, improved types have become available in MySQL++. For a past + example, sql_tinyint used to just be an alias for + signed char, but when MySQL++ began treating + char as a single-character string instead of an + integer, we changed the sql_tinyint typedef to be an + alias for mysqlpp::tiny_int<signed char>. Code + using the type aliases changed over transparently, while code using + what used to be the correct corresponding C++ type usually broke. + This is likely to happen again in the future, too. One example that + comes to mind is that sql_decimal is currently an alias + for double, but SQL’s DECIMAL type + is a fixed-point data type, while double is + floating-point. Thus, you lose accuracy when converting + DECIMAL column data to sql_decimal right + now. In the future, we may add a fixed-point data type to MySQL++; + if we do, we’ll certainly change the tyepdef alias to use it + instead of double. + + Most of these typedefs use standard C++ data types, but a few + are aliases for a MySQL++ specific type. For instance, the SQL type + DATETIME is mirrored in MySQL++ by + mysqlpp::DateTime. For consistency, + sql_types.h includes a typedef alias for + DateTime called + mysqlpp::sql_datetime. + + + + + Handling SQL Nulls + + There is no equivalent of SQL’s null in the standard C++ + type system. + + The primary distinction is one of type: in SQL, null is a + column attribute, which affects whether that column can hold a SQL + null. Just like the const keyword in the C++ type + system, this effectively doubles the number of SQL data types. To + emulate this, MySQL++ provides the Null template to allow the creation of distinct + “nullable” versions of existing C++ types. So for + example, if you have a TINYINT UNSIGNED column that can + have nulls, the proper declaration for MySQL++ would be: + + +mysqlpp::Null<mysqlpp::sql_tinyint_unsigned> myfield; + + Template instantiations are first-class types in the C++ + language, on par with any other type. You can use + Null template instantiations anywhere + you’d use the plain version of that type. (You can see a + complete list of Null template instantiations + for all column types that MySQL understands at the top of + lib/type_info.cpp.) + + There’s a secondary distinction between SQL null and + anything available in the standard C++ type system: SQL null is a + distinct value, equal to nothing else. We can’t use + C++’s NULL for this because it is ambiguous, + being equal to 0 in integer context. MySQL++ provides the global + null object, which you can assign to a + Null template instance to make it equal to + SQL null: + + +myfield = mysqlpp::null; + + By default, MySQL++ enforces the uniqueness of SQL null at + compile time. If you try to convert a SQL null to any other data + type, the compiler will emit an error message saying something + about CannotConvertNullToAnyOtherDataType. It’s + safe to insert a SQL null into a C++ stream, though: you get + “(NULL)”. + + If you don’t like this behavior, you can change it + by passing a different value for the second parameter to template + Null. By default, this parameter is , meaning that we should + enforce the uniqueness of SQL null. To relax this distinction, + you can instantiate the Null template with a + different behavior type: + or . Consider this + code: + + +mysqlpp::Null<unsigned char, mysqlpp::NullIsZero> myfield(mysqlpp::null); +cout << myfield << endl; +cout << int(myfield) << endl; + + This will print “0” twice. If you had used the + default for the second Null template + parameter, the first output statement would have printed + “(NULL)”, and the second wouldn’t even + compile. + + + + + Using Transactions + + The class makes it + easier to use SQL transactions in an exception-safe manner. Normally + you create the Transaction object on the + stack before you issue the queries in your transaction set. Then, + when all the queries in the transaction set have been issued, you + call Transaction::commit(), which commits the + transaction set. If the Transaction object + goes out of scope before you call commit(), the + transaction set is rolled back. This ensures that if some code + throws an exception after the transaction is started but before it + is committed, the transaction isn’t left unresolved. + + examples/transaction.cpp illustrates + this: + + + + One of the downsides of transactions is that the locking it + requires in the database server is prone to deadlocks. The classic + case where this happens is when two programs both want access to the + same two rows within a single transaction each, but they modify them + in opposite orders. If the timing is such that the programs + interleave their lock acquisitions, the two come to an impasse: + neither can get access to the other row they want to modify until + the other program commits its transaction and thus release the row + locks, but neither can finish the transaction because they’re + waiting on row locks the database server is holding on behalf of the + other program. + + The MySQL server is smart enough to detect this condition, but + the best it can do is abort the second transaction. This breaks the + impasse, allowing the first program to complete its + transaction. + + The second program now has to deal with the fact that its + transaction just got aborted. There’s a subtlety in detecting + this situation when using MySQL++. By default, MySQL++ signals + errors like these with exceptions. In the exception handler, you + might expect to get ER_LOCK_DEADLOCK from + Query::errnum() (or + Connection::errnum(), same thing), but what + you’ll almost certainly get instead is 0, meaning “no + error.” Why? It’s because you’re probably using a + Transaction object to get automatic + roll-backs in the face of exceptions. In this case, the roll-back + happens before your exception handler is called by issuing a + ROLLBACK query to the database server. Thus, + Query::errnum() returns the error code + associated with this roll-back query, not the deadlocked transaction + that caused the exception. + + To avoid this problem, a few of the exception objects as of + MySQL++ v3.0 include this last error number in the exception object + itself. It’s populated at the point of the exception, so it + can differ from the value you would get from + Query::errnum() later on when the exception + handler runs. + + The example examples/deadlock.cpp + demonstrates the problem: + + + + This example works a little differently than the others. You + run one copy of the example, then when it pauses waiting for you to + press Enter, you run another copy. Then, depending + on which one you press Enter in, one of the two + will abort with the deadlock exception. You can see from the error + message you get that it matters which method you call to get the + error number. What you do about it is up to you as it depends on + your program’s design and system architecture. + + + + + Which Query Type to Use? + + There are three major ways to execute a query in MySQL++: + Query::execute(), + Query::store(), and + Query::use(). Which should you use, and + why? + + execute() is for queries that do not + return data per se. For instance, + CREATE INDEX. You do get back some information + from the MySQL server, which execute() + returns to its caller in a object. In addition to the obvious — a + flag stating whether the query succeeded or not — this object + also contains things like the number of rows that the query + affected. If you only need the success status, it’s a little + more efficient to call Query::exec() + instead, as it simply returns bool. + + If your query does pull data from the database, the simplest + option is store(). (All of the examples up + to this point have used this method.) This returns a object, which contains the + entire result set. It’s especially convenient because + StoreQueryResult derives from + std::vector<mysqlpp::Row>, so it opens + the whole panoply of STL operations for accessing the rows in the + result set. Access rows randomly with subscript notation, iterate + forwards and backwards over the result set, run STL algorithms on + the set...it all works naturally. + + If you like the idea of storing your results in an STL + container but don’t want to use + std::vector, you can call + Query::storein() instead. It lets you store + the results in any standard STL container (yes, both sequential and + set-associative types) instead of using + StoreQueryResult. You do miss out on some of + the additional database information held by + StoreQueryResult’s other base class, + , however. + + store*() queries are convenient, but + the cost of keeping the entire result set in main memory can + sometimes be too high. It can be surprisingly costly, in fact. A + MySQL database server stores data compactly on disk, but it returns + query data to the client in a textual form. This results in a kind + of data bloat that affects numeric and BLOB types the most. MySQL++ + and the underlying C API library also have their own memory + overheads in addition to this. So, if you happen to know that the + database server stores every record of a particular table in 1 KB, + pulling a million records from that table could easily take several + GB of memory with a store() query, + depending on what’s actually stored in that table. + + For these large result sets, the superior option is a + use() query. This returns a object, which is similar to + StoreQueryResult, but without all of the + random-access features. This is because a “use” query + tells the database server to send the results back one row at a + time, to be processed linearly. It’s analogous to a C++ + stream’s input iterator, as opposed to a random-access + iterator that a container like vector offers. By accepting this + limitation, you can process arbitrarily large result sets. This + technique is demonstrated in + examples/simple3.cpp: + + + + This example does the same thing as + simple2, only with a “use” query + instead of a “store” query. + + Valuable as use() queries are, they + should not be the first resort in solving problems of excessive + memory use. It’s better if you can find a way to simply not + pull as much data from the database in the first place. Maybe + you’re saying SELECT * even though you + don’t immedidately need all the columns from the table. Or, + maybe you’re filtering the result set with C++ code after you + get it from the database server. If you can do that filtering with a + more restrictive WHERE clause on the + SELECT, it’ll not only save memory, + it’ll save bandwidth between the database server and client, + and can even save CPU time. If the filtering criteria can’t be + expressed in a WHERE clause, however, read on to + the next section. + + + + + Conditional Result Row Handling + + Sometimes you must pull more data from the database server + than you actually need and filter it in memory. SQL’s + WHERE clause is powerful, but not as powerful as + C++. Instead of storing the full result set and then picking over it + to find the rows you want to keep, use + Query::store_if(). This is + examples/store_if.cpp: + + + + I doubt anyone really needs to select rows from a table that + have a prime number in a given field. This example is meant to be + just barely more complex than SQL can manage, to avoid obscuring the + point. That point being, the + Query::store_if() call here gives you a + container full of results meeting a criterion that you probably + can’t express in SQL. You will no doubt have much more useful + criteria in your own programs. + + If you need a more complex query than the one + store_if() knows how to build when given an + SSQLS examplar, there are two overloads that let you use your own + query string. One overload takes the query string directly, and the + other uses the query string built with + Query’s stream interface. + + + + + Executing Code for Each Row In a Result Set + + SQL is more than just a database query language. Modern + database engines can actually do some calculations on the data on + the server side. But, this isn’t always the best way to get + something done. When you need to mix code and a query, + MySQL++’s Query::for_each() facility + might be just what you need. This is + examples/for_each.cpp: + + + + You only need to read the main() function + to get a good idea of what the program does. The key line of code + passes an SSQLS examplar and a functor to + Query::for_each(). + for_each() uses the SSQLS instance to build + a select * from TABLE query, + stock in this case. It runs that + query internally, calling gather_stock_stats + on each row. This is a pretty contrived example; you could actually + do this in SQL, but we’re trying to prevent the complexity of + the code from getting in the way of the demonstration here. + + Just as with store_if(), described + above, there are two other overloads for + for_each() that let you use your own query + string. + + + + + Connection Options + + MySQL has a large number of options that control how it makes + the connection to the database server, and how that connection + behaves. The defaults are sufficient for most programs, so only one + of the MySQL++ example programs make any connection option changes. + Here is examples/multiquery.cpp: + + + + This is a fairly complex example demonstrating the multi-query + and stored procedure features in newer versions of MySQL. Because + these are new features, and they change the communication between + the client and server, you have to enable these features in a + connection option. The key line is right up at the top of + main(), where it creates a object and passes it + to Connection::set_option(). That method + will take a pointer to any derivative of : you just create such an object on the heap and pass + it in, which gives Connection the data values + it needs to set the option. You don’t need to worry about + releasing the memory used by the Option + objects; it’s done automatically. + + The only tricky thing about setting options is that only a few + of them can be set after the connection is up. Most need to be set + just as shown in the example above: create an unconnected + Connection object, set your connection + options, and only then establish the connection. The option setting + mechanism takes care of applying the options at the correct time in + the connection establishment sequence. + + If you’re familiar with setting connection options in + the MySQL C API, you’ll have to get your head around the fact + that MySQL++’s connection option mechanism is a much simpler, + higher-level design that doesn’t resemble the C API in any + way. The C API has something like half a dozen different mechanisms + for setting options that control the connection. The flexibility of + the C++ type system allows us to wrap all of these up into a single + high-level mechanism while actually getting greater type safety than + the C API allows. + + + + + Getting Field Meta-Information + + The following example demonstrates how to get information + about the fields in a result set, such as the name of the field and + the SQL type. This is + examples/fieldinf.cpp: + + + + + + + MySQL++’s Special String Types + + MySQL++ has two classes that work like + std::string to some degree: and . These classes exist to provide functionality + that std::string doesn’t provide, but + they are neither derivatives of nor complete supersets of + std::string. As a result, end-user code + generally doesn’t deal with these classes directly, because + std::string is a better general-purpose + string type. In fact, MySQL++ itself uses + std::string most of the time, too. But, the + places these specialized stringish types do get used are so + important to the way MySQL++ works that it’s well worth taking + the time to understand them. + + + + SQLTypeAdapter + + The simpler of the two is + SQLTypeAdapter, or + STA for short.In version 2 + of MySQL++ and earlier, SQLTypeAdapter was + called SQLString, but it was confusing + because its name and the fact that it derived from + std::string suggested that it was a + general-purpose string type. MySQL++ even used it this way in a + few places internally. In v3, we made it a simple base class and + renamed it to reflect its proper limited + function. + + As its name suggests, its only purpose is to adapt other + data types to be used with SQL. It has a whole bunch of conversion + constructors, one for all data types we expect to be used with + MySQL++ for values in queries. SQL queries are strings, so + constructors that take stringish types just make a copy of that + string, and all the others “stringize” the value in + the format needed by + SQL.SQLTypeAdapter + doesn’t do itself. That happens + elsewhere, right at the point that the STA + gets used to build a query. The conversion + constructors preserve type information, so this stringization + process doesn’t throw away any essential information. + + STA is used anywhere MySQL++ needs to + be able to accept any of several data types for use in a SQL + query. Major users are Query’s + template query mechanism and the Query + stream quoting and escaping mechanism. You care about + STA because any time you pass a data value + to MySQL++ to be used in building a SQL query, it goes through + STA. STA is one of + the key pieces in MySQL++ that makes it easy to generate + syntactically-correct SQL queries. + + + + + String + + If MySQL++ can be said to have its own generic string type, + it’s String, but it’s not + really functional enough for general use. It’s possible that + in future versions of MySQL++ we’ll expand its interface to + include everything std::string does, so + that’s why it’s called that.If you + used MySQL++ before v3, String used to be + called ColData. It was renamed because + starting in v2.3, we began using it for holding more than just + column data. I considered renaming it + SQLString instead, but that would have + confused old MySQL++ users to no end. Instead, I followed the + example of Set, MySQL++’s specialized + std::set variant. + + The key thing String provides over + std::string is conversion of strings in SQL + value formats to their native C++ data types. For example, if you + initialize it with the string “2007-11-19”, you can + assign the String to a Date, not because + Date knows how to initialize itself from + String, but the reverse: + String has a bunch of implicit conversion + operators defined for it, so you can use it in any type context + that makes sense in your application. + + Because Row::operator[] returns + String, you can say things like + this: + + int x = row["x"]; + + In a very real sense, String is the + inverse of STA: + String converts SQL value strings to C++ + data types, and STA converts C++ data types + to SQL value strings.During the development of + MySQL++ v3.0, I tried merging + SQLTypeAdapter and + String into a single class to take + advantage of this. The resulting class gave the C++ compiler the + freedom to tie itself up in knots, because it was then allowed to + convert almost any data type to almost any other. You’d get + a tangle of ambiguous data type conversion errors from the most + innocent code. + + String has two main uses. + + By far the most common use is as the field value type of + Row, as exemplified above. It’s not + just the return type of Row::operator[], + though: it’s actually the value type used within + Row’s internal array. As a result, + any time MySQL++ pulls data from the database, it goes through + String when converting it from the string + form used in SQL result sets to the C++ data type you actually + want the data in. It’s the core of the structure population + mechanism in , for example. + + Because String is the last pristine + form of data in a result set before it gets out of MySQL++’s + internals where end-user code can see it, MySQL++’s + sql_blob and related typedefs are + aliases for String. Using anything else + would require copies; while the whole “networked database + server” thing means most of MySQL++ can be quite inefficient + and still not affect benchmark results meaningfully, BLOBs tend to + be big, so making unnecessary copies can really make a difference. + Which brings us to... + + + + + Reference Counting + + To avoid unnecessary buffer copies, both + STA and String are + implemented in terms of a reference-counted copy-on-write buffer + scheme. Both classes share the same underlying mechanism, and so + are interoperable. This means that if you construct one of these + objects from another, it doesn’t actually copy the string + data, it only copies a pointer to the data buffer, and increments + its reference count. If the object has new data assigned to it or + it’s otherwise modified, it decrements its reference count + and creates its own copy of the buffer. This has a lot of + practical import, such as the fact that + Row::operator[] can return + String by value, and it’s still + efficient. + + + + + + Dealing with Binary Data + + The tricky part about dealing with binary data in MySQL++ is + to ensure that you don’t ever treat the data as a C string, + which is really easy to do accidentally. C strings treat zero bytes + as special end-of-string characters, but they’re not special + at all in binary data. Recent releases of MySQL++ do a better job of + letting you keep data in forms that don’t have this problem, + but it’s still possible to do it incorrectly. These examples + demonstrate correct techniques. + + + + Loading a binary file into a BLOB column + + This example shows how to insert binary data into a MySQL + table’s BLOB column with MySQL++, and also how to get the + value of the auto-increment column from the previous insert. (This + MySQL feature is usually used to create unique IDs for rows as + they’re inserted.) The program requires one command line + parameter over that required by the other examples you’ve + seen so far, the path to a JPEG file. This is + examples/load_jpeg.cpp: + + + + Notice that we used the escape manipulator when + building the INSERT query above. This is because we’re not + using one of the MySQL++ types that does automatic escaping and + quoting. + + + + + Serving images from BLOB column via CGI + + This example is also a very short one, considering the + function that it performs. It retreives data loaded by + load_jpeg and prints it out in the form a web + server can accept for a CGI call. This is + examples/cgi_jpeg.cpp: + + + + You install this in a web server’s CGI program + directory, then call it with a URL like + http://my.server.com/cgi-bin/cgi_jpeg?id=1. That + retrieves the JPEG with ID 1 from the table and returns it to the + web server, which will send it on to the browser. + + + + + + Concurrent Queries on a Connection + + An important limitation of the MySQL C API library — + which MySQL++ is built atop, so it shares this limitation — is + that you can’t have two concurrent queries running on a single + connection. If you try, you get an obscure error message about + “Commands out of sync” from the underlying C API + library. (You get it in a MySQL++ exception unless you have + exceptions disabled, in which case you get a failure code and + Connection::error() returns this + message.) + + The easiest way to cause this error is in a multithreaded + program where you have a single object, but allow multiple threads to issue + queries on it. Unless you put in a lot of work to synchronize + access, this is almost guaranteed to fail. + + If you give each thread that issues queries has its own + Connection object, you can still run into + trouble if you pass the data you get from queries around to other + threads. What can happen is that one of these child objects + indirectly calls back to the Connection at a + time where it’s involved with another query. (There are other + ways to run into trouble when sharing MySQL++ data structures among + threads, but the whole topic is complex enough to deserve its own + chapter, .) + + It’s possible to run into this problem in a + single-threaded program as well. As discussed above (), one of the options MySQL offers for + executing a query lets you issue the query, then consume the rows + one at a time, on demand: it’s the “use” query. If + you don’t consume all rows from a query before you issue + another on that connection, you are effectively trying to have + multiple concurrent queries on a single connection, and you end up + with the same problem. The simplest recipie for disaster is: + + +UseQueryResult r1 = query.use("select garbage from plink where foobie='tamagotchi'"); +UseQueryResult r2 = query.use("select blah from bonk where bletch='smurf'"); + + The second use() call fails because + the first result set hasn’t been consumed yet. + + ADDED doc/userman/unicode.dbx Index: doc/userman/unicode.dbx ================================================================== --- /dev/null +++ doc/userman/unicode.dbx @@ -0,0 +1,189 @@ + + + + + Using Unicode with MySQL++ + + + A Short History of Unicode + ...with a focus on relevance to MySQL++ + + In the old days, computer operating systems only dealt with + 8-bit character sets. That only allows for 256 possible characters, + but the modern Western languages have more characters combined than + that alone. Add in all the other languages of the world plus the + various symbols people use in writing, and you have a real + mess! + + Since no standards body held sway over things like + international character encoding in the early days of computing, + many different character sets were invented. These character sets + weren’t even standardized between operating systems, so heaven + help you if you needed to move localized Greek text on a DOS box to + a Russian Macintosh! The only way we got any international + communication done at all was to build standards on top of the + common 7-bit ASCII subset. Either people used approximations like a + plain “c” instead of the French “ç”, + or they invented things like HTML entities + (“&ccedil;” in this case) to encode these additional + characters using only 7-bit ASCII. + + Unicode solves this problem. It encodes every character used + for writing in the world, using up to 4 bytes per character. The + subset covering the most economically valuable cases takes two bytes + per character, so most Unicode-aware programs deal in 2-byte + characters, for efficiency. + + Unfortunately, Unicode was invented about two decades too late + for Unix and C. Those decades of legacy created an immense inertia + preventing a widespread move away from 8-bit characters. MySQL and + C++ come out of these older traditions, and so they share the same + practical limitations. MySQL++ doesn’t have a reason to do + anything more than just pass data along unchanged, so you still need + to be aware of these underlying issues. + + During the development of the Plan + 9 operating system (a kind of successor to Unix) Ken + Thompson invented + the UTF-8 + encoding. UTF-8 is a superset of 7-bit ASCII and is + compatible with C strings, since it doesn’t use 0 bytes + anywhere as multi-byte Unicode encodings do. As a result, many + programs that deal in text will cope with UTF-8 data even though + they have no explicit support for UTF-8. (Follow the last link above + to see how the design of UTF-8 allows this.) Thus, when explicit + support for Unicode was added in MySQL v4.1, they chose to make + UTF-8 the native encoding, to preserve backward compatibility with + programs that had no Unicode support. + + + + + Unicode on Unixy Systems + + Linux and Unix have system-wide UTF-8 support these days. If + your operating system is of 2001 or newer vintage, it probably has + such support. + + On such a system, the terminal I/O code understands UTF-8 + encoded data, so your program doesn’t require any special code + to correctly display a UTF-8 string. If you aren’t sure + whether your system supports UTF-8 natively, just run the + simple1 example: if the first item has two + high-ASCII characters in place of the “ü” in + “Nürnberger Brats”, you know it’s not + handling UTF-8. + + If your Unix doesn’t support UTF-8 natively, it likely + doesn’t support any form of Unicode at all, for the historical + reasons I gave above. Therefore, you will have to convert the UTF-8 + data to the local 8-bit character set. The standard Unix function + iconv() can help here. If your system + doesn’t have the iconv() facility, there + is a free + implementation available from the GNU Project. Another + library you might check out is IBM’s ICU. This is rather + heavy-weight, so if you just need basic conversions, + iconv() should suffice. + + + + + Unicode on Windows + + Each Windows API function that takes a string actually comes + in two versions. One version supports only 1-byte “ANSI” + characters (a superset of ASCII), so they end in 'A'. Windows also + supports the 2-byte subset of Unicode called UCS-2. Some call + these “wide” characters, so the other set of functions + end in 'W'. The MessageBox() + API, for instance, is actually a macro, not a real function. If you + define the UNICODE macro when building your + program, the MessageBox() macro evaluates to + MessageBoxW(); otherwise, to + MessageBoxA(). + + Since MySQL uses the UTF-8 Unicode encoding and Windows uses + UCS-2, you must convert data when passing text between MySQL++ and + the Windows API. Since there’s no point in trying for + portability — no other OS I’m aware of uses UCS-2 + — you might as well use platform-specific functions to do this + translation. Since version 2.2.2, MySQL++ ships with two Visual C++ + specific examples showing how to do this in a GUI program. (In + earlier versions of MySQL++, we did Unicode conversion in the + console mode programs, but this was unrealistic.) + + How you handle Unicode data depends on whether you’re + using the native Windows API, or the newer .NET API. First, the + native case: + + +// Convert a C string in UTF-8 format to UCS-2 format. +void ToUCS2(LPTSTR pcOut, int nOutLen, const char* kpcIn) +{ + MultiByteToWideChar(CP_UTF8, 0, kpcIn, -1, pcOut, nOutLen); +} + +// Convert a UCS-2 string to C string in UTF-8 format. +void ToUTF8(char* pcOut, int nOutLen, LPCWSTR kpcIn) +{ + WideCharToMultiByte(CP_UTF8, 0, kpcIn, -1, pcOut, nOutLen, 0, 0); +} + + These functions leave out some important error checking, so + see examples/vstudio/mfc/mfc_dlg.cpp for the + complete version. + + If you’re building a .NET application (such as, perhaps, + because you’re using Windows Forms), it’s better to use + the .NET libraries for this: + + +// Convert a C string in UTF-8 format to a .NET String in UCS-2 format. +String^ ToUCS2(const char* utf8) +{ + return gcnew String(utf8, 0, strlen(utf8), System::Text::Encoding::UTF8); +} + +// Convert a .NET String in UCS-2 format to a C string in UTF-8 format. +System::Void ToUTF8(char* pcOut, int nOutLen, String^ sIn) +{ + array<Byte>^ bytes = System::Text::Encoding::UTF8->GetBytes(sIn); + nOutLen = Math::Min(nOutLen - 1, bytes->Length); + System::Runtime::InteropServices::Marshal::Copy(bytes, 0, + IntPtr(pcOut), nOutLen); + pcOut[nOutLen] = '\0'; +} + + Unlike the native API versions, these examples are complete, + since the .NET platform handles a lot of things behind the scenes + for us. We don’t need any error-checking code for such simple + routines. + + All of this assumes you’re using Windows NT or one of + its direct descendants: Windows 2000, Windows XP, Windows Vista, or + any “Server” variant of Windows. Windows 95 and its + descendants (98, ME, and CE) do not support UCS-2. They still have + the 'W' APIs for compatibility, but they just smash the data down to + 8-bit and call the 'A' version for you. + + + + + For More Information + The Unicode + FAQs page has copious information on this complex + topic. + + When it comes to Unix and UTF-8 specific items, the UTF-8 and + Unicode FAQ for Unix/Linux is a quicker way to find basic + information. + + ADDED doc/userman/userman.dbx Index: doc/userman/userman.dbx ================================================================== --- /dev/null +++ doc/userman/userman.dbx @@ -0,0 +1,52 @@ + + + +
+ + MySQL++ v3.0.3 User Manual + + + + Kevin + Atkinson + + + + Sinisa + Milivojevic + + + + Monty + Widenius + + + + Warren + Young + + + + + 1998-2001, 2005-2008 + Kevin Atkinson (original author) + MySQL AB + Educational Technology Resources + + + + + + + + + + + + + + + + +
ADDED doc/userman/userman.dbx.in Index: doc/userman/userman.dbx.in ================================================================== --- /dev/null +++ doc/userman/userman.dbx.in @@ -0,0 +1,52 @@ + + + +
+ + MySQL++ v@MYSQLPP_VERSION_MAJOR@.@MYSQLPP_VERSION_MINOR@.@MYSQLPP_VERSION_BUGFIX@ User Manual + + + + Kevin + Atkinson + + + + Sinisa + Milivojevic + + + + Monty + Widenius + + + + Warren + Young + + + + + 1998-2001, 2005-2008 + Kevin Atkinson (original author) + MySQL AB + Educational Technology Resources + + + + + + + + + + + + + + + + +
ADDED dtest Index: dtest ================================================================== --- /dev/null +++ dtest @@ -0,0 +1,80 @@ +#!/bin/bash + +TMP=`mktemp bmXXXXXX` + +# Run simple unit tests first. +typeset -i count=0 +echo -n 'Running unit tests:' +for t in test_* +do + if [ -x "$t" ] + then + errmsg=`./exrun "$t" 2>&1` + errno=$? + if [ "$errno" = 0 ] + then + count=count+1 + else + rm -f $TMP + echo " $t FAILED ($errno)" + echo + echo "$errmsg" + exit $? + fi + fi +done +echo " $count tests succeeded" +echo 'All unit tests passed' >> $TMP + + +# Now run examples to test high-level behavior. The repeated use of +# resetdb is intentional! It's run after each example that changes +# the database in a way that will cause a subsequent example to fail +# because data it expects isn't present. +echo -n 'Running examples:' +for t in \ + resetdb simple[0-9] store_if for_each multiquery tquery1 \ + resetdb tquery[2-9] \ + resetdb ssqls[0-9] +do + if [ -x $t ] + then + if [ "$t" = "resetdb" ] + then + echo + echo -n " " + fi + + echo -n "$t " + echo "---------------- BEGIN $t OUTPUT ----------------" >> $TMP + if ! ./exrun $t -D $* >> $TMP + then + echo + echo 'TESTING ABORTED.' + rm -f $TMP + exit $? + fi + echo "================ END $t OUTPUT ================" >> $TMP + echo >> $TMP + fi +done +echo + + +# Check for any changes +BFILE=bmark.txt +if [ -f $BFILE ] +then + if diff -u -w $BFILE $TMP + then + echo + echo 'All tests passed.' + fi + rm -f $TMP +else + mv $TMP $BFILE + chmod -w $BFILE + echo + echo 'BENCHMARK FILE REGENERATED.' + echo +fi DELETED examples/Makefile.am Index: examples/Makefile.am ================================================================== --- examples/Makefile.am +++ /dev/null @@ -1,51 +0,0 @@ - -include ../Configure - -noinst_PROGRAMS = resetdb simple1 custom1 custom2 custom3 custom4 complic1 fieldinf1 - -noinst_HEADERS = util.hh - -simple1_SOURCES = simple1.cc -simple1_LDFLAGS = -simple1_LDADD = $(SQLPLUSLIBS) -simple1_DEPENDENCIES = $(SQLPLUSLIBS) - -sinisa_ex_SOURCES = sinisa_ex.cc -sinisa_ex_LDFLAGS = -sinisa_ex_LDADD = $(SQLPLUSLIBS) -sinisa_ex_DEPENDENCIES = $(SQLPLUSLIBS) - -resetdb_SOURCES = resetdb.cc util.cc -resetdb_LDFLAGS = -resetdb_LDADD = $(SQLPLUSLIBS) -resetdb_DEPENDENCIES = $(SQLPLUSLIBS) - -custom1_SOURCES = custom1.cc -custom1_LDFLAGS = -custom1_LDADD = $(SQLPLUSLIBS) -custom1_DEPENDENCIES = $(SQLPLUSLIBS) - -custom2_SOURCES = custom2.cc util.cc -custom2_LDFLAGS = -custom2_LDADD = $(SQLPLUSLIBS) -custom2_DEPENDENCIES = $(SQLPLUSLIBS) - -custom3_SOURCES = custom3.cc util.cc -custom3_LDFLAGS = -custom3_LDADD = $(SQLPLUSLIBS) -custom3_DEPENDENCIES = $(SQLPLUSLIBS) - -custom4_SOURCES = custom4.cc -custom4_LDFLAGS = -custom4_LDADD = $(SQLPLUSLIBS) -custom4_DEPENDENCIES = $(SQLPLUSLIBS) - -complic1_SOURCES = complic1.cc -complic1_LDFLAGS = -complic1_LDADD = $(SQLPLUSLIBS) -complic1_DEPENDENCIES = $(SQLPLUSLIBS) - -fieldinf1_SOURCES = fieldinf1.cc -fieldinf1_LDFLAGS = -fieldinf1_LDADD = $(SQLPLUSLIBS) -fieldinf1_DEPENDENCIES = $(SQLPLUSLIBS) ADDED examples/cgi_jpeg.cpp Index: examples/cgi_jpeg.cpp ================================================================== --- /dev/null +++ examples/cgi_jpeg.cpp @@ -0,0 +1,105 @@ +/*********************************************************************** + cgi_jpeg.cpp - Example code showing how to fetch JPEG data from a BLOB + column and send it back to a browser that requested it by ID. + + Use load_jpeg.cpp to load JPEG files into the database we query. + + Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and + (c) 2004-2008 by Educational Technology Resources, Inc. Others may + also hold copyrights on code in this file. See the CREDITS file in + the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#include +#include + +#define IMG_DATABASE "mysql_cpp_data" +#define IMG_HOST "localhost" +#define IMG_USER "root" +#define IMG_PASSWORD "nunyabinness" + +sql_create_2(images, + 1, 2, + mysqlpp::sql_int_unsigned, id, + mysqlpp::sql_blob, data) + +int main() +{ + unsigned int img_id = 0; + char* cgi_query = getenv("QUERY_STRING"); + if (cgi_query) { + if ((strlen(cgi_query) < 4) || memcmp(cgi_query, "id=", 3)) { + std::cout << "Content-type: text/plain" << std::endl << std::endl; + std::cout << "ERROR: Bad query string" << std::endl; + return 1; + } + else { + img_id = atoi(cgi_query + 3); + } + } + else { + std::cerr << "Put this program into a web server's cgi-bin " + "directory, then" << std::endl; + std::cerr << "invoke it with a URL like this:" << std::endl; + std::cerr << std::endl; + std::cerr << " http://server.name.com/cgi-bin/cgi_jpeg?id=2" << + std::endl; + std::cerr << std::endl; + std::cerr << "This will retrieve the image with ID 2." << std::endl; + std::cerr << std::endl; + std::cerr << "You will probably have to change some of the #defines " + "at the top of" << std::endl; + std::cerr << "examples/cgi_jpeg.cpp to allow the lookup to work." << + std::endl; + return 1; + } + + try { + mysqlpp::Connection con(IMG_DATABASE, IMG_HOST, IMG_USER, + IMG_PASSWORD); + mysqlpp::Query query = con.query(); + query << "SELECT * FROM images WHERE id = " << img_id; + mysqlpp::UseQueryResult res = query.use(); + if (res) { + images img = res.fetch_row(); + std::cout << "Content-type: image/jpeg" << std::endl; + std::cout << "Content-length: " << img.data.length() << "\n\n"; + std::cout << img.data; + } + else { + std::cout << "Content-type: text/plain" << std::endl << std::endl; + std::cout << "ERROR: No such image with ID " << img_id << std::endl; + } + } + catch (const mysqlpp::BadQuery& er) { + // Handle any query errors + std::cout << "Content-type: text/plain" << std::endl << std::endl; + std::cout << "QUERY ERROR: " << er.what() << std::endl; + return 1; + } + catch (const mysqlpp::Exception& er) { + // Catch-all for any other MySQL++ exceptions + std::cout << "Content-type: text/plain" << std::endl << std::endl; + std::cout << "GENERAL ERROR: " << er.what() << std::endl; + return 1; + } + + return 0; +} ADDED examples/cmdline.cpp Index: examples/cmdline.cpp ================================================================== --- /dev/null +++ examples/cmdline.cpp @@ -0,0 +1,174 @@ +/*********************************************************************** + cmdline.cpp - Utility functions for printing out data in common + formats, required by most of the example programs. + + Copyright (c) 2007-2008 by Educational Technology Resources, Inc. + Others may also hold copyrights on code in this file. See the + CREDITS file in the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#include "cmdline.h" + +#include + +#include +#include +#include + + +//// globals and constants ///////////////////////////////////////////// + +bool dtest_mode = false; // true when running under dtest +int run_mode = 0; // -m switch's value +const char* kpcSampleDatabase = "mysql_cpp_data"; + + +//// att_getopt //////////////////////////////////////////////////////// +// An implementation of getopt(), included here so we don't have to +// limit ourselves to platforms that provide this natively. It is +// adapted from the public domain getopt() implementation presented at +// the 1985 UNIFORUM conference in Dallas, Texas. It's been reformatted +// and reworked a bit to fit in with MySQL++. + +static const char* ag_optarg; +int ag_optind = 1; + +static int +att_getopt(int argc, char* const argv[], const char* ag_opts) +{ + static int optopt; + static int sp = 1; + register int c; + register const char *cp; + + if (sp == 1) { + /* If all args are processed, finish */ + if (ag_optind >= argc) { + return EOF; + } + if (argv[ag_optind][0] != '-' || argv[ag_optind][1] == '\0') { + return EOF; + } + } + else if (!strcmp(argv[ag_optind], "--")) { + /* No more ag_options to be processed after this one */ + ag_optind++; + return EOF; + } + + optopt = c = argv[ag_optind][sp]; + + /* Check for invalid ag_option */ + if (c == ':' || (cp = strchr(ag_opts, c)) == NULL) { + fprintf(stderr, "%s: illegal option -- %c\n", argv[0], c); + if (argv[ag_optind][++sp] == '\0') { + ag_optind++; + sp = 1; + } + + return '?'; + } + + /* Does this ag_option require an argument? */ + if (*++cp == ':') { + /* If so, get argument; if none provided output error */ + if (argv[ag_optind][sp + 1] != '\0') { + ag_optarg = &argv[ag_optind++][sp + 1]; + } + else if (++ag_optind >= argc) { + fprintf(stderr, + "%s: option requires an argument -- %c\n", argv[0], c); + sp = 1; + return '?'; + } + else { + ag_optarg = argv[ag_optind++]; + } + sp = 1; + } + else { + if (argv[ag_optind][++sp] == '\0') { + sp = 1; + ag_optind++; + } + ag_optarg = NULL; + } + + return c; +} + + +//// print_usage /////////////////////////////////////////////////////// +// Show the program's usage message + +void +print_usage(const char* program_name, const char* extra_parms) +{ + std::cout << "usage: " << program_name << + " [-s server_addr] [-u user] [-p password] " << + extra_parms << std::endl; + std::cout << std::endl; + std::cout << " If no options are given, connects to database " + "server on localhost" << std::endl; + std::cout << " using your user name and no password." << std::endl; + if (strlen(extra_parms) > 0) { + std::cout << std::endl; + std::cout << " The extra parameter " << extra_parms << + " is required, regardless of which" << std::endl; + std::cout << " other arguments you pass." << std::endl; + } + std::cout << std::endl; +} + + +//// parse_command_line //////////////////////////////////////////////// +// Wrapper around att_getopt() to return the parameters needed to +// connect to a database server and select the database itself. + +bool +parse_command_line(int argc, char *argv[], const char** ppdb, + const char** ppserver, const char** ppuser, const char** pppass, + const char* extra_parms) +{ + if (argc < 1) { + std::cerr << "Bad argument count: " << argc << '!' << std::endl; + return false; + } + + if (ppdb && !*ppdb) { + *ppdb = "mysql_cpp_data"; // use default DB + } + + int ch; + while ((ch = att_getopt(argc, argv, "m:p:s:u:D")) != EOF) { + switch (ch) { + case 'm': run_mode = atoi(ag_optarg); break; + case 'p': *pppass = ag_optarg; break; + case 's': *ppserver = ag_optarg; break; + case 'u': *ppuser = ag_optarg; break; + case 'D': dtest_mode = true; break; + default: + print_usage(argv[0], extra_parms); + return false; + } + } + + return true; +} ADDED examples/cmdline.h Index: examples/cmdline.h ================================================================== --- /dev/null +++ examples/cmdline.h @@ -0,0 +1,40 @@ +/*********************************************************************** + cmdline.h - Declares the interface to the command line parsing logic. + It is not important for a new MySQL++ user to understand any of what + goes on inside this module. The examples just pass in the command + line arguments and magically get out the proper database server + login parameters and the name of the database itself. + + Copyright (c) 2007 by Educational Technology Resources, Inc. + Others may also hold copyrights on code in this file. See the + CREDITS file in the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#if !defined(MYSQLPP_CMDLINE_H) +#define MYSQLPP_CMDLINE_H + +extern bool parse_command_line(int argc, char *argv[], + const char** ppdb, const char** ppserver, const char** ppuser, + const char** pppass, const char* extra_parms = ""); +extern void print_usage(const char* program_name, + const char* extra_parms = ""); + +#endif // !defined(MYSQLPP_CMDLINE_H) + DELETED examples/complic1.cc Index: examples/complic1.cc ================================================================== --- examples/complic1.cc +++ /dev/null @@ -1,68 +0,0 @@ - -#include -#include -#include - -int main() { - try { // its in one big try block - - Connection con(use_exceptions); - con.connect("mysql_cpp_data"); - // Here I broke making the connection into two calls. - // The first one creates the Connection object with the - // use exceptions option turned on and the second one - // makes the connection - - Query query = con.query(); - - query << "select * from stock"; - Result res = query.store(); - - cout << "Query: " << query.preview() << endl; - cout << "Records Found: " << res.size() << endl << endl; - - Row row; - cout.setf(ios::left); - cout << setw(17) << "Item" - << setw(4) << "Num" - << setw(7) << "Weight" - << setw(7) << "Price" - << "Date" << endl - << endl; - - Result::iterator i; - - cout.precision(3); - for (i = res.begin(); i != res.end(); i++) { - row = *i; - cout << setw(17) << row["item"] << setw(4) << row[1] - << setw(7) << (double)row[2] - // This is converting the row to a double so that we - // can set the precision of it. - // ColData has the nice feature that it will convert to - // any of the basic c++ types. if there is a problem - // in the conversion it will throw an exception (which I - // cache below). To test it try changing the 2 in row[2] - // to row[0] - << setw(7) << (double)row[3]; - Date date = row["sdate"]; - // The ColData is implicitly converted to a date here. - cout.setf(ios::right); - cout.fill('0'); - cout << setw(2) << date.month << "-" << setw(2) << date.day << endl; - cout.fill(' '); - cout.unsetf(ios::right); - } - return 0; - } catch (BadQuery er) { // handle any connection or - // query errors that may come up - cerr << "Error: " << er.error << endl; - return -1; - } catch (BadConversion er) { // handle bad conversions - cerr << "Error: Tried to convert \"" << er.data << "\" to a \"" - << er.type_name << "\"." << endl; - return -1; - } -} - - ADDED examples/cpool.cpp Index: examples/cpool.cpp ================================================================== --- /dev/null +++ examples/cpool.cpp @@ -0,0 +1,253 @@ +/*********************************************************************** + cpool.cpp - ConnectionPool example. Works with both Windows native + threads and POSIX threads. Shows how to create and use a concrete + ConnectionPool derivative. + + Copyright (c) 2008 by Educational Technology Resources, Inc. + Others may also hold copyrights on code in this file. See the + CREDITS file in the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#include "cmdline.h" +#include "threads.h" + +#include + +using namespace std; + + +#if defined(HAVE_THREADS) +// Define a concrete ConnectionPool derivative. Takes connection +// parameters as inputs to its ctor, which it uses to create the +// connections we're called upon to make. Note that we also declare +// a global pointer to an object of this type, which we create soon +// after startup; this should be a common usage pattern, as what use +// are multiple pools? +class SimpleConnectionPool : public mysqlpp::ConnectionPool +{ +public: + // The object's only constructor + SimpleConnectionPool(const char* db, const char* server, + const char* user, const char* password) : + conns_in_use_(0), + db_(db ? db : ""), + server_(server ? server : ""), + user_(user ? user : ""), + password_(password ? password : "") + { + } + + // The destructor. We _must_ call ConnectionPool::clear() here, + // because our superclass can't do it for us. + ~SimpleConnectionPool() + { + clear(); + } + + // Do a simple form of in-use connection limiting: wait to return + // a connection until there are a reasonably low number in use + // already. Can't do this in create() because we're interested in + // connections actually in use, not those created. Also note that + // we keep our own count; ConnectionPool::size() isn't the same! + mysqlpp::Connection* grab() + { + while (conns_in_use_ > 8) { + cout.put('R'); cout.flush(); // indicate waiting for release + sleep(1); + } + + ++conns_in_use_; + return mysqlpp::ConnectionPool::grab(); + } + + // Other half of in-use conn count limit + void release(const mysqlpp::Connection* pc) + { + mysqlpp::ConnectionPool::release(pc); + --conns_in_use_; + } + +protected: + // Superclass overrides + mysqlpp::Connection* create() + { + // Create connection using the parameters we were passed upon + // creation. This could be something much more complex, but for + // the purposes of the example, this suffices. + cout.put('C'); cout.flush(); // indicate connection creation + return new mysqlpp::Connection( + db_.empty() ? 0 : db_.c_str(), + server_.empty() ? 0 : server_.c_str(), + user_.empty() ? 0 : user_.c_str(), + password_.empty() ? "" : password_.c_str()); + } + + void destroy(mysqlpp::Connection* cp) + { + // Our superclass can't know how we created the Connection, so + // it delegates destruction to us, to be safe. + cout.put('D'); cout.flush(); // indicate connection destruction + delete cp; + } + + unsigned int max_idle_time() + { + // Set our idle time at an example-friendly 3 seconds. A real + // pool would return some fraction of the server's connection + // idle timeout instead. + return 3; + } + +private: + // Number of connections currently in use + unsigned int conns_in_use_; + + // Our connection parameters + std::string db_, server_, user_, password_; +}; +SimpleConnectionPool* poolptr = 0; + + +static thread_return_t CALLBACK_SPECIFIER +worker_thread(thread_arg_t running_flag) +{ + // Ask the underlying C API to allocate any per-thread resources it + // needs, in case it hasn't happened already. In this particular + // program, it's almost guaranteed that the grab() call below will + // create a new connection the first time through, and thus allocate + // these resources implicitly, but there's a nonzero chance that + // this won't happen. Anyway, this is an example program, meant to + // show good style, so we take the high road and ensure the + // resources are allocated before we do any queries. + mysqlpp::Connection::thread_start(); + cout.put('S'); cout.flush(); // indicate thread started + + // Pull data from the sample table a bunch of times, releasing the + // connection we use each time. + for (size_t i = 0; i < 6; ++i) { + // Go get a free connection from the pool, or create a new one + // if there are no free conns yet. + mysqlpp::Connection* cp = poolptr->grab(); + if (!cp) { + cerr << "Failed to get a connection from the pool!" << endl; + break; + } + + // Pull a copy of the sample stock table and print a dot for + // each row in the result set. + mysqlpp::Query query(cp->query("select * from stock")); + mysqlpp::StoreQueryResult res = query.store(); + for (size_t j = 0; j < res.num_rows(); ++j) { + cout.put('.'); + } + + // Immediately release the connection once we're done using it. + // If we don't, the pool can't detect idle connections reliably. + poolptr->release(cp); + + // Delay 1-4 seconds before doing it again. Because this can + // delay longer than the idle timeout, we'll occasionally force + // the creation of a new connection on the next loop. + sleep(rand() % 4 + 1); + } + + // Tell main() that this thread is no longer running + *reinterpret_cast(running_flag) = false; + cout.put('E'); cout.flush(); // indicate thread ended + + // Release the per-thread resources before we exit + mysqlpp::Connection::thread_end(); + + return 0; +} +#endif + + +int +main(int argc, char *argv[]) +{ +#if defined(HAVE_THREADS) + // Get database access parameters from command line + const char* db = 0, *server = 0, *user = 0, *pass = ""; + if (!parse_command_line(argc, argv, &db, &server, &user, &pass)) { + return 1; + } + + // Create the pool and grab a connection. We do it partly to test + // that the parameters are good before we start doing real work, and + // partly because we need a Connection object to call thread_aware() + // on to check that it's okay to start doing that real work. This + // latter check should never fail on Windows, but will fail on most + // other systems unless you take positive steps to build with thread + // awareness turned on. See README-*.txt for your platform. + poolptr = new SimpleConnectionPool(db, server, user, pass); + try { + mysqlpp::Connection* cp = poolptr->grab(); + if (!cp->thread_aware()) { + cerr << "MySQL++ wasn't built with thread awareness! " << + argv[0] << " can't run without it." << endl; + return 1; + } + poolptr->release(cp); + } + catch (mysqlpp::Exception& e) { + cerr << "Failed to set up initial pooled connection: " << + e.what() << endl; + return 1; + } + + // Setup complete. Now let's spin some threads... + cout << endl << "Pool created and working correctly. Now to do " + "some real work..." << endl; + srand(time(0)); + bool running[] = { + true, true, true, true, true, true, true, + true, true, true, true, true, true, true }; + const size_t num_threads = sizeof(running) / sizeof(running[0]); + size_t i; + for (i = 0; i < num_threads; ++i) { + if (int err = create_thread(worker_thread, running + i)) { + cerr << "Failed to create thread " << i << + ": error code " << err << endl; + return 1; + } + } + + // Test the 'running' flags every second until we find that they're + // all turned off, indicating that all threads are stopped. + cout.put('W'); cout.flush(); // indicate waiting for completion + do { + sleep(1); + i = 0; + while (i < num_threads && !running[i]) ++i; + } + while (i < num_threads); + cout << endl << "All threads stopped!" << endl; + + // Shut it all down... + delete poolptr; + cout << endl; +#else + (void)argc; // warning squisher + cout << argv[0] << " requires that threads be enabled!" << endl; +#endif + + return 0; +} DELETED examples/custom1.cc Index: examples/custom1.cc ================================================================== --- examples/custom1.cc +++ /dev/null @@ -1,78 +0,0 @@ - -#include -#include -#include -#include -#include - -sql_create_5 (stock, // struct name, - 1, 5, // I'll explain these latter - string, item, // type, id - int, num, - double, weight, - double, price, - Date, sdate) - -// this is calling a very complex macro which will create a custom -// struct "stock" which has the variables: -// string item -// int num -// ... -// Date sdate -// defined as well methods to help populate the class from a mysql row -// among other things that I'll get too in a latter example - -int main () { - try { // its in one big try block - Connection con (use_exceptions); - con.connect ("mysql_cpp_data"); - Query query = con.query (); - query << "select * from stock"; - - vector < stock > res; - query.storein (res); - // this is storing the results into a vector of the custom struct - // "stock" which was created my the macro above. - - cout.setf (ios::left); - cout << setw (17) << "Item" - << setw (4) << "Num" - << setw (7) << "Weight" - << setw (7) << "Price" - << "Date" << endl - << endl; - - // Now we we iterate through the vector using an iterator and - // produce output similar to that using Row - // Notice how we call the actual variables in i and not an index - // offset. This is because the macro at the begging of the file - // set up an *actual* struct of type stock which contains the - // variables item, num, weight, price, and data. - - cout.precision(3); - vector ::iterator i; - for (i = res.begin (); i != res.end (); i++) { - cout << setw (17) << i->item.c_str () - // unfortunally the gnu string class does not respond to format - // modifers so I have to convert it to a conat char *. - << setw (4) << i->num - << setw (7) << i->weight - << setw (7) << i->price - << i->sdate - << endl; - } - return 0; - - } catch (BadQuery er){ // handle any connection - // or query errors that may come up - cerr << "Error: " << er.error << endl; - return -1; - - } catch (BadConversion er) { - // we still need to cache bad conversions incase something goes - // wrong when the data is converted into stock - cerr << "Error: Tried to convert \"" << er.data << "\" to a \"" - << er.type_name << "\"." << endl; - return -1; - } -} DELETED examples/custom2.cc Index: examples/custom2.cc ================================================================== --- examples/custom2.cc +++ /dev/null @@ -1,49 +0,0 @@ - -#include -#include -#include -#include -#include "util.hh" -// util.hh/cc contains the print_stock_table function - -sql_create_5(stock, 1, 5, string, item, int, num, - double, weight, double, price, Date, sdate) - -int main() { - try { // its in one big try block - - Connection con(use_exceptions); - con.connect("mysql_cpp_data"); - Query query = con.query(); - - stock row; - // create an empty stock object - - /* row.item = "Hot Dogs"; - row.num = 100; - row.weight = 1.5; - row.price = 1.75; - row.sdate = "1998-09-25"; */ - row.set("Hot Dogs", 100, 1.5, 1.75, "1998-09-25"); - // populate stock - - query.insert(row); - // form the query to insert the row - // the table name is the name of the struct by default - cout << "Query : " << query.preview() << endl; - // show the query about to be executed - query.execute(); - // execute a query that does not return a result set - - print_stock_table(query); - // now print the new table; - - } catch (BadQuery er) { - cerr << "Error: " << er.error << endl; - return -1; - } catch (BadConversion er) { - cerr << "Error: Tried to convert \"" << er.data << "\" to a \"" - << er.type_name << "\"." << endl; - return -1; - } -} DELETED examples/custom3.cc Index: examples/custom3.cc ================================================================== --- examples/custom3.cc +++ /dev/null @@ -1,56 +0,0 @@ - -#include -#include -#include -#include -#include "util.hh" -// util.hh/cc contains the print_stock_table function - -sql_create_5(stock, 1, 5, string, item, int, num, - double, weight, double, price, Date, sdate) - -int main() { - try { // its in one big try block - - Connection con(use_exceptions); - con.connect("mysql_cpp_data"); - Query query = con.query(); - - query << "select * from stock where item = \"Hotdogs' Buns\" "; - - Result res = query.store(); - if (res.empty()) - throw BadQuery("Hotdogs' Buns not found in table, run reset-db"); - // here we are testing if the query was successful, if not throw a bad query - stock row = res[0]; - // because there should only be one row in this query we don't - // need to use a vector. Just store the first row directly in - // "row". We can do this because one of the constructors for - // stock takes a Row as an parameter. - - stock row2 = row; - // Now we need to create a copy so that the replace query knows - // what the original values are. - - row.item = "Hotdog Buns"; // now change item - - query.update(row2, row); - // form the query to replace the row - // the table name is the name of the struct by default - cout << "Query : " << query.preview() << endl; - // show the query about to be executed - query.execute(); - // execute a query that does not return a result set - - print_stock_table(query); - // now print the new table; - - } catch (BadQuery er) { - cerr << "Error: " << er.error << endl; - return -1; - } catch (BadConversion er) { - cerr << "Error: Tried to convert \"" << er.data << "\" to a \"" - << er.type_name << "\"." << endl; - return -1; - } -} DELETED examples/custom4.cc Index: examples/custom4.cc ================================================================== --- examples/custom4.cc +++ /dev/null @@ -1,73 +0,0 @@ - -#include -#include -#include -#include -#include - -sql_create_5(stock, - 1, // This number is used to make a SSQLS less-than-comparable. - // If this number is n then if the first n elements are the - // same the two SSQLS are the same. - // In this case if two two stock's "item" are the same then - // the two stock are the same. - 5, // this number should generally be the same as the number of - // elements in the list unless you have a good reason not to. - - string,item, int,num, double,weight, double,price, Date,sdate) - -int main() { - try { // its in one big try block - - Connection con(use_exceptions); - con.connect("mysql_cpp_data"); - Query query = con.query(); - - query << "select * from stock"; - - set res; - query.storein(res); - // here we are storing the elements in a set not a vector. - - cout.setf (ios::left); - cout << setw (17) << "Item" - << setw (4) << "Num" - << setw (7) << "Weight" - << setw (7) << "Price" - << "Date" << endl - << endl; - - // Now we we iterate through the set. Since it is a set the list will - // naturally be in order. - - set::iterator i; - cout.precision(3); - for (i = res.begin (); i != res.end (); i++) { - cout << setw (17) << i->item.c_str () - << setw (4) << i->num - << setw (7) << i->weight - << setw (7) << i->price - << i->sdate - << endl; - } - - i = res.find(stock("Hamburger Buns")); - if (i != res.end()) - cout << "Hamburger Buns found. Currently " << i->num << " in stock.\n"; - else - cout << "Sorry no Hamburger Buns found in stock\n"; - - // Now we are using the set's find method to find out how many - // Hamburger Buns are in stock. - - return 0; - - } catch (BadQuery er) { - cerr << "Error: " << er.error << endl; - return -1; - } catch (BadConversion er) { - cerr << "Error: Tried to convert \"" << er.data << "\" to a \"" - << er.type_name << "\"." << endl; - return -1; - } -} ADDED examples/dbinfo.cpp Index: examples/dbinfo.cpp ================================================================== --- /dev/null +++ examples/dbinfo.cpp @@ -0,0 +1,190 @@ +/*********************************************************************** + dbinfo.cpp - Example showing how to request information about the + database schema, such as table names, column types, etc. + + Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and + (c) 2004-2007 by Educational Technology Resources, Inc. Others may + also hold copyrights on code in this file. See the CREDITS file in + the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#include "cmdline.h" +#include "printdata.h" + +#include + +#include +#include +#include +#include + +using namespace std; + + +// Insert a bar into the stream with the given query string centered +static void +separator(ostream& os, string qstr) +{ + string sep("========================================" + "========================================"); + if (qstr.size()) { + string::size_type start = (sep.size() - qstr.size()) / 2; + sep.replace(start - 1, 1, 1, ' '); + sep.replace(start, qstr.size(), qstr); + sep.replace(start + qstr.size(), 1, 1, ' '); + os << "\n\n"; + } + os << sep << endl; +} + + +// Print out the MySQL server version +static void +show_mysql_version(mysqlpp::Connection& con) +{ + separator(cout, ""); + cout << "MySQL version: " << con.client_version(); +} + + +// Print out the names of all the databases managed by the server +static void +show_databases(mysqlpp::Connection& con) +{ + mysqlpp::Query query = con.query("show databases"); + separator(cout, query.str()); + mysqlpp::StoreQueryResult res = query.store(); + + cout << "Databases found: " << res.size(); + cout.setf(ios::left); + mysqlpp::StoreQueryResult::iterator rit; + for (rit = res.begin(); rit != res.end(); ++rit) { + cout << "\n\t" << (*rit)[0]; + } +} + + +// Print information about each of the tables we found +static void +show_table_info(mysqlpp::Connection& con, const vector& tables) +{ + vector::const_iterator it; + for (it = tables.begin(); it != tables.end(); ++it) { + mysqlpp::Query query = con.query(); + query << "describe " << *it; + separator(cout, query.str()); + mysqlpp::StoreQueryResult res = query.store(); + + unsigned int columns = res.num_fields(); + vector widths; + for (unsigned int i = 0; i < columns; ++i) { + string s = res.field_name(i); + if (s.compare("field") == 0) { + widths.push_back(22); + } + else if (s.compare("type") == 0) { + widths.push_back(20); + } + else if (s.compare("null") == 0) { + widths.push_back(4); + } + else if (s.compare("key") == 0) { + widths.push_back(3); + } + else if (s.compare("extra") == 0) { + widths.push_back(0); + } + else { + widths.push_back(15); + } + + if (widths[i]) { + cout << '|' << setw(widths[i]) << res.field_name(i) << '|'; + } + } + cout << endl; + + mysqlpp::StoreQueryResult::iterator rit; + for (rit = res.begin(); rit != res.end(); ++rit) { + for (unsigned int i = 0; i < columns; ++i) { + if (widths[i]) { + cout << ' ' << setw(widths[i]) << + (*rit)[i].c_str() << ' '; + } + } + cout << endl; + } + } +} + + +// Print out the names of all tables in the sample database, and +// return the list of tables. +static void +show_tables(mysqlpp::Connection& con) +{ + mysqlpp::Query query = con.query("show tables"); + separator(cout, query.str()); + mysqlpp::StoreQueryResult res = query.store(); + + cout << "Tables found: " << res.size(); + cout.setf(ios::left); + vector tables; + mysqlpp::StoreQueryResult::iterator rit; + for (rit = res.begin(); rit != res.end(); ++rit) { + string tbl((*rit)[0]); + cout << "\n\t" << tbl; + tables.push_back(tbl); + } + + show_table_info(con, tables); +} + + +// Call all the above functions in sequence +int +main(int argc, char* argv[]) +{ + // Get database access parameters from command line + const char* db = 0, *server = 0, *user = 0, *pass = ""; + if (!parse_command_line(argc, argv, &db, &server, &user, &pass)) { + return 1; + } + + try { + // Connect to server, then dump a bunch of stuff we find on it + mysqlpp::Connection con(db, server, user, pass); + show_mysql_version(con); + show_databases(con); + show_tables(con); + } + catch (const mysqlpp::BadQuery& er) { + // Handle any query errors + cerr << "Query error: " << er.what() << endl; + return -1; + } + catch (const mysqlpp::Exception& er) { + // Catch-all for any other MySQL++ exceptions + cerr << "Error: " << er.what() << endl; + return -1; + } + + return 0; +} ADDED examples/deadlock.cpp Index: examples/deadlock.cpp ================================================================== --- /dev/null +++ examples/deadlock.cpp @@ -0,0 +1,115 @@ +/*********************************************************************** + deadlock.cpp - Demonstrates how MySQL's deadlock detection interacts + with MySQL++'s Transaction class an exception handling mechanism. + Run one copy of this program with the -m1 command line switch, then + while it's waiting for you to press Enter, run another copy with -m2 + instead. + + Copyright (c) 2007 by Jim Wallace and (c) 2007 by Educational + Technology Resources, Inc. Others may also hold copyrights on code + in this file. See the CREDITS file in the top directory of the + distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#include "cmdline.h" + +#include +#include + +#include + +using namespace std; + +// Bring in global holding the value given to the -m switch +extern int run_mode; + + +int +main(int argc, char *argv[]) +{ + // Get database access parameters from command line + const char* db = 0, *server = 0, *user = 0, *pass = ""; + if (!parse_command_line(argc, argv, &db, &server, &user, &pass)) { + return 1; + } + + // Check that the mode parameter was also given and it makes sense + if ((run_mode != 1) && (run_mode != 2)) { + cerr << argv[0] << " must be run with -m1 or -m2 as one of " + "its command-line arguments." << endl; + return 1; + } + + mysqlpp::Connection con; + try { + // Establish the connection to the database server + con.connect(db, server, user, pass); + + // Start a transaction set. Transactions create mutex locks on + // modified rows, so if two programs both touch the same pair of + // rows but in opposite orders at the wrong time, one of the two + // programs will deadlock. The MySQL server knows how to detect + // this situation, and its error return causes MySQL++ to throw + // a BadQuery exception. The point of this example is that if + // you want to detect this problem, you would check the value of + // BadQuery::errnum(), not Connection::errnum(), because the + // transaction rollback process executes a query which succeeds, + // setting the MySQL C API's "last error number" value to 0. + // The exception object carries its own copy of the error number + // at the point the exception was thrown for this very reason. + mysqlpp::Query query = con.query(); + mysqlpp::Transaction trans(con); + + // Build and run the queries, with the order depending on the -m + // flag, so that a second copy of the program will deadlock if + // run while the first is waiting for Enter. + char dummy[100]; + for (int i = 0; i < 2; ++i) { + int lock = run_mode + (run_mode == 1 ? i : -i); + cout << "Trying lock " << lock << "..." << endl; + + query << "select * from deadlock_test" << lock << + " where x = " << lock << " for update"; + query.store(); + + cout << "Acquired lock " << lock << ". Press Enter to "; + cout << (i == 0 ? "try next lock" : "exit"); + cout << ": " << flush; + cin.getline(dummy, sizeof(dummy)); + } + } + catch (mysqlpp::BadQuery e) { + if (e.errnum() == ER_LOCK_DEADLOCK) { + cerr << "Transaction deadlock detected!" << endl; + cerr << "Connection::errnum = " << con.errnum() << + ", BadQuery::errnum = " << e.errnum() << endl; + } + else { + cerr << "Unexpected query error: " << e.what() << endl; + } + return 1; + } + catch (mysqlpp::Exception e) { + cerr << "General error: " << e.what() << endl; + return 1; + } + + return 0; +} ADDED examples/fieldinf.cpp Index: examples/fieldinf.cpp ================================================================== --- /dev/null +++ examples/fieldinf.cpp @@ -0,0 +1,114 @@ +/*********************************************************************** + fieldinf.cpp - Shows how to request information about the fields in a + table, such as their SQL and C++-equivalent types. + + Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and + (c) 2004-2007 by Educational Technology Resources, Inc. Others may + also hold copyrights on code in this file. See the CREDITS file in + the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#include "cmdline.h" +#include "printdata.h" + +#include +#include + +using namespace std; + + +int +main(int argc, char *argv[]) +{ + // Get database access parameters from command line + const char* db = 0, *server = 0, *user = 0, *pass = ""; + if (!parse_command_line(argc, argv, &db, &server, &user, &pass)) { + return 1; + } + + try { + // Establish the connection to the database server. + mysqlpp::Connection con(db, server, user, pass); + + // Get contents of main example table + mysqlpp::Query query = con.query("select * from stock"); + mysqlpp::StoreQueryResult res = query.store(); + + // Show info about each field in that table + char widths[] = { 12, 22, 46 }; + cout.setf(ios::left); + cout << setw(widths[0]) << "Field" << + setw(widths[1]) << "SQL Type" << + setw(widths[2]) << "Equivalent C++ Type" << + endl; + for (size_t i = 0; i < sizeof(widths) / sizeof(widths[0]); ++i) { + cout << string(widths[i] - 1, '=') << ' '; + } + cout << endl; + + for (size_t i = 0; i < res.field_names()->size(); i++) { + // Suppress C++ type name outputs when run under dtest, + // as they're system-specific. + const char* cname = res.field_type(i).name(); + mysqlpp::FieldTypes::value_type ft = res.field_type(i); + ostringstream os; + os << ft.sql_name() << " (" << ft.id() << ')'; + cout << setw(widths[0]) << res.field_name(i).c_str() << + setw(widths[1]) << os.str() << + setw(widths[2]) << cname << + endl; + } + cout << endl; + + // Simple type check + if (res.field_type(0) == typeid(string)) { + cout << "SQL type of 'item' field most closely resembles " + "the C++ string type." << endl; + } + + // Tricky type check: the 'if' path shouldn't happen because the + // description field has the NULL attribute. We need to dig a + // little deeper if we want to ignore this in our type checks. + if (res.field_type(5) == typeid(string)) { + cout << "Should not happen! Type check failure." << endl; + } + else if (res.field_type(5) == typeid(mysqlpp::Null)) { + cout << "SQL type of 'description' field resembles " + "a nullable variant of the C++ string type." << endl; + } + else { + cout << "Weird: fifth field's type is now " << + res.field_type(5).name() << endl; + cout << "Did something recently change in resetdb?" << endl; + } + } + catch (const mysqlpp::BadQuery& er) { + // Handle any query errors + cerr << "Query error: " << er.what() << endl; + return -1; + } + catch (const mysqlpp::Exception& er) { + // Catch-all for any other MySQL++ exceptions + cerr << "Error: " << er.what() << endl; + return -1; + } + + return 0; +} DELETED examples/fieldinf1.cc Index: examples/fieldinf1.cc ================================================================== --- examples/fieldinf1.cc +++ /dev/null @@ -1,66 +0,0 @@ - -#include -#include -#include - -int main() { - try { // its in one big try block - - Connection con(use_exceptions); - con.connect("mysql_cpp_data"); - Query query = con.query(); - query << "select * from stock"; - Result res = query.store(); - - cout << "Query: " << query.preview() << endl; - cout << "Records Found: " << res.size() << endl << endl; - - cout << "Query Info:\n"; - cout.setf(ios::left); - - for (unsigned int i = 0; i < res.names().size(); i++) { - cout << setw(2) << i - << setw(15) << res.names(i).c_str() - // this is the name of the field - << setw(15) << res.types(i).sql_name() - // this is the SQL identifier name - // Result::types(unsigned int) returns a mysql_type_info which in many - // ways is like type_info except that it has additional sql type - // information in it. (with one of the methods being sql_name()) - << setw(20) << res.types(i).name() - // this is the C++ identifier name which most closely resembles - // the sql name (its is implementation defined and often not very readable) - << endl; - } - - cout << endl; - - if (res.types(0) == typeid(string)) - cout << "Field 'item' is of an sql type which most closely resembles a\n" - << "the c++ string type\n"; - // this is demonstrating how a mysql_type_info can be compared with a c++ - // type_info. - - if (res.types(1) == typeid(short int)) - cout << "Field 'num' is of an sql type which most closely resembles a\n" - << "the c++ short int type\n"; - else if (res.types(1).base_type() == typeid(short int)) - cout << "Field 'num' base type is of an sql type which most closely \n" - << "resembles a the c++ short int type\n"; - // However you have to be careful as if it can be null the actual type is - // Null not TYPE. So you should always use the base_type method - // to get at the underlying type. If the type is not null than this base - // type would be the same as its type. - - return 0; - } catch (BadQuery er) { - cerr << "Error: " << er.error << endl; - return -1; - } catch (BadConversion er) { // handle bad conversions - cerr << "Error: Tried to convert \"" << er.data << "\" to a \"" - << er.type_name << "\"." << endl; - return -1; - } -} - - ADDED examples/for_each.cpp Index: examples/for_each.cpp ================================================================== --- /dev/null +++ examples/for_each.cpp @@ -0,0 +1,108 @@ +/*********************************************************************** + for_each.cpp - Demonstrates Query::for_each(), showing how to perform + an arbitrary action on each row in a result set. + + Copyright (c) 2005-2008 by Educational Technology Resources, Inc. and + (c) 2007 by Joel Fielder. Others may also hold copyrights on code + in this file. See the CREDITS file in the top directory of the + distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#include "cmdline.h" +#include "printdata.h" +#include "stock.h" + +#include + +#include + +#include + + +// Define a functor to collect statistics about the stock table +class gather_stock_stats +{ +public: + gather_stock_stats() : + items_(0), + weight_(0), + cost_(0) + { + } + + void operator()(const stock& s) + { + items_ += s.num; + weight_ += (s.num * s.weight); + cost_ += (s.num * s.price); + } + +private: + mysqlpp::sql_bigint items_; + mysqlpp::sql_double weight_, cost_; + + friend std::ostream& operator<<(std::ostream& os, + const gather_stock_stats& ss); +}; + + +// Dump the contents of gather_stock_stats to a stream in human-readable +// form. +std::ostream& +operator<<(std::ostream& os, const gather_stock_stats& ss) +{ + os << ss.items_ << " items " << + "weighing " << ss.weight_ << " stone and " << + "costing " << ss.cost_ << " cowrie shells"; + return os; +} + + +int +main(int argc, char *argv[]) +{ + // Get database access parameters from command line + const char* db = 0, *server = 0, *user = 0, *pass = ""; + if (!parse_command_line(argc, argv, &db, &server, &user, &pass)) { + return 1; + } + + try { + // Establish the connection to the database server. + mysqlpp::Connection con(db, server, user, pass); + + // Gather and display the stats for the entire stock table + mysqlpp::Query query = con.query(); + std::cout << "There are " << query.for_each(stock(), + gather_stock_stats()) << '.' << std::endl; + } + catch (const mysqlpp::BadQuery& e) { + // Something went wrong with the SQL query. + std::cerr << "Query failed: " << e.what() << std::endl; + return 1; + } + catch (const mysqlpp::Exception& er) { + // Catch-all for any other MySQL++ exceptions + std::cerr << "Error: " << er.what() << std::endl; + return 1; + } + + return 0; +} ADDED examples/load_jpeg.cpp Index: examples/load_jpeg.cpp ================================================================== --- /dev/null +++ examples/load_jpeg.cpp @@ -0,0 +1,137 @@ +/*********************************************************************** + load_jpeg.cpp - Example showing how to insert BLOB data into the + database from a file. + + Copyright (c) 1998 by Kevin Atkinson, (c) 1999, 2000 and 2001 by + MySQL AB, and (c) 2004-2007 by Educational Technology Resources, Inc. + Others may also hold copyrights on code in this file. See the CREDITS + file in the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#include "cmdline.h" +#include "printdata.h" + +#include + +#include + +using namespace std; +using namespace mysqlpp; + + +// Pull in a state variable used by att_getopt() implementation so we +// can pick up where standard command line processing leaves off. Feel +// free to ignore this implementation detail. +extern int ag_optind; + + +static bool +is_jpeg(const unsigned char* img_data) +{ + return (img_data[0] == 0xFF) && (img_data[1] == 0xD8) && + ((memcmp(img_data + 6, "JFIF", 4) == 0) || + (memcmp(img_data + 6, "Exif", 4) == 0)); +} + + +int +main(int argc, char *argv[]) +{ + // Get database access parameters from command line + const char* db = 0, *server = 0, *user = 0, *pass = ""; + if (!parse_command_line(argc, argv, &db, &server, &user, &pass, + "[jpeg_file]")) { + return 1; + } + + try { + // Establish the connection to the database server. + mysqlpp::Connection con(db, server, user, pass); + + // Assume that the last command line argument is a file. Try + // to read that file's data into img_data, and check it to see + // if it appears to be a JPEG file. Bail otherwise. + string img_name, img_data; + if (argc - ag_optind >= 1) { + img_name = argv[ag_optind]; + ifstream img_file(img_name.c_str(), ios::ate); + if (img_file) { + size_t img_size = img_file.tellg(); + if (img_size > 10) { + img_file.seekg(0, ios::beg); + unsigned char* img_buffer = new unsigned char[img_size]; + img_file.read(reinterpret_cast(img_buffer), + img_size); + if (is_jpeg(img_buffer)) { + img_data.assign( + reinterpret_cast(img_buffer), + img_size); + } + else { + cerr << '"' << img_file << + "\" isn't a JPEG!" << endl; + } + delete[] img_buffer; + } + else { + cerr << "File is too short to be a JPEG!" << endl; + } + } + } + if (img_data.empty()) { + print_usage(argv[0], "[jpeg_file]"); + return 1; + } + + // Insert image data into the BLOB column in the images table. + // We're inserting it as an std::string instead of using the raw + // data buffer allocated above because we don't want the data + // treated as a C string, which would truncate the data at the + // first null character. + Query query = con.query(); + query << "INSERT INTO images (data) VALUES(\"" << + mysqlpp::escape << img_data << "\")"; + SimpleResult res = query.execute(); + + // If we get here, insertion succeeded + cout << "Inserted \"" << img_name << + "\" into images table, " << img_data.size() << + " bytes, ID " << res.insert_id() << endl; + } + catch (const BadQuery& er) { + // Handle any query errors + cerr << "Query error: " << er.what() << endl; + return -1; + } + catch (const BadConversion& er) { + // Handle bad conversions + cerr << "Conversion error: " << er.what() << endl << + "\tretrieved data size: " << er.retrieved << + ", actual size: " << er.actual_size << endl; + return -1; + } + catch (const Exception& er) { + // Catch-all for any other MySQL++ exceptions + cerr << "Error: " << er.what() << endl; + return -1; + } + + return 0; +} ADDED examples/logo.jpg Index: examples/logo.jpg ================================================================== --- /dev/null +++ examples/logo.jpg cannot compute difference between binary files ADDED examples/multiquery.cpp Index: examples/multiquery.cpp ================================================================== --- /dev/null +++ examples/multiquery.cpp @@ -0,0 +1,207 @@ +/*********************************************************************** + multiquery.cpp - Example showing how to iterate over result sets upon + execution of a query that returns more than one result set. You can + get multiple result sets when executing multiple separate SQL + statments in a single query, or when dealing with the results of + calling a stored procedure. + + Copyright (c) 1998 by Kevin Atkinson, (c) 1999, 2000 and 2001 by + MySQL AB, (c) 2004, 2005 by Educational Technology Resources, Inc., + and (c) 2005 by Arnon Jalon. Others may also hold copyrights on + code in this file. See the CREDITS file in the top directory of + the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#include "cmdline.h" +#include "printdata.h" + +#include + +#include +#include +#include + +using namespace std; +using namespace mysqlpp; + + +typedef vector IntVectorType; + + +static void +print_header(IntVectorType& widths, StoreQueryResult& res) +{ + cout << " |" << setfill(' '); + for (size_t i = 0; i < res.field_names()->size(); i++) { + cout << " " << setw(widths.at(i)) << res.field_name(i) << " |"; + } + cout << endl; +} + + +static void +print_row(IntVectorType& widths, Row& row) +{ + cout << " |" << setfill(' '); + for (size_t i = 0; i < row.size(); ++i) { + cout << " " << setw(widths.at(i)) << row[i] << " |"; + } + cout << endl; +} + + +static void +print_row_separator(IntVectorType& widths) +{ + cout << " +" << setfill('-'); + for (size_t i = 0; i < widths.size(); i++) { + cout << "-" << setw(widths.at(i)) << '-' << "-+"; + } + cout << endl; +} + + +static void +print_result(StoreQueryResult& res, int index) +{ + // Show how many rows are in result, if any + StoreQueryResult::size_type num_results = res.size(); + if (res && (num_results > 0)) { + cout << "Result set " << index << " has " << num_results << + " row" << (num_results == 1 ? "" : "s") << ':' << endl; + } + else { + cout << "Result set " << index << " is empty." << endl; + return; + } + + // Figure out the widths of the result set's columns + IntVectorType widths; + int size = res.num_fields(); + for (int i = 0; i < size; i++) { + widths.push_back(max( + res.field(i).max_length(), + res.field_name(i).size())); + } + + // Print result set header + print_row_separator(widths); + print_header(widths, res); + print_row_separator(widths); + + // Display the result set contents + for (StoreQueryResult::size_type i = 0; i < num_results; ++i) { + print_row(widths, res[i]); + } + + // Print result set footer + print_row_separator(widths); +} + + +static void +print_multiple_results(Query& query) +{ + // Execute query and print all result sets + StoreQueryResult res = query.store(); + print_result(res, 0); + for (int i = 1; query.more_results(); ++i) { + res = query.store_next(); + print_result(res, i); + } +} + + +int +main(int argc, char *argv[]) +{ + // Get connection parameters from command line + const char* db = 0, *server = 0, *user = 0, *pass = ""; + if (!parse_command_line(argc, argv, &db, &server, &user, &pass)) { + return 1; + } + + try { + // Enable multi-queries. Notice that you almost always set + // MySQL++ connection options before establishing the server + // connection, and options are always set using this one + // interface. If you're familiar with the underlying C API, + // you know that there is poor consistency on these matters; + // MySQL++ abstracts these differences away. + Connection con; + con.set_option(new MultiStatementsOption(true)); + + // Connect to the database + if (!con.connect(db, server, user, pass)) { + return 1; + } + + // Set up query with multiple queries. + Query query = con.query(); + query << "DROP TABLE IF EXISTS test_table; " << + "CREATE TABLE test_table(id INT); " << + "INSERT INTO test_table VALUES(10); " << + "UPDATE test_table SET id=20 WHERE id=10; " << + "SELECT * FROM test_table; " << + "DROP TABLE test_table"; + cout << "Multi-query: " << endl << query << endl; + + // Execute statement and display all result sets. + print_multiple_results(query); + +#if MYSQL_VERSION_ID >= 50000 + // If it's MySQL v5.0 or higher, also test stored procedures, which + // return their results the same way multi-queries do. + query << "DROP PROCEDURE IF EXISTS get_stock; " << + "CREATE PROCEDURE get_stock" << + "( i_item varchar(20) ) " << + "BEGIN " << + "SET i_item = concat('%', i_item, '%'); " << + "SELECT * FROM stock WHERE lower(item) like lower(i_item); " << + "END;"; + cout << "Stored procedure query: " << endl << query << endl; + + // Create the stored procedure. + print_multiple_results(query); + + // Call the stored procedure and display its results. + query << "CALL get_stock('relish')"; + cout << "Query: " << query << endl; + print_multiple_results(query); +#endif + + return 0; + } + catch (const BadOption& err) { + cerr << err.what() << endl; + cerr << "This example requires MySQL 4.1.1 or later." << endl; + return 1; + } + catch (const ConnectionFailed& err) { + cerr << "Failed to connect to database server: " << + err.what() << endl; + return 1; + } + catch (const Exception& er) { + // Catch-all for any other MySQL++ exceptions + cerr << "Error: " << er.what() << endl; + return 1; + } +} ADDED examples/printdata.cpp Index: examples/printdata.cpp ================================================================== --- /dev/null +++ examples/printdata.cpp @@ -0,0 +1,116 @@ +/*********************************************************************** + printdata.cpp - Utility functions for printing out data in common + formats, required by most of the example programs. + + Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and + (c) 2004-2007 by Educational Technology Resources, Inc. Others may + also hold copyrights on code in this file. See the CREDITS file in + the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#include "printdata.h" + +#include +#include + +using namespace std; + + +//// print_stock_header //////////////////////////////////////////////// +// Display a header suitable for use with print_stock_rows(). + +void +print_stock_header(int rows) +{ + cout << "Records found: " << rows << endl << endl; + cout.setf(ios::left); + cout << setw(31) << "Item" << + setw(10) << "Num" << + setw(10) << "Weight" << + setw(10) << "Price" << + "Date" << endl << endl; +} + + +//// print_stock_row /////////////////////////////////////////////////// +// Print out a row of data from the stock table, in a format compatible +// with the header printed out in the previous function. + +void +print_stock_row(const mysqlpp::sql_char& item, mysqlpp::sql_bigint num, + mysqlpp::sql_double weight, mysqlpp::sql_decimal price, + const mysqlpp::sql_date& date) +{ + cout << setw(30) << item << ' ' << + setw(9) << num << ' ' << + setw(9) << weight << ' ' << + setw(9) << price << ' ' << + date << endl; +} + + +//// print_stock_row /////////////////////////////////////////////////// +// Take a Row from the example 'stock' table, break it up into fields, +// and call the above version of this function. + +void +print_stock_row(const mysqlpp::Row& row) +{ + print_stock_row(string(row[0]), row[1], row[2], row[3], row[4]); +} + + +//// print_stock_rows ////////////////////////////////////////////////// +// Print out a number of rows from the example 'stock' table. + +void +print_stock_rows(mysqlpp::StoreQueryResult& res) +{ + print_stock_header(res.size()); + + // Use the StoreQueryResult class's read-only random access iterator to walk + // through the query results. + mysqlpp::StoreQueryResult::iterator i; + for (i = res.begin(); i != res.end(); ++i) { + // Notice that a dereferenced result iterator can be converted + // to a Row object, which makes for easier element access. + print_stock_row(*i); + } +} + + +//// print_stock_table ///////////////////////////////////////////////// +// Simply retrieve and print the entire contents of the stock table. + +void +print_stock_table(mysqlpp::Query& query) +{ + // Reset query object to its pristine state in case it's been used + // before by our caller for template queries. + query.reset(); + + // Build the query itself, and show it to the user + query << "select * from stock"; + cout << "Query: " << query << endl; + + // Execute it, and display the results + mysqlpp::StoreQueryResult res = query.store(); + print_stock_rows(res); +} ADDED examples/printdata.h Index: examples/printdata.h ================================================================== --- /dev/null +++ examples/printdata.h @@ -0,0 +1,42 @@ +/*********************************************************************** + printdata.h - Declares utility routines for printing out data in + common forms, used by most of the example programs. + + Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and + (c) 2004-2007 by Educational Technology Resources, Inc. Others may + also hold copyrights on code in this file. See the CREDITS file in + the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#if !defined(MYSQLPP_PRINTDATA_H) +#define MYSQLPP_PRINTDATA_H + +#include + +void print_stock_header(int rows); +void print_stock_row(const mysqlpp::Row& r); +void print_stock_row(const mysqlpp::sql_char& item, + mysqlpp::sql_bigint num, mysqlpp::sql_double weight, + mysqlpp::sql_decimal price, const mysqlpp::sql_date& date); +void print_stock_rows(mysqlpp::StoreQueryResult& res); +void print_stock_table(mysqlpp::Query& query); + +#endif // !defined(MYSQLPP_PRINTDATA_H) + DELETED examples/resetdb.cc Index: examples/resetdb.cc ================================================================== --- examples/resetdb.cc +++ /dev/null @@ -1,79 +0,0 @@ - -#include -#include - -int main (int argc, char *argv[]) { - Connection connection(use_exceptions); - try { // the entire main block is one big try block; - - if (argc == 1) connection.connect(""); - else if (argc == 2) connection.connect("",argv[1]); - else if (argc == 3) connection.connect("",argv[1],argv[2]); - else if (argc <= 4) connection.connect("",argv[1],argv[2],argv[3]); - // create a new object and connect based on any (if any) arguments - // passed to main(); - - try { - connection.select_db("mysql_cpp_data"); - } catch (BadQuery er) { - // if it couldn't connect to the database assume that it doesn't exist - // and try created it. If that does not work exit with an error. - connection.create_db("mysql_cpp_data"); - connection.select_db("mysql_cpp_data"); - } - - Query query = connection.query(); // create a new query object - - try { // ignore any errors here - // I hope to make this simpler soon - query.execute("drop table stock"); - } catch (BadQuery er) {} - - query << "create table stock (item char(20) not null, num smallint," - << "weight double, price double, sdate date)"; - query.execute(RESET_QUERY); - // send the query to create the table and execute it. The - // RESET_QUERY tells the query object to reset it self after - // execution - - query << "insert into %5:table values (%0q, %1q, %2, %3, %4q)"; - query.parse(); - // set up the template query I will use to insert the data. The - // parse method call is important as it is what lets the query - // know that this is a template and not a literal string - - query.def["table"] = "stock"; - // This is setting the parameter named table to stock. - - query.execute ("Hamburger Buns", 56, 1.25, 1.1, "1998-04-26"); - query.execute ("Hotdogs' Buns" ,65, 1.1 , 1.1, "1998-04-23"); - query.execute ("Dinner Roles" , 75, .95, .97, "1998-05-25"); - query.execute ("White Bread" , 87, 1.5, 1.75, "1998-09-04"); - // The last parameter "table" is not specified here. Thus - // the default value for "table" is used which is "stock". - - } catch (BadQuery er) { // handle any errors that may come up - cerr << "Error: " << er.error << endl; - return -1; - } -} - - - - - - - - - - - - - - - - - - - - ADDED examples/resetdb.cpp Index: examples/resetdb.cpp ================================================================== --- /dev/null +++ examples/resetdb.cpp @@ -0,0 +1,214 @@ +/*********************************************************************** + resetdb.cpp - (Re)initializes the example database, mysql_cpp_data. + You must run this at least once before running most of the other + examples, and it is helpful sometimes to run it again, as some of + the examples modify the table in this database. + + Copyright (c) 1998 by Kevin Atkinson, (c) 1999, 2000 and 2001 by + MySQL AB, and (c) 2004-2008 by Educational Technology Resources, Inc. + Others may also hold copyrights on code in this file. See the CREDITS + file in the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#include "cmdline.h" +#include "printdata.h" + +#include + +#include + +using namespace std; + + +// Pull in the sample database name from the cmdline module. +extern const char* kpcSampleDatabase; + + +// Convert a packed version number in the format used within MySQL++ +// to a printable string. +static string +version_str(int packed) +{ + char buf[9]; + snprintf(buf, sizeof(buf), "%d.%d.%d", + (packed & 0xFF0000) >> 16, + (packed & 0x00FF00) >> 8, + (packed & 0x0000FF)); + return buf; +} + + +int +main(int argc, char *argv[]) +{ + // Ensure that we're not mixing library and header file versions. + // This is really easy to do if you have MySQL++ on your system and + // are trying to build a new version, and run the examples directly + // instead of through exrun. + if (mysqlpp::get_library_version() != MYSQLPP_HEADER_VERSION) { + cerr << "Version mismatch: library is v" << + version_str(mysqlpp::get_library_version()) << + ", headers are v" << + version_str(MYSQLPP_HEADER_VERSION) << + ". Are you running this" << endl << + "with exrun? See README.examples." << endl; + return 1; + } + + // Connect to database server + const char *server = 0, *user = 0, *pass = ""; + mysqlpp::Connection con; + try { + if (parse_command_line(argc, argv, 0, &server, &user, &pass)) { + extern bool dtest_mode; + if (dtest_mode) { + cout << "Connecting to database server..." << endl; + } + else { + cout << "Connecting to '" << + (user ? user : "USERNAME") << "'@'" << + (server ? server : "localhost") << "', with" << + (pass[0] ? "" : "out") << " password..." << endl; + } + con.connect(0, server, user, pass); + } + else { + return 1; // command line parsing failed + } + } + catch (exception& er) { + cerr << "Connection failed: " << er.what() << endl; + return 1; + } + + // Create new sample database, or re-create it. We suppress + // exceptions, because it's not an error if DB doesn't yet exist. + bool new_db = false; + { + mysqlpp::NoExceptions ne(con); + mysqlpp::Query query = con.query(); + if (con.select_db(kpcSampleDatabase)) { + // Toss old tables, ignoring errors because it would just + // mean the table doesn't exist, which doesn't matter. + cout << "Dropping existing sample data tables..." << endl; + query.exec("drop table stock"); + query.exec("drop table images"); + query.exec("drop table deadlock_test1"); + query.exec("drop table deadlock_test2"); + } + else { + // Database doesn't exist yet, so create and select it. + if (con.create_db(kpcSampleDatabase) && + con.select_db(kpcSampleDatabase)) { + new_db = true; + } + else { + cerr << "Error creating DB: " << con.error() << endl; + return 1; + } + } + } + + // Create sample data table within sample database. + try { + // Send the query to create the stock table and execute it. + cout << "Creating stock table..." << endl; + mysqlpp::Query query = con.query(); + query << + "CREATE TABLE stock (" << + " item CHAR(30) NOT NULL, " << + " num BIGINT NOT NULL, " << + " weight DOUBLE NOT NULL, " << + " price DECIMAL(6,2) NOT NULL, " << + " sdate DATE NOT NULL, " << + " description MEDIUMTEXT NULL) " << + "ENGINE = InnoDB " << + "CHARACTER SET utf8 COLLATE utf8_general_ci"; + query.execute(); + + // Set up the template query to insert the data. The parse() + // call tells the query object that this is a template and + // not a literal query string. + query << "insert into %6:table values " << + "(%0q, %1q, %2, %3, %4q, %5q:desc)"; + query.parse(); + + // Set a default for template query parameters "table" and "desc". + query.template_defaults["table"] = "stock"; + query.template_defaults["desc"] = mysqlpp::null; + + // Notice that we don't give a sixth parameter in these calls, + // so the default value of "stock" is used. Also notice that + // the first row is a UTF-8 encoded Unicode string! All you + // have to do to store Unicode data in recent versions of MySQL + // is use UTF-8 encoding. + cout << "Populating stock table..." << flush; + query.execute("Nürnberger Brats", 97, 1.5, 8.79, "2005-03-10"); + query.execute("Pickle Relish", 87, 1.5, 1.75, "1998-09-04"); + query.execute("Hot Mustard", 73, .95, .97, "1998-05-25", + "good American yellow mustard, not that European stuff"); + query.execute("Hotdog Buns", 65, 1.1, 1.1, "1998-04-23"); + + // Test that above did what we wanted. + cout << "inserted " << con.count_rows("stock") << " rows." << endl; + + // Now create empty images table, for testing BLOB and auto- + // increment column features. + cout << "Creating empty images table..." << endl; + query.reset(); // forget template query info + query << + "CREATE TABLE images (" << + " id INT UNSIGNED NOT NULL AUTO_INCREMENT, " << + " data BLOB, " << + " PRIMARY KEY (id)" << + ")"; + query.execute(); + + // Create the tables used by examples/deadlock.cpp + cout << "Creating deadlock testing tables..." << endl; + query.execute("CREATE TABLE deadlock_test1 (x INT) ENGINE=innodb"); + query.execute("CREATE TABLE deadlock_test2 (x INT) ENGINE=innodb"); + query.execute("INSERT INTO deadlock_test1 VALUES (1);"); + query.execute("INSERT INTO deadlock_test2 VALUES (2);"); + + // Report success + cout << (new_db ? "Created" : "Reinitialized") << + " sample database successfully." << endl; + } + catch (const mysqlpp::BadQuery& er) { + // Handle any query errors + cerr << endl << "Query error: " << er.what() << endl; + return 1; + } + catch (const mysqlpp::BadConversion& er) { + // Handle bad conversions + cerr << endl << "Conversion error: " << er.what() << endl << + "\tretrieved data size: " << er.retrieved << + ", actual size: " << er.actual_size << endl; + return 1; + } + catch (const mysqlpp::Exception& er) { + // Catch-all for any other MySQL++ exceptions + cerr << endl << "Error: " << er.what() << endl; + return 1; + } + + return 0; +} DELETED examples/simple1.cc Index: examples/simple1.cc ================================================================== --- examples/simple1.cc +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include -#include - -int main() { - Connection con("mysql_cpp_data"); - // The full format for the Connection constructor is - // Connection(cchar *db, cchar *host="", - // cchar *user="", cchar *passwd="") - // You may need to specify some of them if the database is not on - // the local machine or you database username is not the same as your - // login name, etc.. - - Query query = con.query(); - // This creates a query object that is bound to con. - - query << "select * from stock"; - // You can write to the query object like you would any other ostrem - - Result res = query.store(); - // Query::store() executes the query and returns the results - - cout << "Query: " << query.preview() << endl; - // Query::preview() simply returns a string with the current query - // string in it. - - cout << "Records Found: " << res.size() << endl << endl; - - Row row; - cout.setf(ios::left); - cout << setw(17) << "Item" - << setw(4) << "Num" - << setw(7) << "Weight" - << setw(7) << "Price" - << "Date" << endl - << endl; - - Result::iterator i; - // The Result class has a read-only Random Access Iterator - for (i = res.begin(); i != res.end(); i++) { - row = *i; - cout << setw(17) << row[0] - << setw(4) << row[1] - << setw(7) << row["weight"] - // you can use either the index number or column name when - // retrieving the colume data as demonstrated above. - << setw(7) << row[3] - << row[4] << endl; - } - return 0; -} ADDED examples/simple1.cpp Index: examples/simple1.cpp ================================================================== --- /dev/null +++ examples/simple1.cpp @@ -0,0 +1,70 @@ +/*********************************************************************** + simple1.cpp - Example showing the simplest way to get data from a MySQL + table with MySQL++. + + Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and + (c) 2004-2007 by Educational Technology Resources, Inc. Others may + also hold copyrights on code in this file. See the CREDITS file in + the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#include "cmdline.h" +#include "printdata.h" + +#include + +#include +#include + +using namespace std; + +int +main(int argc, char *argv[]) +{ + // Get database access parameters from command line + const char* db = 0, *server = 0, *user = 0, *pass = ""; + if (!parse_command_line(argc, argv, &db, &server, &user, &pass)) { + return 1; + } + + // Connect to the sample database. + mysqlpp::Connection conn(false); + if (conn.connect(db, server, user, pass)) { + // Retrieve a subset of the sample stock table set up by resetdb + // and display it. + mysqlpp::Query query = conn.query("select item from stock"); + if (mysqlpp::StoreQueryResult res = query.store()) { + cout << "We have:" << endl; + for (size_t i = 0; i < res.num_rows(); ++i) { + cout << '\t' << res[i][0] << endl; + } + } + else { + cerr << "Failed to get item list: " << query.error() << endl; + return 1; + } + + return 0; + } + else { + cerr << "DB connection failed: " << conn.error() << endl; + return 1; + } +} ADDED examples/simple2.cpp Index: examples/simple2.cpp ================================================================== --- /dev/null +++ examples/simple2.cpp @@ -0,0 +1,85 @@ +/*********************************************************************** + simple2.cpp - Retrieves the entire contents of the sample stock table + using a "store" query, and prints it out. + + Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and + (c) 2004-2007 by Educational Technology Resources, Inc. Others may + also hold copyrights on code in this file. See the CREDITS file in + the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#include "cmdline.h" +#include "printdata.h" + +#include + +#include +#include + +using namespace std; + +int +main(int argc, char *argv[]) +{ + // Get database access parameters from command line + const char* db = 0, *server = 0, *user = 0, *pass = ""; + if (!parse_command_line(argc, argv, &db, &server, &user, &pass)) { + return 1; + } + + // Connect to the sample database. + mysqlpp::Connection conn(false); + if (conn.connect(db, server, user, pass)) { + // Retrieve the sample stock table set up by resetdb + mysqlpp::Query query = conn.query("select * from stock"); + mysqlpp::StoreQueryResult res = query.store(); + + // Display results + if (res) { + // Display header + cout.setf(ios::left); + cout << setw(31) << "Item" << + setw(10) << "Num" << + setw(10) << "Weight" << + setw(10) << "Price" << + "Date" << endl << endl; + + // Get each row in result set, and print its contents + for (size_t i = 0; i < res.num_rows(); ++i) { + cout << setw(30) << res[i]["item"] << ' ' << + setw(9) << res[i]["num"] << ' ' << + setw(9) << res[i]["weight"] << ' ' << + setw(9) << res[i]["price"] << ' ' << + setw(9) << res[i]["sdate"] << + endl; + } + } + else { + cerr << "Failed to get stock table: " << query.error() << endl; + return 1; + } + + return 0; + } + else { + cerr << "DB connection failed: " << conn.error() << endl; + return 1; + } +} ADDED examples/simple3.cpp Index: examples/simple3.cpp ================================================================== --- /dev/null +++ examples/simple3.cpp @@ -0,0 +1,92 @@ +/*********************************************************************** + simple3.cpp - Example showing how to use the 'use' method of retrieving + a table, as opposed to the more common 'store' method illustrated + by the simple2 example. + + Copyright (c) 2005-2007 by Educational Technology Resources, Inc. + Others may also hold copyrights on code in this file. See the CREDITS + file in the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#include "cmdline.h" +#include "printdata.h" + +#include + +#include +#include + +using namespace std; + +int +main(int argc, char *argv[]) +{ + // Get database access parameters from command line + const char* db = 0, *server = 0, *user = 0, *pass = ""; + if (!parse_command_line(argc, argv, &db, &server, &user, &pass)) { + return 1; + } + + // Connect to the sample database. + mysqlpp::Connection conn(false); + if (conn.connect(db, server, user, pass)) { + // Ask for all rows from the sample stock table and display + // them. Unlike simple2 example, we retreive each row one at + // a time instead of storing the entire result set in memory + // and then iterating over it. + mysqlpp::Query query = conn.query("select * from stock"); + if (mysqlpp::UseQueryResult res = query.use()) { + // Display header + cout.setf(ios::left); + cout << setw(31) << "Item" << + setw(10) << "Num" << + setw(10) << "Weight" << + setw(10) << "Price" << + "Date" << endl << endl; + + // Get each row in result set, and print its contents + while (mysqlpp::Row row = res.fetch_row()) { + cout << setw(30) << row["item"] << ' ' << + setw(9) << row["num"] << ' ' << + setw(9) << row["weight"] << ' ' << + setw(9) << row["price"] << ' ' << + setw(9) << row["sdate"] << + endl; + } + + // Check for error: can't distinguish "end of results" and + // error cases in return from fetch_row() otherwise. + if (conn.errnum()) { + cerr << "Error received in fetching a row: " << + conn.error() << endl; + return 1; + } + return 0; + } + else { + cerr << "Failed to get stock item: " << query.error() << endl; + return 1; + } + } + else { + cerr << "DB connection failed: " << conn.error() << endl; + return 1; + } +} DELETED examples/sinisa_ex.cc Index: examples/sinisa_ex.cc ================================================================== --- examples/sinisa_ex.cc +++ /dev/null @@ -1,96 +0,0 @@ -#include -#include -vector yy; -#include -#include -#include - -int main() { - Connection con(use_exceptions); - try { - con.real_connect ("","localhost","root","",3306,(int)0,60,NULL); - - cout << con.clinet_info() << endl << endl; - Query query = con.query(); - - query << "show databases"; - - Result res = query.store(); - - cout << "Query: " << query.preview() << endl; - - cout << "Records Found: " << res.size() << endl << endl; - - Row row; - cout.setf(ios::left); - cout << setw(17) << "Databases" << endl << endl; - - Result::iterator i; - for (i = res.begin(); i != res.end(); i++) { - row = *i; - cout << setw(17) << row[0] << endl; - } - char database [] = "mysql"; - con.select_db (database); - - query << "show tables"; - - res = query.store(); - - cout << "Query: " << query.preview() << endl; - - cout << "Records Found: " << res.size() << endl << endl; - - cout.setf(ios::left); - cout << setw(17) << "Tables" << endl << endl; - - for (i = res.begin(); i != res.end(); i++) { - row = *i; - string xx(row[0]); - cout << setw(17) << row[0] << endl; - yy.insert(yy.end(),xx); - } - for (unsigned int j = 0; j < yy.size();j++) { - query << "describe " << yy[j] << ""; - cout << query.preview() << endl << endl; - res = query.store(); - unsigned int columns = res.num_fields(), counter; - cout << setw(15) << endl; - for (counter = 0; counter < columns; counter++) { - cout << setw(15) << res.names(counter) << " "; - } - cout << endl << endl; - for (i = res.begin(); i!=res.end();i++) { - row = *i; - for (counter = 0; counter < columns; counter++) { - cout << row[counter] << " "; - } - cout << endl; - } - } - query << "select * from user"; - res = query.store(); int columns = res.num_fields(); - cout << query.preview() << endl << endl; - cout << "fields = " << res.num_fields() << "rows = " << res.size() << endl; - for (i = res.begin(); i!=res.end();i++) { - row = *i; - for (int counter = 0; counter < columns; counter++) { - cout << row[counter] << " "; - } - cout << endl; - } - } catch (BadQuery er){ // handle any connection - // or query errors that may come up - cerr << "Error: " << er.error << " " << con.errnum() << endl; - return -1; - - } catch (BadConversion er) { - // we still need to cache bad conversions incase something goes - // wrong when the data is converted into stock - cerr << "Error: Tried to convert \"" << er.data << "\" to a \"" - << er.type_name << "\"." << endl; - return -1; - } - -} - ADDED examples/ssqls1.cpp Index: examples/ssqls1.cpp ================================================================== --- /dev/null +++ examples/ssqls1.cpp @@ -0,0 +1,89 @@ +/*********************************************************************** + ssqls1.cpp - Example that produces the same results as simple1, but it + uses a Specialized SQL Structure to store the results instead of a + MySQL++ Result object. + + Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and + (c) 2004-2008 by Educational Technology Resources, Inc. Others may + also hold copyrights on code in this file. See the CREDITS file in + the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#include "cmdline.h" +#include "printdata.h" +#include "stock.h" + +#include +#include + +using namespace std; + +int +main(int argc, char *argv[]) +{ + // Get database access parameters from command line + const char* db = 0, *server = 0, *user = 0, *pass = ""; + if (!parse_command_line(argc, argv, &db, &server, &user, &pass)) { + return 1; + } + + try { + // Establish the connection to the database server. + mysqlpp::Connection con(db, server, user, pass); + + // Retrieve a subset of the stock table's columns, and store + // the data in a vector of 'stock' SSQLS structures. See the + // user manual for the consequences arising from this quiet + // ability to store a subset of the table in the stock SSQLS. + mysqlpp::Query query = con.query("select item,description from stock"); + vector res; + query.storein(res); + + // Display the items + cout << "We have:" << endl; + vector::iterator it; + for (it = res.begin(); it != res.end(); ++it) { + cout << '\t' << it->item; + if (it->description != mysqlpp::null) { + cout << " (" << it->description << ")"; + } + cout << endl; + } + } + catch (const mysqlpp::BadQuery& er) { + // Handle any query errors + cerr << "Query error: " << er.what() << endl; + return -1; + } + catch (const mysqlpp::BadConversion& er) { + // Handle bad conversions; e.g. type mismatch populating 'stock' + cerr << "Conversion error: " << er.what() << endl << + "\tretrieved data size: " << er.retrieved << + ", actual size: " << er.actual_size << endl; + return -1; + } + catch (const mysqlpp::Exception& er) { + // Catch-all for any other MySQL++ exceptions + cerr << "Error: " << er.what() << endl; + return -1; + } + + return 0; +} ADDED examples/ssqls2.cpp Index: examples/ssqls2.cpp ================================================================== --- /dev/null +++ examples/ssqls2.cpp @@ -0,0 +1,88 @@ +/*********************************************************************** + ssqls2.cpp - Example showing how to insert a row using the Specialized + SQL Structures feature of MySQL++. + + Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and + (c) 2004-2008 by Educational Technology Resources, Inc. Others may + also hold copyrights on code in this file. See the CREDITS file in + the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#include "cmdline.h" +#include "printdata.h" +#include "stock.h" + +#include + +using namespace std; + +int +main(int argc, char *argv[]) +{ + // Get database access parameters from command line + const char* db = 0, *server = 0, *user = 0, *pass = ""; + if (!parse_command_line(argc, argv, &db, &server, &user, &pass)) { + return 1; + } + + try { + // Establish the connection to the database server. + mysqlpp::Connection con(db, server, user, pass); + + // Create and populate a stock object. We could also have used + // the set() member, which takes the same parameters as this + // constructor. + stock row("Hot Dogs", 100, 1.5, 1.75, + mysqlpp::sql_date("1998-09-25"), mysqlpp::null); + + // Form the query to insert the row into the stock table. + mysqlpp::Query query = con.query(); + query.insert(row); + + // Show the query about to be executed. + cout << "Query: " << query << endl; + + // Execute the query. We use execute() because INSERT doesn't + // return a result set. + query.execute(); + + // Retrieve and print out the new table contents. + print_stock_table(query); + } + catch (const mysqlpp::BadQuery& er) { + // Handle any query errors + cerr << "Query error: " << er.what() << endl; + return -1; + } + catch (const mysqlpp::BadConversion& er) { + // Handle bad conversions + cerr << "Conversion error: " << er.what() << endl << + "\tretrieved data size: " << er.retrieved << + ", actual size: " << er.actual_size << endl; + return -1; + } + catch (const mysqlpp::Exception& er) { + // Catch-all for any other MySQL++ exceptions + cerr << "Error: " << er.what() << endl; + return -1; + } + + return 0; +} ADDED examples/ssqls3.cpp Index: examples/ssqls3.cpp ================================================================== --- /dev/null +++ examples/ssqls3.cpp @@ -0,0 +1,108 @@ +/*********************************************************************** + ssqls3.cpp - Example showing how to update an SQL row using the + Specialized SQL Structures feature of MySQL++. + + Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and + (c) 2004-2008 by Educational Technology Resources, Inc. Others may + also hold copyrights on code in this file. See the CREDITS file in + the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#include "cmdline.h" +#include "printdata.h" +#include "stock.h" + +#include + +using namespace std; + +int +main(int argc, char *argv[]) +{ + // Get database access parameters from command line + const char* db = 0, *server = 0, *user = 0, *pass = ""; + if (!parse_command_line(argc, argv, &db, &server, &user, &pass)) { + return 1; + } + + try { + // Establish the connection to the database server. + mysqlpp::Connection con(db, server, user, pass); + + // Build a query to retrieve the stock item that has Unicode + // characters encoded in UTF-8 form. + mysqlpp::Query query = con.query( + "select * from stock where item = \"Nürnberger Brats\""); + + // Retrieve the row, throwing an exception if it fails. + mysqlpp::StoreQueryResult res = query.store(); + if (res.empty()) { + throw mysqlpp::BadQuery("UTF-8 bratwurst item not found in " + "table, run resetdb"); + } + + // Because there should only be one row in the result set, + // there's no point in storing the result in an STL container. + // We can store the first row directly into a stock structure + // because one of an SSQLS's constructors takes a Row object. + stock row = res[0]; + + // Create a copy so that the replace query knows what the + // original values are. + stock orig_row = row; + + // Change the stock object's item to use only 7-bit ASCII, and + // to deliberately be wider than normal column widths printed + // by print_stock_table(). + row.item = "Nuerenberger Bratwurst"; + + // Form the query to replace the row in the stock table. + query.update(orig_row, row); + + // Show the query about to be executed. + cout << "Query: " << query << endl; + + // Run the query with execute(), since UPDATE doesn't return a + // result set. + query.execute(); + + // Retrieve and print out the new table contents. + print_stock_table(query); + } + catch (const mysqlpp::BadQuery& er) { + // Handle any query errors + cerr << "Query error: " << er.what() << endl; + return -1; + } + catch (const mysqlpp::BadConversion& er) { + // Handle bad conversions + cerr << "Conversion error: " << er.what() << endl << + "\tretrieved data size: " << er.retrieved << + ", actual size: " << er.actual_size << endl; + return -1; + } + catch (const mysqlpp::Exception& er) { + // Catch-all for any other MySQL++ exceptions + cerr << "Error: " << er.what() << endl; + return -1; + } + + return 0; +} ADDED examples/ssqls4.cpp Index: examples/ssqls4.cpp ================================================================== --- /dev/null +++ examples/ssqls4.cpp @@ -0,0 +1,100 @@ +/*********************************************************************** + ssqls4.cpp - Example very similar to ssqls1.cpp, except that it + stores its result set in an STL set container. This demonstrates + how one can manipulate MySQL++ result sets in a very natural C++ + style. + + Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and + (c) 2004-2008 by Educational Technology Resources, Inc. Others may + also hold copyrights on code in this file. See the CREDITS file in + the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#include "cmdline.h" +#include "printdata.h" +#include "stock.h" + +#include + +using namespace std; + +int +main(int argc, char *argv[]) +{ + // Get database access parameters from command line + const char* db = 0, *server = 0, *user = 0, *pass = ""; + if (!parse_command_line(argc, argv, &db, &server, &user, &pass)) { + return 1; + } + + try { + // Establish the connection to the database server. + mysqlpp::Connection con(db, server, user, pass); + + // Retrieve all rows from the stock table and put them in an + // STL set. Notice that this works just as well as storing them + // in a vector, which we did in ssqls1.cpp. It works because + // SSQLS objects are less-than comparable. + mysqlpp::Query query = con.query("select * from stock"); + set res; + query.storein(res); + + // Display the result set. Since it is an STL set and we set up + // the SSQLS to compare based on the item column, the rows will + // be sorted by item. + print_stock_header(res.size()); + set::iterator it; + cout.precision(3); + for (it = res.begin(); it != res.end(); ++it) { + print_stock_row(it->item.c_str(), it->num, it->weight, + it->price, it->sdate); + } + + // Use set's find method to look up a stock item by item name. + // This also uses the SSQLS comparison setup. + it = res.find(stock("Hotdog Buns")); + if (it != res.end()) { + cout << endl << "Currently " << it->num << + " hotdog buns in stock." << endl; + } + else { + cout << endl << "Sorry, no hotdog buns in stock." << endl; + } + } + catch (const mysqlpp::BadQuery& er) { + // Handle any query errors + cerr << "Query error: " << er.what() << endl; + return -1; + } + catch (const mysqlpp::BadConversion& er) { + // Handle bad conversions + cerr << "Conversion error: " << er.what() << endl << + "\tretrieved data size: " << er.retrieved << + ", actual size: " << er.actual_size << endl; + return -1; + } + catch (const mysqlpp::Exception& er) { + // Catch-all for any other MySQL++ exceptions + cerr << "Error: " << er.what() << endl; + return -1; + } + + return 0; +} ADDED examples/ssqls5.cpp Index: examples/ssqls5.cpp ================================================================== --- /dev/null +++ examples/ssqls5.cpp @@ -0,0 +1,85 @@ +/*********************************************************************** + ssqls5.cpp - Example showing how to use the equal_list() member of + some SSQLS types to build SELECT queries with custom WHERE clauses. + + Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, (c) + 2004-2008 by Educational Technology Resources, Inc., and (c) 2005 by + Chris Frey. Others may also hold copyrights on code in this file. + See the CREDITS file in the top directory of the distribution for + details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#include "cmdline.h" +#include "printdata.h" +#include "stock.h" + +#include +#include + +using namespace std; + +int +main(int argc, char *argv[]) +{ + // Get database access parameters from command line + const char* db = 0, *server = 0, *user = 0, *pass = ""; + if (!parse_command_line(argc, argv, &db, &server, &user, &pass)) { + return 1; + } + + try { + // Establish the connection to the database server. + mysqlpp::Connection con(db, server, user, pass); + + // Get all the rows in the stock table. + mysqlpp::Query query = con.query("select * from stock"); + vector res; + query.storein(res); + + if (res.size() > 0) { + // Build a select query using the data from the first row + // returned by our previous query. + query << "select * from stock where " << + res[0].equal_list(" and ", stock_weight, stock_price); + + // Display the finished query. + cout << "Custom query:\n" << query << endl; + } + } + catch (const mysqlpp::BadQuery& er) { + // Handle any query errors + cerr << "Query error: " << er.what() << endl; + return -1; + } + catch (const mysqlpp::BadConversion& er) { + // Handle bad conversions + cerr << "Conversion error: " << er.what() << endl << + "\tretrieved data size: " << er.retrieved << + ", actual size: " << er.actual_size << endl; + return -1; + } + catch (const mysqlpp::Exception& er) { + // Catch-all for any other MySQL++ exceptions + cerr << "Error: " << er.what() << endl; + return -1; + } + + return 0; +} ADDED examples/stock.h Index: examples/stock.h ================================================================== --- /dev/null +++ examples/stock.h @@ -0,0 +1,47 @@ +/*********************************************************************** + stock.h - Declares the stock SSQLS used by several of the examples. + + Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and + (c) 2004-2008 by Educational Technology Resources, Inc. Others may + also hold copyrights on code in this file. See the CREDITS file in + the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#include +#include + +// The following is calling a very complex macro which will create +// "struct stock", which has the member variables: +// +// sql_char item; +// ... +// Null description; +// +// plus methods to help populate the class from a MySQL row. See the +// SSQLS sections in the user manual for further details. +sql_create_6(stock, + 1, 6, // The meaning of these values is covered in the user manual + mysqlpp::sql_char, item, + mysqlpp::sql_bigint, num, + mysqlpp::sql_double, weight, + mysqlpp::sql_double, price, + mysqlpp::sql_date, sdate, + mysqlpp::Null, description) + ADDED examples/store_if.cpp Index: examples/store_if.cpp ================================================================== --- /dev/null +++ examples/store_if.cpp @@ -0,0 +1,103 @@ +/*********************************************************************** + store_if.cpp - Demonstrates Query::store_if(), showing only the rows + from the sample table with prime quantities. This isn't intended + to be useful, only to show how you can do result set filtering that + outstrips the power of SQL. + + Copyright (c) 2005-2008 by Educational Technology Resources, Inc. + Others may also hold copyrights on code in this file. See the CREDITS + file in the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#include "cmdline.h" +#include "printdata.h" +#include "stock.h" + +#include + +#include + +#include + + +// Define a functor for testing primality. +struct is_prime +{ + bool operator()(const stock& s) + { + if ((s.num == 2) || (s.num == 3)) { + return true; // 2 and 3 are trivial cases + } + else if ((s.num < 2) || ((s.num % 2) == 0)) { + return false; // can't be prime if < 2 or even + } + else { + // The only possibility left is that it's divisible by an + // odd number that's less than or equal to its square root. + for (int i = 3; i <= sqrt(double(s.num)); i += 2) { + if ((s.num % i) == 0) { + return false; + } + } + return true; + } + } +}; + + +int +main(int argc, char *argv[]) +{ + // Get database access parameters from command line + const char* db = 0, *server = 0, *user = 0, *pass = ""; + if (!parse_command_line(argc, argv, &db, &server, &user, &pass)) { + return 1; + } + + try { + // Establish the connection to the database server. + mysqlpp::Connection con(db, server, user, pass); + + // Collect the stock items with prime quantities + std::vector results; + mysqlpp::Query query = con.query(); + query.store_if(results, stock(), is_prime()); + + // Show the results + print_stock_header(results.size()); + std::vector::const_iterator it; + for (it = results.begin(); it != results.end(); ++it) { + print_stock_row(it->item.c_str(), it->num, it->weight, + it->price, it->sdate); + } + } + catch (const mysqlpp::BadQuery& e) { + // Something went wrong with the SQL query. + std::cerr << "Query failed: " << e.what() << std::endl; + return 1; + } + catch (const mysqlpp::Exception& er) { + // Catch-all for any other MySQL++ exceptions + std::cerr << "Error: " << er.what() << std::endl; + return 1; + } + + return 0; +} ADDED examples/threads.h Index: examples/threads.h ================================================================== --- /dev/null +++ examples/threads.h @@ -0,0 +1,60 @@ +/*********************************************************************** + threads.h - Abstracts away the differences between POSIX threads and + Windows native threads. Used by the cpool example only; we could + keep this code inline there, but it's really just unimportant + details. + + Copyright (c) 2008 by Educational Technology Resources, Inc. + Others may also hold copyrights on code in this file. See the + CREDITS file in the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#if !defined(MYSQLPP_THREADS_H) +#define MYSQLPP_THREADS_H + +#include + +#if defined(MYSQLPP_PLATFORM_WINDOWS) +# define HAVE_THREADS +# define CALLBACK_SPECIFIER WINAPI + typedef DWORD thread_return_t; + typedef LPVOID thread_arg_t; + static int create_thread(LPTHREAD_START_ROUTINE worker, thread_arg_t arg) + { + return CreateThread(0, 0, worker, arg, 0, 0) ? 0 : GetLastError(); + } + static void sleep(int s) { Sleep(s * 1000); } +#else +# include "../config.h" +# if defined(HAVE_PTHREAD) +# define HAVE_THREADS +# define CALLBACK_SPECIFIER + typedef void* thread_return_t; + typedef void* thread_arg_t; + static int create_thread(thread_return_t(*worker)(thread_arg_t), + thread_arg_t arg) + { + pthread_t pt; + return pthread_create(&pt, 0, worker, arg); + } +# endif +#endif + +#endif // !defined(MYSQLPP_THREADS_H) ADDED examples/tquery1.cpp Index: examples/tquery1.cpp ================================================================== --- /dev/null +++ examples/tquery1.cpp @@ -0,0 +1,92 @@ +/*********************************************************************** + tquery1.cpp - Example similar to ssqls3.cpp, except that it uses + template queries instead of SSQLS. + + Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and + (c) 2004-2008 by Educational Technology Resources, Inc. Others may + also hold copyrights on code in this file. See the CREDITS file in + the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#include "cmdline.h" +#include "printdata.h" + +#include + +using namespace std; + +int +main(int argc, char *argv[]) +{ + // Get database access parameters from command line + const char* db = 0, *server = 0, *user = 0, *pass = ""; + if (!parse_command_line(argc, argv, &db, &server, &user, &pass)) { + return 1; + } + + try { + // Establish the connection to the database server. + mysqlpp::Connection con(db, server, user, pass); + + // Build a template query to retrieve a stock item given by + // item name. + mysqlpp::Query query = con.query( + "select * from stock where item = %0q"); + query.parse(); + + // Retrieve an item added by resetdb; it won't be there if + // tquery* or ssqls3 is run since resetdb. + mysqlpp::StoreQueryResult res1 = query.store("Nürnberger Brats"); + if (res1.empty()) { + throw mysqlpp::BadQuery("UTF-8 bratwurst item not found in " + "table, run resetdb"); + } + + // Replace the proper German name with a 7-bit ASCII + // approximation using a different template query. + query.reset(); // forget previous template query data + query << "update stock set item = %0q where item = %1q"; + query.parse(); + mysqlpp::SimpleResult res2 = query.execute("Nuerenberger Bratwurst", + res1[0][0].c_str()); + + // Print the new table contents. + print_stock_table(query); + } + catch (const mysqlpp::BadQuery& er) { + // Handle any query errors + cerr << "Query error: " << er.what() << endl; + return -1; + } + catch (const mysqlpp::BadConversion& er) { + // Handle bad conversions + cerr << "Conversion error: " << er.what() << endl << + "\tretrieved data size: " << er.retrieved << + ", actual size: " << er.actual_size << endl; + return -1; + } + catch (const mysqlpp::Exception& er) { + // Catch-all for any other MySQL++ exceptions + cerr << "Error: " << er.what() << endl; + return -1; + } + + return 0; +} ADDED examples/tquery2.cpp Index: examples/tquery2.cpp ================================================================== --- /dev/null +++ examples/tquery2.cpp @@ -0,0 +1,98 @@ +/*********************************************************************** + tquery2.cpp - Same as tquery1.cpp, except that it passes the template + query parameters in a SQLQueryParms object, instead of separately. + This is useful when the calling code doesn't know in advance how + many parameters there will be. This is most likely because the + templates are coming from somewhere else, or being generated. + + Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and + (c) 2004-2008 by Educational Technology Resources, Inc. Others may + also hold copyrights on code in this file. See the CREDITS file in + the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#include "cmdline.h" +#include "printdata.h" + +#include + +using namespace std; + +int +main(int argc, char *argv[]) +{ + // Get database access parameters from command line + const char* db = 0, *server = 0, *user = 0, *pass = ""; + if (!parse_command_line(argc, argv, &db, &server, &user, &pass)) { + return 1; + } + + try { + // Establish the connection to the database server. + mysqlpp::Connection con(db, server, user, pass); + + // Build a template query to retrieve a stock item given by + // item name. + mysqlpp::Query query = con.query( + "select * from stock where item = %0q"); + query.parse(); + + // Retrieve an item added by resetdb; it won't be there if + // tquery* or ssqls3 is run since resetdb. + mysqlpp::SQLQueryParms sqp; + sqp << "Nürnberger Brats"; + mysqlpp::StoreQueryResult res1 = query.store(sqp); + if (res1.empty()) { + throw mysqlpp::BadQuery("UTF-8 bratwurst item not found in " + "table, run resetdb"); + } + + // Replace the proper German name with a 7-bit ASCII + // approximation using a different template query. + query.reset(); // forget previous template query info + query << "update stock set item = %0q where item = %1q"; + query.parse(); + sqp.clear(); + sqp << "Nuerenberger Bratwurst" << res1[0][0].c_str(); + mysqlpp::SimpleResult res2 = query.execute(sqp); + + // Print the new table contents. + print_stock_table(query); + } + catch (const mysqlpp::BadQuery& er) { + // Handle any query errors + cerr << "Query error: " << er.what() << endl; + return -1; + } + catch (const mysqlpp::BadConversion& er) { + // Handle bad conversions + cerr << "Conversion error: " << er.what() << endl << + "\tretrieved data size: " << er.retrieved << + ", actual size: " << er.actual_size << endl; + return -1; + } + catch (const mysqlpp::Exception& er) { + // Catch-all for any other MySQL++ exceptions + cerr << "Error: " << er.what() << endl; + return -1; + } + + return 0; +} ADDED examples/tquery3.cpp Index: examples/tquery3.cpp ================================================================== --- /dev/null +++ examples/tquery3.cpp @@ -0,0 +1,82 @@ +/*********************************************************************** + tquery3.cpp - Similar to tquery1.cpp but uses unquoted parameters. + It's here more for code test coverage than because it shows + something interesting. We've historically had a problem with + tqueries with just one parameter; we cover the quoted case in + resetdb and the other tquery examples, so we get the unquoted + one here. + + Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and + (c) 2004-2008 by Educational Technology Resources, Inc. Others may + also hold copyrights on code in this file. See the CREDITS file in + the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#include "cmdline.h" +#include "printdata.h" + +#include + +using namespace std; + +int +main(int argc, char *argv[]) +{ + // Get database access parameters from command line + const char* db = 0, *server = 0, *user = 0, *pass = ""; + if (!parse_command_line(argc, argv, &db, &server, &user, &pass)) { + return 1; + } + + try { + // Establish the connection to the database server. + mysqlpp::Connection con(db, server, user, pass); + + // Build a template query to retrieve item names for stock + // entries with a quantity over some threshold. + mysqlpp::Query query = con.query( + "select item from stock where num > %0"); + query.parse(); + + // Get a list of things we have lots of in stock + if (mysqlpp::StoreQueryResult res = query.store(80)) { + cout << "Stuff we have a lot of in stock:" << endl; + for (size_t i = 0; i < res.num_rows(); ++i) { + cout << '\t' << res[i]["item"] << endl; + } + } + else { + cerr << "Failed to get item list: " << query.error() << endl; + return 1; + } + } + catch (const mysqlpp::BadQuery& er) { + // Handle any query errors + cerr << "Query error: " << er.what() << endl; + return 2; + } + catch (const mysqlpp::Exception& er) { + // Catch-all for any other MySQL++ exceptions + cerr << "Error: " << er.what() << endl; + return 2; + } + + return 0; +} ADDED examples/transaction.cpp Index: examples/transaction.cpp ================================================================== --- /dev/null +++ examples/transaction.cpp @@ -0,0 +1,107 @@ +/*********************************************************************** + transaction.cpp - Example showing how to use the transaction support in + MySQL++ v2.1 and up. + + Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and + (c) 2004-2008 by Educational Technology Resources, Inc. Others may + also hold copyrights on code in this file. See the CREDITS file in + the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#include "cmdline.h" +#include "printdata.h" +#include "stock.h" + +#include + +using namespace std; + +int +main(int argc, char *argv[]) +{ + // Get database access parameters from command line + const char* db = 0, *server = 0, *user = 0, *pass = ""; + if (!parse_command_line(argc, argv, &db, &server, &user, &pass)) { + return 1; + } + + try { + // Establish the connection to the database server. + mysqlpp::Connection con(db, server, user, pass); + + // Show initial state + mysqlpp::Query query = con.query(); + cout << "Initial state of stock table:" << endl; + print_stock_table(query); + + // Insert a few rows in a single transaction set + { + mysqlpp::Transaction trans(con); + + stock row("Sauerkraut", 42, 1.2, 0.75, + mysqlpp::sql_date("2006-03-06"), mysqlpp::null); + query.insert(row); + query.execute(); + + cout << "\nRow inserted, but not committed." << endl; + cout << "Verify this with another program (e.g. simple1), " + "then hit Enter." << endl; + getchar(); + + cout << "\nCommitting transaction gives us:" << endl; + trans.commit(); + print_stock_table(query); + } + + // Now let's test auto-rollback + { + mysqlpp::Transaction trans(con); + cout << "\nNow adding catsup to the database..." << endl; + + stock row("Catsup", 3, 3.9, 2.99, + mysqlpp::sql_date("2006-03-06"), mysqlpp::null); + query.insert(row); + query.execute(); + } + cout << "\nNo, yuck! We don't like catsup. Rolling it back:" << + endl; + print_stock_table(query); + + } + catch (const mysqlpp::BadQuery& er) { + // Handle any query errors + cerr << "Query error: " << er.what() << endl; + return -1; + } + catch (const mysqlpp::BadConversion& er) { + // Handle bad conversions + cerr << "Conversion error: " << er.what() << endl << + "\tretrieved data size: " << er.retrieved << + ", actual size: " << er.actual_size << endl; + return -1; + } + catch (const mysqlpp::Exception& er) { + // Catch-all for any other MySQL++ exceptions + cerr << "Error: " << er.what() << endl; + return -1; + } + + return 0; +} DELETED examples/util.cc Index: examples/util.cc ================================================================== --- examples/util.cc +++ /dev/null @@ -1,40 +0,0 @@ -#include -#include -#include "util.hh" - -void print_stock_table(Query& query) { - query.reset(); - query << "select * from stock"; - // You can write to the query object like you would any other ostrem - - Result res = query.store(); - // Query::store() executes the query and returns the results - - cout << "Query: " << query.preview() << endl; - // Query::preview() simply returns a string with the current query - // string in it. - - cout << "Records Found: " << res.size() << endl << endl; - - Row row; - cout.setf(ios::left); - cout << setw(17) << "Item" - << setw(4) << "Num" - << setw(7) << "Weight" - << setw(7) << "Price" - << "Date" << endl - << endl; - - Result::iterator i; - // The Result class has a read-only Random Access Iterator - for (i = res.begin(); i != res.end(); i++) { - row = *i; - cout << setw(17) << row[0] - << setw(4) << row[1] - << setw(7) << row["weight"] - // you can use either the index number or column name when - // retrieving the colume data as demonstrated above. - << setw(7) << row[3] - << row[4] << endl; - } -} DELETED examples/util.hh Index: examples/util.hh ================================================================== --- examples/util.hh +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _util_hh_ -#define _util_hh_ - -#include - -void print_stock_table(Query& query); - -#endif ADDED examples/vstudio/mfc/mfc.cpp Index: examples/vstudio/mfc/mfc.cpp ================================================================== --- /dev/null +++ examples/vstudio/mfc/mfc.cpp @@ -0,0 +1,54 @@ +/*********************************************************************** + mfc.cpp - Skeletal main module of the MySQL++ MFC example program. + Nothing interesting to see here. Move along to mfc_dlg.cpp, folks. + + Copyright (c) 2007 by Educational Technology Resources, Inc. Others + may also hold copyrights on code in this file. See the CREDITS file in + the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#include "stdafx.h" +#include "mfc.h" +#include "mfc_dlg.h" + +CApp gApplication; + +BOOL CApp::InitInstance() +{ + // Set up Windows commomn controls + INITCOMMONCONTROLSEX InitCtrls; + InitCtrls.dwSize = sizeof(InitCtrls); + InitCtrls.dwICC = ICC_WIN95_CLASSES; + InitCommonControlsEx(&InitCtrls); + + CWinApp::InitInstance(); + + // Initialize Winsock for MySQL communication, start GUI + if (AfxSocketInit()) { + CExampleDlg dlg; + m_pMainWnd = &dlg; + dlg.DoModal(); + } + else { + AfxMessageBox(IDP_SOCKETS_INIT_FAILED); + } + + return FALSE; +} ADDED examples/vstudio/mfc/mfc.h Index: examples/vstudio/mfc/mfc.h ================================================================== --- /dev/null +++ examples/vstudio/mfc/mfc.h @@ -0,0 +1,34 @@ +/*********************************************************************** + mfc.cpp - Declares the MFC application object. Nothing interesting to + see here. Move along to mfc_dlg.cpp, folks. + + Copyright (c) 2007 by Educational Technology Resources, Inc. Others + may also hold copyrights on code in this file. See the CREDITS file in + the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#pragma once + +class CApp : public CWinApp +{ +public: + CApp() { } + virtual BOOL InitInstance(); +}; ADDED examples/vstudio/mfc/mfc.rc Index: examples/vstudio/mfc/mfc.rc ================================================================== --- /dev/null +++ examples/vstudio/mfc/mfc.rc @@ -0,0 +1,135 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "#define _AFX_NO_SPLITTER_RESOURCES\r\n" + "#define _AFX_NO_OLE_RESOURCES\r\n" + "#define _AFX_NO_TRACKER_RESOURCES\r\n" + "#define _AFX_NO_PROPERTY_RESOURCES\r\n" + "\r\n" + "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" + "LANGUAGE 9, 1\r\n" + "#pragma code_page(1252)\r\n" + "#include ""afxres.rc"" // Standard components\r\n" + "#endif\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_MFC_DIALOG DIALOGEX 0, 0, 210, 105 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION +EXSTYLE WS_EX_APPWINDOW +CAPTION "MySQL++ MFC Example" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + EDITTEXT IDC_SERVER_EDIT,51,7,94,14,ES_AUTOHSCROLL + EDITTEXT IDC_USER_EDIT,51,24,94,14,ES_AUTOHSCROLL + EDITTEXT IDC_PASSWORD_EDIT,51,41,94,14,ES_PASSWORD | ES_AUTOHSCROLL + DEFPUSHBUTTON "Connect!",IDC_CONNECT_BUTTON,153,7,50,14 + PUSHBUTTON "Close",IDCANCEL,153,25,50,16 + LISTBOX IDC_RESULTS_LIST,51,58,94,40,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_DISABLED | WS_VSCROLL + RTEXT "Server:",IDC_STATIC,7,7,40,8 + RTEXT "User name:",IDC_STATIC,7,24,40,8 + RTEXT "Password:",IDC_STATIC,7,41,40,8 + RTEXT "Results:",IDC_STATIC,7,58,40,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_MFC_DIALOG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 203 + TOPMARGIN, 7 + BOTTOMMARGIN, 98 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDP_SOCKETS_INIT_FAILED "Windows sockets initialization failed." +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#define _AFX_NO_SPLITTER_RESOURCES +#define _AFX_NO_OLE_RESOURCES +#define _AFX_NO_TRACKER_RESOURCES +#define _AFX_NO_PROPERTY_RESOURCES + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE 9, 1 +#pragma code_page(1252) +#include "afxres.rc" // Standard components +#endif + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + ADDED examples/vstudio/mfc/mfc_dlg.cpp Index: examples/vstudio/mfc/mfc_dlg.cpp ================================================================== --- /dev/null +++ examples/vstudio/mfc/mfc_dlg.cpp @@ -0,0 +1,275 @@ +/*********************************************************************** + mfc_dlg.cpp - Defines the dialog box behavior for the MySQL++ MFC + example. + + Copyright (c) 2007 by Educational Technology Resources, Inc. Others + may also hold copyrights on code in this file. See the CREDITS file in + the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#include "stdafx.h" +#include "mfc_dlg.h" + +#include + +BEGIN_MESSAGE_MAP(CExampleDlg, CDialog) + ON_BN_CLICKED(IDC_CONNECT_BUTTON, &CExampleDlg::OnBnClickedConnectButton) +END_MESSAGE_MAP() + + +//// ctor ////////////////////////////////////////////////////////////// + +CExampleDlg::CExampleDlg(CWnd* pParent) : +CDialog(IDD_MFC_DIALOG, pParent) +{ + LoadDefaults(); +} + + +//// AddMessage //////////////////////////////////////////////////////// +// Inserts the given string at the end of the list box we're using for +// output to the user. + +void +CExampleDlg::AddMessage(LPCTSTR pcMessage) +{ + ResultsList.InsertString(-1, pcMessage); +} + + +//// DoDataExchange //////////////////////////////////////////////////// +// Transfer data from the controls into our member variables + +void +CExampleDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + DDX_Text(pDX, IDC_SERVER_EDIT, sServerAddress); + DDX_Text(pDX, IDC_USER_EDIT, sUserName); + DDX_Text(pDX, IDC_PASSWORD_EDIT, sPassword); + DDX_Control(pDX, IDC_RESULTS_LIST, ResultsList); +} + + +//// LoadDefaults ////////////////////////////////////////////////////// +// Load default input values from registry, if they exist. + +void +CExampleDlg::LoadDefaults() +{ + HKEY key = OpenSettingsRegistryKey(); + if (key) { + TCHAR acSetting[100]; + if (LoadSetting(key, _T("user"), acSetting, sizeof(acSetting))) { + sUserName = acSetting; + } + if (LoadSetting(key, _T("server"), acSetting, sizeof(acSetting))) { + sServerAddress = acSetting; + } + RegCloseKey(key); + } + + if (sUserName.IsEmpty()) { + TCHAR acUserName[100]; + DWORD nBufferSize = sizeof(acUserName); + if (GetUserName(acUserName, &nBufferSize)) { + sUserName = acUserName; + } + } + if (sServerAddress.IsEmpty()) { + sServerAddress = _T("localhost"); + } +} + + +//// LoadSetting /////////////////////////////////////////////////////// +// Loads up the value of the named registry value underneath the given +// key and returns it in pcValue. + +bool +CExampleDlg::LoadSetting(HKEY key, LPCTSTR pcName, LPTSTR pcValue, + DWORD nValueSize) +{ + return RegQueryValueEx(key, pcName, 0, 0, LPBYTE(pcValue), + &nValueSize) == ERROR_SUCCESS; +} + + +//// OnBnClickedConnectButton ////////////////////////////////////////// +// This is essentially the same thing as examples/simple1.cpp + +void +CExampleDlg::OnBnClickedConnectButton() +{ + WCHAR awcTempBuf[100]; + const int kTempBufSize = sizeof(awcTempBuf) / sizeof(awcTempBuf[0]); + + // Pull user input into our member variables + UpdateData(TRUE); + + // Clear out the results list, in case this isn't the first time + // we've come in here. + ResultsList.ResetContent(); + + // Translate the Unicode text we get from the UI into the UTF-8 form + // that MySQL wants. + const int kInputBufSize = 100; + char acServerAddress[kInputBufSize]; + char acUserName[kInputBufSize]; + char acPassword[kInputBufSize]; + ToUTF8(acServerAddress, kInputBufSize, sServerAddress); + ToUTF8(acUserName, kInputBufSize, sUserName); + ToUTF8(acPassword, kInputBufSize, sPassword); + + // Connect to the sample database. + mysqlpp::Connection con(false); + if (!con.connect("mysql_cpp_data", acServerAddress, acUserName, + acPassword)) { + AddMessage(_T("Failed to connect to server:")); + if (ToUCS2(awcTempBuf, kTempBufSize, con.error())) { + AddMessage(awcTempBuf); + } + return; + } + + // Retrieve a subset of the sample stock table set up by resetdb + mysqlpp::Query query = con.query(); + query << "select item from stock"; + mysqlpp::StoreQueryResult res = query.store(); + + if (res) { + // Display the result set + mysqlpp::Row row; + for (mysqlpp::Row::size_type i = 0; row = res.at(i); ++i) { + if (ToUCS2(awcTempBuf, kTempBufSize, row.at(0))) { + AddMessage(awcTempBuf); + } + } + + // Retreive was successful, so save user inputs now + SaveInputs(); + } + else { + // Retreive failed + AddMessage(_T("Failed to get item list:")); + if (ToUCS2(awcTempBuf, kTempBufSize, query.error())) { + AddMessage(awcTempBuf); + } + } +} + + +//// OpenSettingsRegistryKey /////////////////////////////////////////// + +HKEY +CExampleDlg::OpenSettingsRegistryKey() +{ + HKEY key1, key2; + if ((RegOpenKey(HKEY_CURRENT_USER, _T("Software"), &key1) == + ERROR_SUCCESS) && (RegCreateKey(key1, + _T("MySQL++ Examples"), &key2) == ERROR_SUCCESS)) { + RegCloseKey(key1); + return key2; + } + else { + return 0; + } +} + + +//// SaveInputs //////////////////////////////////////////////////////// +// Saves the input fields' values to the registry, except for the +// password field. + +bool +CExampleDlg::SaveInputs() +{ + HKEY key = OpenSettingsRegistryKey(); + if (key) { + SaveSetting(key, _T("user"), sUserName); + SaveSetting(key, _T("server"), sServerAddress); + RegCloseKey(key); + return true; + } + else { + return false; + } +} + + +//// SaveSetting /////////////////////////////////////////////////////// +// Saves the given value as a named entry under the given registry key. + +bool +CExampleDlg::SaveSetting(HKEY key, LPCTSTR pcName, LPCTSTR pcValue) +{ + DWORD nBytes = DWORD(sizeof(TCHAR) * (_tcslen(pcValue) + 1)); + return RegSetValueEx(key, pcName, 0, REG_SZ, LPBYTE(pcValue), + nBytes) == ERROR_SUCCESS; +} + + +//// ToUCS2 //////////////////////////////////////////////////////////// +// Convert a C string in UTF-8 format to UCS-2 format. + +bool +CExampleDlg::ToUCS2(LPTSTR pcOut, int nOutLen, const char* kpcIn) +{ + if (strlen(kpcIn) > 0) { + // Do the conversion normally + return MultiByteToWideChar(CP_UTF8, 0, kpcIn, -1, pcOut, + nOutLen) > 0; + } + else if (nOutLen > 1) { + // Can't distinguish no bytes copied from an error, so handle + // an empty input string as a special case. + _tccpy(pcOut, _T("")); + return true; + } + else { + // Not enough room to do anything! + return false; + } +} + + +//// ToUTF8 //////////////////////////////////////////////////////////// +// Convert a UCS-2 multibyte string to the UTF-8 format required by +// MySQL, and thus MySQL++. + +bool +CExampleDlg::ToUTF8(char* pcOut, int nOutLen, LPCWSTR kpcIn) +{ + if (_tcslen(kpcIn) > 0) { + // Do the conversion normally + return WideCharToMultiByte(CP_UTF8, 0, kpcIn, -1, pcOut, + nOutLen, 0, 0) > 0; + } + else if (nOutLen > 0) { + // Can't distinguish no bytes copied from an error, so handle + // an empty input string as a special case. + *pcOut = '\0'; + return true; + } + else { + // Not enough room to do anything! + return false; + } +} ADDED examples/vstudio/mfc/mfc_dlg.h Index: examples/vstudio/mfc/mfc_dlg.h ================================================================== --- /dev/null +++ examples/vstudio/mfc/mfc_dlg.h @@ -0,0 +1,58 @@ +/*********************************************************************** + mfc_dlg.h - Declares the dialog class for the MySQL++ MFC example. + + Copyright (c) 2007 by Educational Technology Resources, Inc. Others + may also hold copyrights on code in this file. See the CREDITS file in + the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#pragma once +#include "afxwin.h" +#include "resource.h" + +class CExampleDlg : public CDialog +{ +public: + //// Public interface + CExampleDlg(CWnd* pParent = 0); + + //// Public data + CString sServerAddress; + CString sUserName; + CString sPassword; + CListBox ResultsList; + +protected: + //// Internal support functions + void AddMessage(LPCTSTR pcMessage); + void DoDataExchange(CDataExchange* pDX); + void LoadDefaults(); + bool LoadSetting(HKEY key, LPCTSTR pcName, LPTSTR pcValue, + DWORD nValueSize); + HKEY OpenSettingsRegistryKey(); + bool SaveInputs(); + bool SaveSetting(HKEY key, LPCTSTR pcName, LPCTSTR pcValue); + bool ToUCS2(LPTSTR pcOut, int nOutLen, const char* kpcIn); + bool ToUTF8(char* pcOut, int nOutLen, LPCWSTR kpcIn); + + //// Message map + afx_msg void OnBnClickedConnectButton(); + DECLARE_MESSAGE_MAP() +}; ADDED examples/vstudio/mfc/resource.h Index: examples/vstudio/mfc/resource.h ================================================================== --- /dev/null +++ examples/vstudio/mfc/resource.h @@ -0,0 +1,22 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by mfc.rc +// +#define IDD_MFC_DIALOG 102 +#define IDP_SOCKETS_INIT_FAILED 103 +#define IDC_SERVER_EDIT 1000 +#define IDC_PASSWORD_EDIT 1001 +#define IDC_USER_EDIT 1002 +#define IDC_RESULTS_LIST 1003 +#define IDC_CONNECT_BUTTON 1004 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 129 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1005 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif ADDED examples/vstudio/mfc/stdafx.h Index: examples/vstudio/mfc/stdafx.h ================================================================== --- /dev/null +++ examples/vstudio/mfc/stdafx.h @@ -0,0 +1,54 @@ +/*********************************************************************** + stdafx.h - Common include file to bring in MFC support and other + basics. + + Copyright (c) 2007 by Educational Technology Resources, Inc. Others + may also hold copyrights on code in this file. See the CREDITS file in + the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#pragma once + +#ifndef VC_EXTRALEAN +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers +#endif + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef WINVER // Allow use of features specific to Windows XP or later. +#define WINVER 0x0501 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. +#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later. +#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. +#endif + +// turns off MFC's hiding of some common and often safely ignored warning messages +#define _AFX_ALL_WARNINGS + +#include // MFC core and standard components +#include // MFC extensions +#include // MFC support for Windows Common Controls +#include // MFC socket extensions + ADDED examples/vstudio/wforms/AssemblyInfo.cpp Index: examples/vstudio/wforms/AssemblyInfo.cpp ================================================================== --- /dev/null +++ examples/vstudio/wforms/AssemblyInfo.cpp @@ -0,0 +1,18 @@ +using namespace System; +using namespace System::Reflection; +using namespace System::Runtime::CompilerServices; +using namespace System::Runtime::InteropServices; +using namespace System::Security::Permissions; + +[assembly:AssemblyTitleAttribute("wforms")]; +[assembly:AssemblyDescriptionAttribute("")]; +[assembly:AssemblyConfigurationAttribute("")]; +[assembly:AssemblyCompanyAttribute("the MySQL++ project")]; +[assembly:AssemblyProductAttribute("MySQL++ Windows Forms Example")]; +[assembly:AssemblyCopyrightAttribute("Copyright © 2007 by ETR, Inc.")]; +[assembly:AssemblyTrademarkAttribute("")]; +[assembly:AssemblyCultureAttribute("")]; +[assembly:AssemblyVersionAttribute("1.0.*")]; +[assembly:ComVisible(false)]; +[assembly:CLSCompliantAttribute(true)]; +[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)]; ADDED examples/vstudio/wforms/MainForm.h Index: examples/vstudio/wforms/MainForm.h ================================================================== --- /dev/null +++ examples/vstudio/wforms/MainForm.h @@ -0,0 +1,346 @@ +/*********************************************************************** + MainForm.cpp - Defines the dialog box behavior for the MySQL++ C++/CLI + Windows Forms example. + + Copyright (c) 2007 by Educational Technology Resources, Inc. Others + may also hold copyrights on code in this file. See the CREDITS file in + the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#pragma once + +#include + +namespace wforms { + + using namespace Microsoft::Win32; + using namespace System; + using namespace System::ComponentModel; + using namespace System::Collections; + using namespace System::Windows::Forms; + using namespace System::Data; + using namespace System::Drawing; + + public ref class MainForm : public System::Windows::Forms::Form + { + public: + MainForm() + { + InitializeComponent(); + LoadDefaults(); + } + + protected: + ~MainForm() + { + if (components) { + delete components; + } + } + + private: + // Insert a text string into the output list control + Void AddMessage(String^ msg) + { + resultsList_->Items->Add(msg); + } + + // Handle Close button click by shutting down application + Void CloseButton_Click(Object^ sender, EventArgs^ e) + { + Application::Exit(); + } + + // Handle Connect button click. The body of this function is + // essentially the same as the simple2 command line example, with + // some GUI overhead. + Void ConnectButton_Click(Object^ sender, EventArgs^ e) + { + // Clear out the results list, in case this isn't the first time + // we've come in here. + resultsList_->Items->Clear(); + + // Translate the Unicode text we get from the UI into the UTF-8 + // form that MySQL wants. + const int kInputBufSize = 100; + char acServerAddress[kInputBufSize]; + char acUserName[kInputBufSize]; + char acPassword[kInputBufSize]; + ToUTF8(acServerAddress, kInputBufSize, serverAddress_->Text); + ToUTF8(acUserName, kInputBufSize, userName_->Text); + ToUTF8(acPassword, kInputBufSize, password_->Text); + + // Connect to the sample database. + mysqlpp::Connection con(false); + if (!con.connect("mysql_cpp_data", acServerAddress, acUserName, + acPassword)) { + AddMessage("Failed to connect to server:"); + AddMessage(gcnew String(con.error())); + return; + } + + // Retrieve a subset of the sample stock table set up by resetdb + mysqlpp::Query query = con.query(); + query << "select item from stock"; + mysqlpp::StoreQueryResult res = query.store(); + + if (res) { + // Display the result set + mysqlpp::Row row; + for (mysqlpp::Row::size_type i = 0; row = res.at(i); ++i) { + AddMessage(ToUCS2(row.at(0))); + } + + // Retreive was successful, so save user inputs now + SaveInputs(); + } + else { + // Retreive failed + AddMessage("Failed to get item list:"); + AddMessage(ToUCS2(query.error())); + } + } + + // Load the default input field values, if there are any + Void LoadDefaults() + { + RegistryKey^ settings = OpenSettingsRegistryKey(); + if (settings) { + userName_->Text = LoadSetting(settings, L"user"); + serverAddress_->Text = LoadSetting(settings, L"server"); + } + + if (String::IsNullOrEmpty(userName_->Text)) { + userName_->Text = Environment::UserName; + } + if (String::IsNullOrEmpty(serverAddress_->Text)) { + serverAddress_->Text = L"localhost"; + } + } + + // Returns a setting from underneath the given registry key. + // Assumes that it's a string value under the MySQL++ examples' + // settings area. + String^ LoadSetting(RegistryKey^ key, String^ name) + { + return (String^)key->GetValue(name); + } + + // Returns a reference to the MySQL++ examples' settings area in the + // registry. + RegistryKey^ OpenSettingsRegistryKey() + { + RegistryKey^ key = Registry::CurrentUser->OpenSubKey(L"Software", + true); + return key ? key->CreateSubKey(L"MySQL++ Examples") : nullptr; + } + + // Saves the input fields' values to the registry, except for the + // password field. + Void SaveInputs() + { + RegistryKey^ settings = OpenSettingsRegistryKey(); + if (settings) { + SaveSetting(settings, "user", userName_->Text); + SaveSetting(settings, "server", serverAddress_->Text); + } + } + + // Saves the given value as a named entry under the given registry + // key. + Void SaveSetting(RegistryKey^ key, String^ name, String^ value) + { + key->SetValue(name, value); + } + + // Takes a string in the .NET platform's native Unicode format and + // copies it to the given C string buffer in UTF-8 encoding. + Void ToUTF8(char* pcOut, int nOutLen, String^ sIn) + { + array^ bytes = System::Text::Encoding::UTF8->GetBytes(sIn); + nOutLen = Math::Min(nOutLen - 1, bytes->Length); + System::Runtime::InteropServices::Marshal::Copy(bytes, 0, + IntPtr(pcOut), nOutLen); + pcOut[nOutLen] = '\0'; + } + + // Takes the given C string encoded in UTF-8 and converts it to a + // Unicode string in the .NET platform's native Unicode encoding. + String^ ToUCS2(const char* utf8) + { + return gcnew String(utf8, 0, strlen(utf8), + System::Text::Encoding::UTF8); + } + + private: System::Windows::Forms::TextBox^ serverAddress_; + private: System::Windows::Forms::TextBox^ password_; + private: System::Windows::Forms::TextBox^ userName_; + private: System::Windows::Forms::ListBox^ resultsList_; + private: System::Windows::Forms::Button^ connectButton_; + private: System::Windows::Forms::Button^ closeButton_; + private: System::ComponentModel::Container^ components; + +#pragma region Windows Form Designer generated code + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + void InitializeComponent(void) + { + System::Windows::Forms::Label^ label1; + System::Windows::Forms::Label^ label2; + System::Windows::Forms::Label^ label3; + System::Windows::Forms::Label^ label4; + this->serverAddress_ = (gcnew System::Windows::Forms::TextBox()); + this->password_ = (gcnew System::Windows::Forms::TextBox()); + this->userName_ = (gcnew System::Windows::Forms::TextBox()); + this->resultsList_ = (gcnew System::Windows::Forms::ListBox()); + this->connectButton_ = (gcnew System::Windows::Forms::Button()); + this->closeButton_ = (gcnew System::Windows::Forms::Button()); + label1 = (gcnew System::Windows::Forms::Label()); + label2 = (gcnew System::Windows::Forms::Label()); + label3 = (gcnew System::Windows::Forms::Label()); + label4 = (gcnew System::Windows::Forms::Label()); + this->SuspendLayout(); + // + // label1 + // + label1->AutoSize = true; + label1->Location = System::Drawing::Point(29, 13); + label1->Name = L"label1"; + label1->Size = System::Drawing::Size(41, 13); + label1->TabIndex = 6; + label1->Text = L"Server:"; + label1->TextAlign = System::Drawing::ContentAlignment::TopRight; + // + // label2 + // + label2->AutoSize = true; + label2->Location = System::Drawing::Point(9, 39); + label2->Name = L"label2"; + label2->Size = System::Drawing::Size(61, 13); + label2->TabIndex = 7; + label2->Text = L"User name:"; + label2->TextAlign = System::Drawing::ContentAlignment::TopRight; + // + // label3 + // + label3->AutoSize = true; + label3->Location = System::Drawing::Point(14, 65); + label3->Name = L"label3"; + label3->Size = System::Drawing::Size(56, 13); + label3->TabIndex = 8; + label3->Text = L"Password:"; + label3->TextAlign = System::Drawing::ContentAlignment::TopRight; + // + // label4 + // + label4->AutoSize = true; + label4->Location = System::Drawing::Point(25, 92); + label4->Name = L"label4"; + label4->Size = System::Drawing::Size(45, 13); + label4->TabIndex = 9; + label4->Text = L"Results:"; + label4->TextAlign = System::Drawing::ContentAlignment::TopRight; + // + // serverAddress_ + // + this->serverAddress_->Location = System::Drawing::Point(70, 9); + this->serverAddress_->Name = L"serverAddress_"; + this->serverAddress_->Size = System::Drawing::Size(139, 20); + this->serverAddress_->TabIndex = 0; + // + // password_ + // + this->password_->Location = System::Drawing::Point(70, 61); + this->password_->Name = L"password_"; + this->password_->Size = System::Drawing::Size(139, 20); + this->password_->TabIndex = 2; + this->password_->UseSystemPasswordChar = true; + // + // userName_ + // + this->userName_->Location = System::Drawing::Point(70, 35); + this->userName_->Name = L"userName_"; + this->userName_->Size = System::Drawing::Size(139, 20); + this->userName_->TabIndex = 1; + // + // resultsList_ + // + this->resultsList_->Enabled = false; + this->resultsList_->FormattingEnabled = true; + this->resultsList_->Location = System::Drawing::Point(70, 88); + this->resultsList_->Name = L"resultsList_"; + this->resultsList_->Size = System::Drawing::Size(228, 95); + this->resultsList_->TabIndex = 3; + this->resultsList_->TabStop = false; + // + // connectButton_ + // + this->connectButton_->Location = System::Drawing::Point(224, 9); + this->connectButton_->Name = L"connectButton_"; + this->connectButton_->Size = System::Drawing::Size(75, 23); + this->connectButton_->TabIndex = 3; + this->connectButton_->Text = L"Connect!"; + this->connectButton_->UseVisualStyleBackColor = true; + this->connectButton_->Click += gcnew System::EventHandler(this, &MainForm::ConnectButton_Click); + // + // closeButton_ + // + this->closeButton_->DialogResult = System::Windows::Forms::DialogResult::Cancel; + this->closeButton_->Location = System::Drawing::Point(224, 38); + this->closeButton_->Name = L"closeButton_"; + this->closeButton_->Size = System::Drawing::Size(75, 23); + this->closeButton_->TabIndex = 4; + this->closeButton_->Text = L"Close"; + this->closeButton_->UseVisualStyleBackColor = true; + this->closeButton_->Click += gcnew System::EventHandler(this, &MainForm::CloseButton_Click); + // + // MainForm + // + this->AcceptButton = this->connectButton_; + this->AutoScaleDimensions = System::Drawing::SizeF(6, 13); + this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; + this->CancelButton = this->closeButton_; + this->ClientSize = System::Drawing::Size(310, 192); + this->ControlBox = false; + this->Controls->Add(label4); + this->Controls->Add(label3); + this->Controls->Add(label2); + this->Controls->Add(label1); + this->Controls->Add(this->closeButton_); + this->Controls->Add(this->connectButton_); + this->Controls->Add(this->resultsList_); + this->Controls->Add(this->userName_); + this->Controls->Add(this->password_); + this->Controls->Add(this->serverAddress_); + this->FormBorderStyle = System::Windows::Forms::FormBorderStyle::FixedDialog; + this->MaximizeBox = false; + this->MinimizeBox = false; + this->Name = L"MainForm"; + this->ShowIcon = false; + this->Text = L"MySQL++ Windows Forms Examples"; + this->ResumeLayout(false); + this->PerformLayout(); + + } +#pragma endregion +}; +} ADDED examples/vstudio/wforms/MainForm.resX Index: examples/vstudio/wforms/MainForm.resX ================================================================== --- /dev/null +++ examples/vstudio/wforms/MainForm.resX @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + False + + + False + + + False + + + False + + ADDED examples/vstudio/wforms/resource.h Index: examples/vstudio/wforms/resource.h ================================================================== --- /dev/null +++ examples/vstudio/wforms/resource.h @@ -0,0 +1,3 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by app.rc ADDED examples/vstudio/wforms/wforms.cpp Index: examples/vstudio/wforms/wforms.cpp ================================================================== --- /dev/null +++ examples/vstudio/wforms/wforms.cpp @@ -0,0 +1,17 @@ +// wforms.cpp : main project file. + +#include "MainForm.h" + +using namespace wforms; + +[STAThreadAttribute] +int main(array ^args) +{ + // Enabling Windows XP visual effects before any controls are created + Application::EnableVisualStyles(); + Application::SetCompatibleTextRenderingDefault(false); + + // Create the main window and run it + Application::Run(gcnew MainForm()); + return 0; +} ADDED exrun Index: exrun ================================================================== --- /dev/null +++ exrun @@ -0,0 +1,61 @@ +#!/bin/sh +if [ -z "$1" ] +then + echo "usage: $0 [TOOL] [args...]" + echo + echo " Runs the given example, using the library in the current directory" + echo " instead of using the system library search mechanism. Accepts an " + echo " arbitrary number of arguments." + echo + echo " TOOL can be 'valgrind', 'gdb', or 'ldd', which causes exrun to" + echo " run the example program under the given tool." + echo + exit 1 +fi + +TOOL= +PROG=$1 +if [ "$PROG" = 'valgrind' ] +then + TOOL='valgrind' + shift + PROG=$1 +elif [ "$PROG" = 'gdb' ] +then + TOOL='gdb --args' + shift + PROG=$1 +elif [ "$PROG" = 'ldd' ] +then + TOOL='ldd' + shift + PROG=$1 +fi + +shift +if [ -e "$PROG" ] +then + if [ `uname -s` = 'Darwin' ] + then + DYLD_LIBRARY_PATH=. $TOOL ./$PROG $* + elif [ `uname -o` = 'Cygwin' ] + then + # Cygwin build case; see below for bash-as-DOS-shell case + PATH=. $TOOL ./$PROG $* + elif [ -e /usr/bin/ldd ] + then + LD_LIBRARY_PATH=. $TOOL ./$PROG $* + else + echo "ERROR: I don't grok this system's dynamic linkage system." + fi +elif [ `uname -o` = 'Cygwin' ] +then + # VC++ build, but using Cygwin's bash as shell to run programs + cmd.exe /c exrun.bat $PROG $* +else + echo "usage: $0 [TOOL] [args...]" + echo + echo " Run $0 without arguments for more detailed usage info." + echo + exit 1 +fi ADDED exrun.bat Index: exrun.bat ================================================================== --- /dev/null +++ exrun.bat @@ -0,0 +1,9 @@ +@echo off +set PROG=%1 +if not exist %PROG% set PROG=%1.exe +if not exist %PROG% set PROG=Debug\%1 +if not exist %PROG% set PROG=Debug\%1.exe +shift + +set PATH=Debug;%PATH% +%PROG% %1 %2 %3 %4 %5 %6 %7 %8 %9 ADDED install.bat Index: install.bat ================================================================== --- /dev/null +++ install.bat @@ -0,0 +1,38 @@ +@echo off +if "%1" == "" goto error + +set BASE_DIR=c:\mysql++ +set INST_INC_DIR=%BASE_DIR%\include +set INST_LIB_DIR=%BASE_DIR%\%1 + +if not exist %BASE_DIR% mkdir %BASE_DIR% +if not exist %INST_INC_DIR% mkdir %INST_INC_DIR% +if not exist %INST_LIB_DIR% mkdir %INST_LIB_DIR% +if not exist %INST_LIB_DIR%\debug mkdir %INST_LIB_DIR%\debug +if not exist %INST_LIB_DIR%\release mkdir %INST_LIB_DIR%\release + +copy lib\*.h "%INST_INC_DIR%" > NUL + +if exist *.a goto install_mingw +copy debug\*.dll "%INST_LIB_DIR%\debug" > NUL +copy debug\*.lib "%INST_LIB_DIR%\debug" > NUL +copy release\*.dll "%INST_LIB_DIR%\release" > NUL +copy release\*.lib "%INST_LIB_DIR%\release" > NUL +goto install_done +:install_mingw +copy *.a "%INST_LIB_DIR%\debug" > NUL +echo WARNING: I assume you built a debug version of the library, as that +echo is what you get with MinGW unless you make a special effort. You +echo must do a manual install if you make a release version. + +:install_done +echo MySQL++ (%1 version) installed successfully! +goto end + +:error +echo usage: install [subdir] +echo. +echo Installs MySQL++ into the given subdirectory of %BASE_DIR% + +:end + ADDED lib/Doxyfile.in Index: lib/Doxyfile.in ================================================================== --- /dev/null +++ lib/Doxyfile.in @@ -0,0 +1,1055 @@ +# Doxyfile 1.5.2-1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = MySQL++ + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = @PACKAGE_VERSION@ + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = ../doc + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian, +# Italian, Japanese, Japanese-en (Japanese with English messages), Korean, +# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian, +# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explicit @brief command for a brief description. + +JAVADOC_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = querydef.h ssqls.h + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html/refman + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = ../doc/html/refman/_header.html + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = YES + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = letter + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = DOXYGEN_IGNORE + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = YES + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO ADDED lib/autoflag.h Index: lib/autoflag.h ================================================================== --- /dev/null +++ lib/autoflag.h @@ -0,0 +1,57 @@ +/// \file autoflag.h +/// \brief Defines a template for setting a flag within a given variable +/// scope, and resetting it when exiting that scope. + +/*********************************************************************** + Copyright (c) 2007 by Educational Technology Resources, Inc. Others + may also hold copyrights on code in this file. See the CREDITS file in + the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#if !defined(MYSQLPP_AUTOFLAG_H) +#define MYSQLPP_AUTOFLAG_H + +/// \brief A template for setting a flag on a variable as long as the +/// object that set it is in scope. Flag resets when object goes +/// out of scope. Works on anything that looks like bool. + +template +class AutoFlag +{ +public: + /// \brief Constructor: sets ref to true. + AutoFlag(T& ref) : + referent_(ref) + { + referent_ = true; + } + + /// \brief Destructor: sets referent passed to ctor to false. + ~AutoFlag() + { + referent_ = false; + } + +private: + T& referent_; +}; + +#endif // !defined(MYSQLPP_AUTOFLAG_H) + ADDED lib/beemutex.cpp Index: lib/beemutex.cpp ================================================================== --- /dev/null +++ lib/beemutex.cpp @@ -0,0 +1,182 @@ +/*********************************************************************** + beemutex.cpp - Implements the BeecryptMutex class. The name comes + from the fact that we lifted this essentially intact from the + Beecrypt library, which is also LGPL. See beecrypt.h for the list + of changes we made on integrating it into MySQL++. + + Copyright (c) 2004 Beeyond Software Holding BV and (c) 2007 by + Educational Technology Resources, Inc. Others may also hold + copyrights on code in this file. See the CREDITS file in the top + directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#define MYSQLPP_NOT_HEADER +#include "beemutex.h" + +#include "common.h" + +#include +#include + + +namespace mysqlpp { + +#define ACTUALLY_DOES_SOMETHING +#if defined(HAVE_SYNCH_H) + typedef mutex_t bc_mutex_t; +#elif defined(HAVE_PTHREAD) + typedef pthread_mutex_t bc_mutex_t; +#elif defined(MYSQLPP_PLATFORM_WINDOWS) + typedef HANDLE bc_mutex_t; +#else +// No supported mutex type found, so class becomes a no-op. +# undef ACTUALLY_DOES_SOMETHING +#endif + +#if defined(ACTUALLY_DOES_SOMETHING) + static bc_mutex_t* impl_ptr(void* p) + { return static_cast(p); } +# if defined(MYSQLPP_PLATFORM_WINDOWS) + static bc_mutex_t impl_val(void* p) + { return *static_cast(p); } +# endif +#endif + + +BeecryptMutex::BeecryptMutex() throw (MutexFailed) +#if defined(ACTUALLY_DOES_SOMETHING) + : pmutex_(new bc_mutex_t) +#endif +{ +#if defined(MYSQLPP_PLATFORM_WINDOWS) + *impl_ptr(pmutex_) = CreateMutex((LPSECURITY_ATTRIBUTES) 0, FALSE, + (LPCTSTR) 0); + if (!impl_val(pmutex_)) + throw MutexFailed("CreateMutex failed"); +#else +# if HAVE_SYNCH_H || HAVE_PTHREAD + register int rc; +# endif +# if HAVE_SYNCH_H + if ((rc = mutex_init(impl_ptr(pmutex_), USYNC_THREAD, 0))) + throw MutexFailed(strerror(rc)); +# elif HAVE_PTHREAD + if ((rc = pthread_mutex_init(impl_ptr(pmutex_), 0))) + throw MutexFailed(strerror(rc)); +# endif +#endif +} + + +BeecryptMutex::~BeecryptMutex() +{ +#if defined(ACTUALLY_DOES_SOMETHING) +# if defined(MYSQLPP_PLATFORM_WINDOWS) + CloseHandle(impl_val(pmutex_)); +# elif HAVE_SYNCH_H + mutex_destroy(impl_ptr(pmutex_)); +# elif HAVE_PTHREAD + pthread_mutex_destroy(impl_ptr(pmutex_)); +# endif + + delete impl_ptr(pmutex_); +#endif +} + + +void +BeecryptMutex::lock() throw (MutexFailed) +{ +#if defined(MYSQLPP_PLATFORM_WINDOWS) + if (WaitForSingleObject(impl_val(pmutex_), INFINITE) == WAIT_OBJECT_0) + return; + throw MutexFailed("WaitForSingleObject failed"); +#else +# if HAVE_SYNCH_H || HAVE_PTHREAD + register int rc; +# endif +# if HAVE_SYNCH_H + if ((rc = mutex_lock(impl_ptr(pmutex_)))) + throw MutexFailed(strerror(rc)); +# elif HAVE_PTHREAD + if ((rc = pthread_mutex_lock(impl_ptr(pmutex_)))) + throw MutexFailed(strerror(rc)); +# endif +#endif +} + + +bool +BeecryptMutex::trylock() throw (MutexFailed) +{ +#if defined(ACTUALLY_DOES_SOMETHING) +# if defined(MYSQLPP_PLATFORM_WINDOWS) + switch (WaitForSingleObject(impl_val(pmutex_), 0)) { + case WAIT_TIMEOUT: + return false; + case WAIT_OBJECT_0: + return true; + default: + throw MutexFailed("WaitForSingleObbject failed"); + } +# else + register int rc; +# if HAVE_SYNCH_H + if ((rc = mutex_trylock(impl_ptr(pmutex_))) == 0) + return true; + if (rc == EBUSY) + return false; + throw MutexFailed(strerror(rc)); +# elif HAVE_PTHREAD + if ((rc = pthread_mutex_trylock(impl_ptr(pmutex_))) == 0) + return true; + if (rc == EBUSY) + return false; + throw MutexFailed(strerror(rc)); +# endif +# endif +#else + return true; // no-op build, so always succeed +#endif +} + + +void +BeecryptMutex::unlock() throw (MutexFailed) +{ +#if defined(MYSQLPP_PLATFORM_WINDOWS) + if (!ReleaseMutex(impl_val(pmutex_))) + throw MutexFailed("ReleaseMutex failed"); +#else +# if HAVE_SYNCH_H || HAVE_PTHREAD + register int rc; +# endif +# if HAVE_SYNCH_H + if ((rc = mutex_unlock(impl_ptr(pmutex_)))) + throw MutexFailed(strerror(rc)); +# elif HAVE_PTHREAD + if ((rc = pthread_mutex_unlock(impl_ptr(pmutex_)))) + throw MutexFailed(strerror(rc)); +# endif +#endif +} + +} // end namespace mysqlpp + ADDED lib/beemutex.h Index: lib/beemutex.h ================================================================== --- /dev/null +++ lib/beemutex.h @@ -0,0 +1,118 @@ +/// \file beemutex.h +/// \brief MUTually EXclusive lock class. +/// \author Bob Deblier +/// +/// Modified by Warren Young of Educational Technology Resources, Inc. +/// from version in Beecrypt 4.1.2: +/// +/// - minor style changes to make it fit within MySQL++ +/// - changed init() to a ctor and destroy() to a dtor +/// - class just becomes a no-op if no supported mutex type is available +/// - throwing MutexFailed instead of \c char* +/// - moved all method implementations from inline in the .h file to +/// a .cpp file so we don't have to make the header depend on config.h +/// on autoconf-using systems +/// - made private mutex member a void* so we don't have to define the +/// full type in the .h file, due to previous item +/// - added more Doxygen comments, and changed some existing comments + +/*********************************************************************** + Copyright (c) 2004 Beeyond Software Holding BV and (c) 2007-2008 + by Educational Technology Resources, Inc. Others may also hold + copyrights on code in this file. See the CREDITS file in the top + directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#if !defined(MYSQLPP_BEEMUTEX_H) +#define MYSQLPP_BEEMUTEX_H + +#include "exceptions.h" + +namespace mysqlpp { + +/// \brief Wrapper around platform-specific mutexes. +/// +/// This class is only intended to be used within the library. We don't +/// really want to support this as a general purpose class. If it works +/// for you as-is, that's great, we won't try to stop you. But if you +/// run into a problem that doesn't affect MySQL++ itself, we're not +/// likely to bother enhancing this class to fix the problem. +class MYSQLPP_EXPORT BeecryptMutex +{ +public: + /// \brief Create the mutex object + /// + /// Throws a MutexFailed exception if we can't acquire the lock for + /// some reason. The exception contains a message saying why. + BeecryptMutex() throw (MutexFailed); + + /// \brief Destroy the mutex + /// + /// Failures are quietly ignored. + ~BeecryptMutex(); + + /// \brief Acquire the mutex, blocking if it can't be acquired + /// immediately. + void lock() throw (MutexFailed); + + /// \brief Acquire the mutex immediately and return true, or return + /// false if it would have to block to acquire the mutex. + bool trylock() throw (MutexFailed); + + /// \brief Release the mutex + void unlock() throw (MutexFailed); + +private: + void* pmutex_; +}; + + +/// \brief Wrapper around BeecryptMutex to add scope-bound locking +/// and unlocking. +/// +/// This allows code to lock a mutex and ensure it will unlock on exit +/// from the enclosing scope even in the face of exceptions. This is +/// separate from BeecryptMutex because we don't want to make this +/// behavior mandatory. + +class ScopedLock +{ +public: + /// \brief Lock the mutex. + explicit ScopedLock(BeecryptMutex& mutex) : + mutex_(mutex) + { + mutex.lock(); + } + + /// \brief Unlock the mutex. + ~ScopedLock() { mutex_.unlock(); } + +private: + ScopedLock(const ScopedLock&); // can't copy + ScopedLock& operator =(const ScopedLock&); // can't assign + + BeecryptMutex& mutex_; ///< the mutex object we manage +}; + +} // end namespace mysqlpp + +#endif // !defined(MYSQLPP_BEEMUTEX_H) + ADDED lib/common.h Index: lib/common.h ================================================================== --- /dev/null +++ lib/common.h @@ -0,0 +1,185 @@ +/// \file common.h +/// \brief This file includes top-level definitions for use both +/// internal to the library, and outside it. Contrast mysql++.h +/// +/// This file mostly takes care of platform differences. + +/*********************************************************************** + Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and + (c) 2004-2008 by Educational Technology Resources, Inc. Others may + also hold copyrights on code in this file. See the CREDITS file in + the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#if !defined(MYSQLPP_COMMON_H) +#define MYSQLPP_COMMON_H + +#if !defined(DOXYGEN_IGNORE) +// Doxygen will not generate documentation for the following stuff. + +// Enable SSQLS by default. Turned off below on platforms where we +// know it doesn't work. +#define MYSQLPP_SSQLS_COMPATIBLE + +// For all platforms but Visual C++ 2003, the following macro is just +// an alias for "*this". It needs a more complicated definition on +// VC++ 2003 to work around an error in the overloaded operator lookup +// logic. For an explanation of the problem, see: +// http://groups.google.com/group/microsoft.public.vc.stl/browse_thread/thread/9a68d84644e64f15 +#define MYSQLPP_QUERY_THISPTR *this + +// Work out major platform-specific stuff here. +#if defined(__WIN32__) || defined(_WIN32) +# define MYSQLPP_PLATFORM_WINDOWS + + // Windows compiler support. Tested with Microsoft Visual C++, + // Borland C++ Builder, and MinGW GCC. +# include + + // Stuff for Visual C++ only +# if defined(_MSC_VER) +# define MYSQLPP_PLATFORM_VISUAL_CPP + // MS *still* doesn't ship stdint.h, through VC++ 2008 at least. + // This means we have to take a wild guess at appropriate + // integer types in lib/sql_types.h. See test/inttypes.cpp for + // tests that check whether we've guessed well. +# define MYSQLPP_NO_STDINT_H +# if _MSC_VER < 1400 + // Workarounds for limitations of VC++ 2003 that are fixed + // in 2005 and later. +# undef MYSQLPP_QUERY_THISPTR +# define MYSQLPP_QUERY_THISPTR dynamic_cast(*this) +# undef MYSQLPP_SSQLS_COMPATIBLE +# elif !defined(_STLP_VERSION) && !defined(_STLP_VERSION_STR) + // VC++ 2005 or newer and not using STLport, so #define + // portability flags indicating features we can use from + // the compiler's native RTL. +# define MYSQLPP_HAVE_LOCALTIME_S +# define MYSQLPP_HAVE_STD__NOINIT +# endif + + // Disable complaints about STL data members: VC++ believes + // these need to be __declspec(dllexport) for some reason. +# pragma warning(disable: 4251) + // Disable complaint that VC++ doesn't grok throw specs +# pragma warning(disable: 4290) + // Disable whining about using 'this' as a member initializer on VC++. +# pragma warning(disable: 4355) + // Disable whining about implicit conversions to bool +# pragma warning(disable: 4800) + // Disable nagging about new "secure" functions like strncpy_s() +# pragma warning(disable: 4996) + // Call _snprintf() for VC++ version of snprintf() function +# define snprintf _snprintf +# endif + + // Define DLL import/export tags for Windows compilers, where we build + // the library into a DLL, for LGPL license compatibility reasons. + // (This is based on a similar mechanism in wxWindows.) + + #ifdef MYSQLPP_MAKING_DLL + // When making the DLL, export tagged symbols, so they appear + // in the import library. + #define MYSQLPP_EXPORT __declspec(dllexport) + #elif !defined(MYSQLPP_NO_DLL) + // We must be _using_ the DLL, so import symbols instead. + #define MYSQLPP_EXPORT __declspec(dllimport) + #else + // Not making a DLL at all, so no-op these declspecs + #define MYSQLPP_EXPORT + #endif +#else + // If not Windows, we assume some sort of Unixy build environment, + // where autotools is used. (This includes Cygwin!) #include the + // config.h file only if this file was included from a non-header + // file, because headers must not be dependent on config.h. +# if defined(MYSQLPP_NOT_HEADER) +# include "config.h" +# endif + + // Make DLL stuff a no-op on this platform. + #define MYSQLPP_EXPORT +#endif + +#if defined(MYSQLPP_MYSQL_HEADERS_BURIED) +# include +#else +# include +#endif + +namespace mysqlpp { + +/// \brief Alias for 'true', to make code requesting exceptions more +/// readable. +const bool use_exceptions = true; + +/// \brief Used to disambiguate overloads of equal_list() in SSQLSes. +enum sql_cmp_type { sql_use_compare }; + +#if !defined(DOXYGEN_IGNORE) +// Figure out how to get large integer support on this system. Suppress +// refman documentation for these typedefs, as they're system-dependent. +#if defined(MYSQLPP_NO_LONG_LONGS) +// Alias "longlong" and "ulonglong" to the regular "long" counterparts +typedef unsigned long ulonglong; +typedef long longlong; +#elif defined(_MSC_VER) +// It's VC++, so we'll use Microsoft's 64-bit integer types +typedef unsigned __int64 ulonglong; +typedef __int64 longlong; +#else +// No better idea, so assume the C99 convention. If your compiler +// doesn't support this, please provide a patch to extend this ifdef, or +// define MYSQLPP_NO_LONG_LONGS. +typedef unsigned long long ulonglong; +typedef long long longlong; +#endif +#endif // !defined(DOXYGEN_IGNORE) + +#if !defined(MYSQLPP_NO_UNSIGNED_INT_TYPES) +/// \brief Contraction for 'unsigned long' +/// +/// This is not to be used within the library or directly by end-user +/// code. It exists to make the MySQL C API headers happy: my_global.h +/// defines it, but we can't use it in MySQL++, so we do it ourselves. +typedef unsigned long ulong; +#endif + +} // end namespace mysqlpp + +// The MySQL headers define these macros, which is completely wrong in a +// C++ project. Undo the damage. +#undef min +#undef max + +#endif // !defined(DOXYGEN_IGNORE) + + +// Now that we've defined all the stuff above, we can pull in the full +// MySQL header. Basically, the above largely replaces MySQL's my_global.h +// while actually working with C++. This is why we disobey the MySQL +// developer docs, which recommend including my_global.h before mysql.h. +#if defined(MYSQLPP_MYSQL_HEADERS_BURIED) +# include +#else +# include +#endif + +#endif // !defined(MYSQLPP_COMMON_H) ADDED lib/comparable.h Index: lib/comparable.h ================================================================== --- /dev/null +++ lib/comparable.h @@ -0,0 +1,94 @@ +/// \file comparable.h +/// \brief Declares the Comparable mixin + +/*********************************************************************** + Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and + (c) 2004-2008 by Educational Technology Resources, Inc. Others may + also hold copyrights on code in this file. See the CREDITS file in + the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#if !defined(MYSQLPP_COMPARABLE_H) +#define MYSQLPP_COMPARABLE_H + +/// \brief Mix-in that gives its subclass a full set of comparison +/// operators. +/// +/// Simply by inheriting publically from this and implementing +/// compare(), the subclass gains a full set of comparison operators, +/// because all of the operators are implemented in terms of compare(). +template +class Comparable +{ +public: + /// \brief Returns true if "other" is equal to this object + bool operator ==(const T& other) const + { + return !compare(other); + } + + /// \brief Returns true if "other" is not equal to this object + bool operator !=(const T& other) const + { + return compare(other); + } + + /// \brief Returns true if "other" is less than this object + bool operator <(const T& other) const + { + return compare(other) < 0; + } + + /// \brief Returns true if "other" is less than or equal to this object + bool operator <=(const T& other) const + { + return compare(other) <= 0; + } + + /// \brief Returns true if "other" is greater than this object + bool operator >(const T& other) const + { + return compare(other) > 0; + } + + /// \brief Returns true if "other" is greater than or equal to this object + bool operator >=(const T& other) const + { + return compare(other) >= 0; + } + +protected: + /// \brief Destroy object + /// + /// This class has nothing to destroy, but declaring the dtor + /// virtual placates some compilers set to high warning levels. + /// Protecting it ensures you can't delete subclasses through base + /// class pointers, which makes no sense because this class isn't + /// made for polymorphism. It's just a mixin. + virtual ~Comparable() { } + + /// \brief Compare this object to another of the same type + /// + /// Returns < 0 if this object is "before" the other, 0 of they are + /// equal, and > 0 if this object is "after" the other. + virtual int compare(const T& other) const = 0; +}; + +#endif // !defined(MYSQLPP_COMPARABLE_H) ADDED lib/connection.cpp Index: lib/connection.cpp ================================================================== --- /dev/null +++ lib/connection.cpp @@ -0,0 +1,383 @@ +/*********************************************************************** + connection.cpp - Implements the Connection class. + + Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and + (c) 2004-2008 by Educational Technology Resources, Inc. Others may + also hold copyrights on code in this file. See the CREDITS file in + the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#define MYSQLPP_NOT_HEADER +#include "connection.h" + +#include "dbdriver.h" +#include "query.h" +#include "result.h" + +using namespace std; + +namespace mysqlpp { + +Connection::Connection(bool te) : +OptionalExceptions(te), +driver_(new DBDriver()), +copacetic_(true) +{ +} + + +Connection::Connection(const char* db, const char* server, + const char* user, const char* password, unsigned int port) : +OptionalExceptions(), +driver_(new DBDriver()), +copacetic_(true) +{ + connect(db, server, user, password, port); +} + + +Connection::Connection(const Connection& other) : +OptionalExceptions(), +driver_(new DBDriver(*other.driver_)) +{ + copy(other); +} + + +Connection::~Connection() +{ + disconnect(); + delete driver_; +} + + +void +Connection::build_error_message(const char* core) +{ + error_message_ = "Can't "; + error_message_ += core; + error_message_ += " while disconnected"; +} + + +std::string +Connection::client_version() const +{ + return driver_->client_version(); +} + + +bool +Connection::connect(const char* db, const char* server, + const char* user, const char* password, unsigned int port) +{ + // Figure out what the server parameter means, then try to establish + // the connection. + error_message_.clear(); + string host, socket_name; + copacetic_ = parse_ipc_method(server, host, port, socket_name) && + driver_->connect(host.c_str(), + (socket_name.empty() ? 0 : socket_name.c_str()), port, db, + user, password); + + // If it failed, decide how to tell the user + if (!copacetic_ && throw_exceptions()) { + throw ConnectionFailed(error(), errnum()); + } + else { + return copacetic_; + } +} + + +bool +Connection::connected() const +{ + return driver_->connected(); +} + + +void +Connection::copy(const Connection& other) +{ + error_message_.clear(); + set_exceptions(other.throw_exceptions()); + driver_->copy(*other.driver_); +} + + +ulonglong +Connection::count_rows(const std::string& table) +{ + error_message_.clear(); + Query q(this, throw_exceptions()); + q << "SELECT COUNT(*) FROM " << table; + if (StoreQueryResult res = q.store()) { + return res[0][0]; + } + else { + return 0; + } +} + + +bool +Connection::create_db(const std::string& db) +{ + error_message_.clear(); + Query q(this, throw_exceptions()); + q << "CREATE DATABASE " << db; + return q.exec(); +} + + +void +Connection::disconnect() +{ + error_message_.clear(); + driver_->disconnect(); +} + + +bool +Connection::drop_db(const std::string& db) +{ + error_message_.clear(); + Query q(this, throw_exceptions()); + q << "DROP DATABASE " << db; + return q.exec(); +} + + +int +Connection::errnum() +{ + return driver_->errnum(); +} + + +const char* +Connection::error() const +{ + return error_message_.size() ? error_message_.c_str() : driver_->error(); +} + + +std::string +Connection::ipc_info() const +{ + return driver_->ipc_info(); +} + + +bool +Connection::kill(unsigned long tid) const +{ + error_message_.clear(); + return driver_->kill(tid); +} + + +Connection& +Connection::operator=(const Connection& rhs) +{ + copy(rhs); + return *this; +} + + +bool +Connection::parse_ipc_method(const char* server, std::string& host, + unsigned int& port, std::string& socket_name) +{ + // NOTE: This routine has no connection type knowledge. It can only + // recognize a 0 value for the server parameter. All substantial + // tests are delegated to our specialized subclasses, which figure + // out what kind of connection the server address denotes. We do + // the platform-specific tests first as they're the most reliable. + + if (server == 0) { + // Just take all the defaults + return true; + } + else if (WindowsNamedPipeConnection::is_wnp(server)) { + // Use Windows named pipes + host = server; + return true; + } + else if (UnixDomainSocketConnection::is_socket(server)) { + // Use Unix domain sockets + socket_name = server; + return true; + } + else { + // Failing above, it can only be some kind of TCP/IP address. + host = server; + return TCPConnection::parse_address(host, port, error_message_); + } +} + + +bool +Connection::ping() +{ + if (connected()) { + error_message_.clear(); + return driver_->ping(); + } + else { + // Not connected, and we've forgotten everything we need in + // order to re-connect, if we once were connected. + build_error_message("ping database server"); + return false; + } +} + + +int +Connection::protocol_version() const +{ + return driver_->protocol_version(); +} + + +Query +Connection::query(const char* qstr) +{ + return Query(this, throw_exceptions(), qstr); +} + + +Query +Connection::query(const std::string& qstr) +{ + return query(qstr.c_str()); +} + + +bool +Connection::select_db(const std::string& db) +{ + error_message_.clear(); + if (connected()) { + if (driver_->select_db(db.c_str())) { + return true; + } + else { + if (throw_exceptions()) { + throw DBSelectionFailed(error(), errnum()); + } + return false; + } + } + else { + build_error_message("select a database"); + if (throw_exceptions()) { + throw DBSelectionFailed(error_message_.c_str()); + } + return false; + } +} + + +std::string +Connection::server_status() const +{ + return driver_->server_status(); +} + + +std::string +Connection::server_version() const +{ + return driver_->server_version(); +} + + +bool +Connection::set_option(Option* o) +{ + error_message_ = driver_->set_option(o); + if (error_message_.empty()) { + return true; + } + else { + if (throw_exceptions()) { + throw BadOption(error_message_, typeid(*o)); + } + return false; + } +} + + +bool +Connection::shutdown() +{ + error_message_.clear(); + if (connected()) { + if (driver_->shutdown()) { + return true; + } + else { + if (throw_exceptions()) { + throw ConnectionFailed(error(), errnum()); + } + return false; + } + } + else { + build_error_message("shutdown database server"); + if (throw_exceptions()) { + throw ConnectionFailed(error_message_.c_str()); + } + return false; + } +} + + +bool +Connection::thread_aware() +{ + return DBDriver::thread_aware(); +} + + +void +Connection::thread_end() +{ + DBDriver::thread_end(); +} + + +unsigned long +Connection::thread_id() +{ + return driver_->thread_id(); +} + + +bool +Connection::thread_start() +{ + return DBDriver::thread_start(); +} + +} // end namespace mysqlpp + ADDED lib/connection.h Index: lib/connection.h ================================================================== --- /dev/null +++ lib/connection.h @@ -0,0 +1,368 @@ +/// \file connection.h +/// \brief Declares the Connection class. +/// +/// Every program using MySQL++ must create a Connection object, which +/// manages information about the connection to the database server, and +/// performs connection-related operations once the connection is up. +/// Subordinate classes, such as Query and Row take their defaults as +/// to whether exceptions are thrown when errors are encountered from +/// the Connection object that created them, directly or indirectly. + +/*********************************************************************** + Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and + (c) 2004-2007 by Educational Technology Resources, Inc. Others may + also hold copyrights on code in this file. See the CREDITS file in + the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#if !defined(MYSQLPP_CONNECTION_H) +#define MYSQLPP_CONNECTION_H + +#include "common.h" + +#include "noexceptions.h" +#include "options.h" + +#include + +namespace mysqlpp { + +#if !defined(DOXYGEN_IGNORE) +// Make Doxygen ignore this +class MYSQLPP_EXPORT Query; +class DBDriver; +#endif + +/// \brief Manages the connection to the database server. +/// +/// This class is a thick wrapper around DBDriver, adding high-level +/// error handling, utility functions, and abstraction away from +/// underlying C API details. + +class MYSQLPP_EXPORT Connection : public OptionalExceptions +{ +private: + /// \brief Pointer to bool data member, for use by safe bool + /// conversion operator. + /// + /// \see http://www.artima.com/cppsource/safebool.html + typedef bool Connection::*private_bool_type; + +public: + /// \brief Create object without connecting to the database server. + /// + /// \param te if true, exceptions are thrown on errors + Connection(bool te = true); + + /// \brief Create object and connect to database server in one step. + /// + /// This constructor allows you to most fully specify the options + /// used when connecting to the database server. + /// + /// \param db name of database to select upon connection + /// \param server specifies the IPC method and parameters for + /// contacting the server; see below for details + /// \param user user name to log in under, or 0 to use the user + /// name this program is running under + /// \param password password to use when logging in + /// \param port TCP port number database server is listening on, or + /// 0 to use default value; note that you may also give this as + /// part of the \c server parameter + /// + /// The server parameter can be any of several different forms: + /// + /// - \b 0: Let the database driver decide how to connect; usually + /// some sort of localhost IPC method. + /// - \b ".": On Windows, this means named pipes, if the server + /// supports it + /// - \b "/some/domain/socket/path": If the passed string doesn't + /// match one of the previous alternatives and we're on a system + /// that supports Unix domain sockets, MySQL++ will test it to see + /// if it names one, and use it if we have permission. + /// - \b "host.name.or.ip:port": If the previous test fails, or if + /// the system doesn't support Unix domain sockets at all, it + /// assumes the string is some kind of network address, optionally + /// followed by a colon and port. The name can be in dotted quad + /// form, a host name, or a domain name. The port can either be a + /// TCP/IP port number or a symbolic service name. If a port or + /// service name is given here and a nonzero value is passed for + /// the \c port parameter, the latter takes precedence. + Connection(const char* db, const char* server = 0, const char* user = 0, + const char* password = 0, unsigned int port = 0); + + /// \brief Establish a new connection using the same parameters as + /// an existing connection. + /// + /// \param other existing Connection object + Connection(const Connection& other); + + /// \brief Destroy object + virtual ~Connection(); + + /// \brief Get version of library underpinning the current database + /// driver. + std::string client_version() const; + + /// \brief Connect to database after object is created. + /// + /// It's better to use the connect-on-create constructor if you can. + /// See its documentation for the meaning of these parameters. + /// + /// If you call this method on an object that is already connected + /// to a database server, the previous connection is dropped and a + /// new connection is established. + virtual bool connect(const char* db = 0, const char* server = 0, + const char* user = 0, const char* password = 0, + unsigned int port = 0); + + /// \brief Returns true if connection was established successfully + /// + /// \return true if connection was established successfully + bool connected() const; + + /// \brief Returns the number of rows in a table + /// + /// \param table name of table whose rows you want counted + /// + /// This is syntactic sugar for a \c SELECT \c COUNT(*) + /// \c FROM \c table SQL query. + ulonglong count_rows(const std::string& table); + + /// \brief Ask the database server to create a database + /// + /// \param db name of database to create + /// + /// \return true if database was created successfully + bool create_db(const std::string& db); + + /// \brief Drop the connection to the database server + void disconnect(); + + /// \brief Returns a reference to the current database driver + /// + /// \internal This exists mostly for the benefit of Query, Result + /// and ResUse. If there is something you want to use in the + /// DBDriver interface, look for something similar in one of these + /// classes instead. If you still can't find it, send a message to + /// the mailing list asking about it. Unless you're doing something + /// very low-level, there should never be a reason to use the + /// driver directly. + DBDriver* driver() { return driver_; } + + /// \brief Asks the database server to drop (destroy) a database + /// + /// \param db name of database to destroy + /// + /// \return true if database was dropped successfully + bool drop_db(const std::string& db); + + /// \brief Return last error number associated with this + /// connection + int errnum(); + + /// \brief Return error message for last error associated with + /// this connection. + /// + /// Returns either a MySQL++-specific error message if one exists, + /// or one from the current database driver otherwise. + const char* error() const; + + /// \brief Get information about the IPC connection to the + /// database server + /// + /// String contains info about type of connection (e.g. TCP/IP, + /// named pipe, Unix socket...) and the server hostname. + std::string ipc_info() const; + + /// \brief Kill a database server thread + /// + /// \param tid ID of thread to kill + /// + /// \see thread_id() + bool kill(unsigned long tid) const; + + /// \brief Test whether any error has occurred within the object. + /// + /// Allows the object to be used in bool context, like this: + /// + /// \code + /// Connection conn; + /// .... use conn + /// if (conn) { + /// ... nothing bad has happened since last successful use + /// } + /// else { + /// ... some error has occurred + /// } + /// \endcode + /// + /// Prior to MySQL++ v3, the object was always falsy when we + /// weren't connected. Now a true return simply indicates a lack of + /// errors. If you've been using this to test for whether the + /// connection is still up, you need to call connected() instead. + operator private_bool_type() const + { + return copacetic_ ? &Connection::copacetic_ : 0; + } + + /// \brief Copy an existing Connection object's state into this + /// object. + Connection& operator=(const Connection& rhs); + + /// \brief "Pings" the database server + /// + /// \retval true if server is responding + /// \retval false if either we already know the connection is down + /// and cannot re-establish it, or if the server did not respond to + /// the ping and we could not re-establish the connection. + bool ping(); + + /// \brief Returns version number of the protocol the database + /// driver uses to communicate with the server. + int protocol_version() const; + + /// \brief Return a new query object. + /// + /// The returned query object is tied to this connection object, + /// so when you call a method like + /// \link Query::execute() execute() \endlink + /// on that object, the query is sent to the server this object + /// is connected to. + /// + /// \param qstr an optional query string for populating the + /// new Query object + Query query(const char* qstr = 0); + + /// \brief Return a new query object + /// + /// \param qstr initial query string + Query query(const std::string& qstr); + + /// \brief Change to a different database managed by the + /// database server we are connected to. + /// + /// \param db database to switch to + /// + /// \retval true if we changed databases successfully + bool select_db(const std::string& db); + + /// \brief Get the database server's version string + std::string server_version() const; + + /// \brief Sets a connection option + /// + /// \param o pointer to any derivative of Option allocated on + /// the heap + /// + /// Objects passed to this method and successfully set will be + /// released when this Connection object is destroyed. If an error + /// occurs while setting the option the object will be deleted + /// immediately. + /// + /// Because there are so many Option subclasses, the actual effect + /// of this function has a wide range. This mechanism abstracts + /// away many things that are unrelated down at the database driver + /// level, hiding them behind a coherent, type-safe interface. + /// + /// The rules about which options can be set, when, are up to the + /// underlying database driver. Some must be set before the + /// connection is established because they can only be used during + /// that connection setup process. Others can be set at any time + /// after the connection comes up. If you get it wrong, you'll get + /// a BadOption exception. + /// + /// \retval true if option was successfully set + bool set_option(Option* o); + + /// \brief Ask database server to shut down. + bool shutdown(); + + /// \brief Returns information about database server's status + std::string server_status() const; + + /// \brief Returns true if both MySQL++ and database driver we're + /// using were compiled with thread awareness. + static bool thread_aware(); + + /// \brief Tells the underlying database driver that this thread + /// is done using the library. + static void thread_end(); + + /// \brief Returns the database server's thread ID for this connection + /// + /// This has nothing to do with threading on the client side. The + /// only thing you can do with this value is pass it to kill(). + unsigned long thread_id(); + + /// \brief Tells the underlying database driver that the current + /// thread is now using its services. + /// + /// It's not necessary to call this from the thread that creates + /// the connection as it's done automatically. This method exists + /// for times when multiple threads may use this object; it allows + /// the underlying database driver to set up any per-thread data + /// structures it needs. + /// + /// The MySQL++ user manual's chapter + /// on threads details two major strategies for dealing with + /// connections in the face of threads. The Connection-per-thread + /// option frees you from ever having to call this method. The + /// other documented strategy is to use ConnectionPool, which opens + /// the possibility for one thread to create a connection that + /// another uses, so you do need to call this method in that case, + /// or with any other similar strategy. + /// + /// \retval True if there was no problem + static bool thread_start(); + +protected: + /// \brief Build an error message in the standard form used whenever + /// one of the methods can't succeed because we're not connected to + /// the database server. + void build_error_message(const char* core); + + /// \brief Establish a new connection as a copy of an existing one + /// + /// \param other the connection to copy + void copy(const Connection& other); + + /// \brief Extract elements from the server parameter in formats + /// suitable for passing to DBDriver::connect(). + bool parse_ipc_method(const char* server, std::string& host, + unsigned int& port, std::string& socket_name); + + //// Subclass data + mutable std::string error_message_; ///< MySQL++ specific error, if any + +private: + DBDriver* driver_; + bool copacetic_; +}; + + +} // end namespace mysqlpp + +// Not strictly required, but bring in our specialization subclasses +#include "tcp_connection.h" +#include "uds_connection.h" +#include "wnp_connection.h" + +#endif // !defined(MYSQLPP_CONNECTION_H) + ADDED lib/cpool.cpp Index: lib/cpool.cpp ================================================================== --- /dev/null +++ lib/cpool.cpp @@ -0,0 +1,161 @@ +/*********************************************************************** + cpool.cpp - Implements the ConnectionPool class. + + Copyright (c) 2007 by Educational Technology Resources, Inc. and + (c) 2007 by Jonathan Wakely. Others may also hold copyrights on + code in this file. See the CREDITS file in the top directory of + the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#include "cpool.h" + +#include "connection.h" + +#include +#include + +namespace mysqlpp { + + +/// \brief Functor to test whether a given ConnectionInfo object is +/// "too old". +/// +/// \internal This is a template only because ConnectionInfo is private. +/// Making it a template means the private type is only used at the point +/// of instantiation, where it is accessible. + +template +class TooOld : std::unary_function +{ +public: +#if !defined(DOXYGEN_IGNORE) + TooOld(unsigned int tmax) : + min_age_(time(0) - tmax) + { + } + + bool operator()(const ConnInfoT& conn_info) const + { + return !conn_info.in_use && conn_info.last_used <= min_age_; + } + +#endif +private: + time_t min_age_; +}; + + + +//// clear ///////////////////////////////////////////////////////////// +// Destroy connections in the pool, either all of them (completely +// draining the pool) or just those not currently in use. The public +// method shrink() is an alias for clear(false). + +void +ConnectionPool::clear(bool all) +{ + ScopedLock lock(mutex_); // ensure we're not interfered with + + PoolIt it = pool_.begin(), doomed; + while (it != pool_.end()) { + if (all || !it->in_use) { + doomed = it++; + destroy(doomed->conn); + pool_.erase(doomed); + } + else { + ++it; + } + } +} + + +//// find_mru ////////////////////////////////////////////////////////// +// Find most recently used available connection. Uses operator< for +// ConnectionInfo to order pool with MRU connection last. Returns 0 if +// there are no connections not in use. + +Connection* +ConnectionPool::find_mru() +{ + PoolIt mru = std::max_element(pool_.begin(), pool_.end()); + if (mru != pool_.end() && !mru->in_use) { + mru->in_use = true; + return mru->conn; + } + else { + return 0; + } +} + + +//// grab ////////////////////////////////////////////////////////////// + +Connection* +ConnectionPool::grab() +{ + ScopedLock lock(mutex_); // ensure we're not interfered with + remove_old_connections(); + if (Connection* mru = find_mru()) { + return mru; + } + else { + // No free connections, so create and return a new one. + pool_.push_back(ConnectionInfo(create())); + return pool_.back().conn; + } +} + + +//// release /////////////////////////////////////////////////////////// + +void +ConnectionPool::release(const Connection* pc) +{ + ScopedLock lock(mutex_); // ensure we're not interfered with + + for (PoolIt it = pool_.begin(); it != pool_.end(); ++it) { + if (it->conn == pc) { + it->in_use = false; + it->last_used = time(0); + break; + } + } +} + + +//// remove_old_connections //////////////////////////////////////////// +// Remove connections that were last used too long ago. + +void +ConnectionPool::remove_old_connections() +{ + TooOld too_old(max_idle_time()); + + PoolIt it = pool_.begin(); + while ((it = std::find_if(it, pool_.end(), too_old)) != pool_.end()) { + destroy(it->conn); + pool_.erase(it++); + } +} + + +} // end namespace mysqlpp + ADDED lib/cpool.h Index: lib/cpool.h ================================================================== --- /dev/null +++ lib/cpool.h @@ -0,0 +1,201 @@ +/// \file cpool.h +/// \brief Declares the ConnectionPool class. + +/*********************************************************************** + Copyright (c) 2007-2008 by Educational Technology Resources, Inc. and + (c) 2007 by Jonathan Wakely. Others may also hold copyrights on + code in this file. See the CREDITS file in the top directory of + the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#if !defined(MYSQLPP_CPOOL_H) +#define MYSQLPP_CPOOL_H + +#include "beemutex.h" + +#include + +#include +#include + +namespace mysqlpp { + +#if !defined(DOXYGEN_IGNORE) +// Make Doxygen ignore this +class MYSQLPP_EXPORT Connection; +#endif + +/// \brief Manages a pool of connections for programs that need more +/// than one Connection object at a time, but can't predict how many +/// they need in advance. +/// +/// This class is useful in programs that need to make multiple +/// simultaneous queries on the database; this requires multiple +/// Connection objects due to a hard limitation of the underlying +/// C API. Connection pools are most useful in multithreaded programs, +/// but it can be helpful to have one in a single-threaded program as +/// well. Sometimes it's necessary to get more data from the server +/// while in the middle of processing data from an earlier query; this +/// requires multiple connections. Whether you use a pool or manage +/// connections yourself is up to you, but realize that this class +/// takes care of a lot of subtle details for you that aren't obvious. +/// +/// The pool's policy for connection reuse is to always return the +/// \em most recently used connection that's not being used right now. +/// This ensures that excess connections don't hang around any longer +/// than they must. If the pool were to return the \em least recently +/// used connection, it would be likely to result in a large pool of +/// sparsely used connections because we'd keep resetting the last-used +/// time of whichever connection is least recently used at that moment. + +class MYSQLPP_EXPORT ConnectionPool +{ +public: + /// \brief Create empty pool + ConnectionPool() { } + + /// \brief Destroy object + /// + /// If the pool raises an assertion on destruction, it means our + /// subclass isn't calling clear() in its dtor as it should. + virtual ~ConnectionPool() { assert(empty()); } + + /// \brief Returns true if pool is empty + bool empty() const { return pool_.empty(); } + + /// \brief Grab a free connection from the pool. + /// + /// This method creates a new connection if an unused one doesn't + /// exist, and destroys any that have remained unused for too long. + /// If there is more than one free connection, we return the most + /// recently used one; this allows older connections to die off over + /// time when the caller's need for connections decreases. + /// + /// Do not delete the returned pointer. This object manages the + /// lifetime of connection objects it creates. + /// + /// \retval a pointer to the connection + virtual Connection* grab(); + + /// \brief Return a connection to the pool + /// + /// Marks the connection as no longer in use. + /// + /// The pool updates the last-used time of a connection only on + /// release, on the assumption that it was used just prior. There's + /// nothing forcing you to do it this way: your code is free to + /// delay releasing idle connections as long as it likes. You + /// want to avoid this because it will make the pool perform poorly; + /// if it doesn't know approximately how long a connection has + /// really been idle, it can't make good judgements about when to + /// remove it from the pool. + virtual void release(const Connection* pc); + + /// \brief Remove all unused connections from the pool + void shrink() { clear(false); } + +protected: + /// \brief Drains the pool, freeing all allocated memory. + /// + /// A derived class must call this in its dtor to avoid leaking all + /// Connection objects still in existence. We can't do it up at + /// this level because this class's dtor can't call our subclass's + /// destroy() method. + /// + /// \param all if true, remove all connections, even those in use + void clear(bool all = true); + + /// \brief Create a new connection + /// + /// Subclasses must override this. + /// + /// Essentially, this method lets your code tell ConnectionPool + /// what server to connect to, what login parameters to use, what + /// connection options to enable, etc. ConnectionPool can't know + /// any of this without your help. + /// + /// \retval A connected Connection object + virtual Connection* create() = 0; + + /// \brief Destroy a connection + /// + /// Subclasses must override this. + /// + /// This is for destroying the objects returned by create(). + /// Because we can't know what the derived class did to create the + /// connection we can't reliably know how to destroy it. + virtual void destroy(Connection*) = 0; + + /// \brief Returns the maximum number of seconds a connection is + /// able to remain idle before it is dropped. + /// + /// Subclasses must override this as it encodes a policy issue, + /// something that MySQL++ can't declare by fiat. + /// + /// \retval number of seconds before an idle connection is destroyed + /// due to lack of use + virtual unsigned int max_idle_time() = 0; + + /// \brief Returns the current size of the internal connection pool. + size_t size() const { return pool_.size(); } + +private: + //// Internal types + struct ConnectionInfo { + Connection* conn; + time_t last_used; + bool in_use; + + ConnectionInfo(Connection* c) : + conn(c), + last_used(time(0)), + in_use(true) + { + } + + // Strict weak ordering for ConnectionInfo objects. + // + // This ordering defines all in-use connections to be "less + // than" those not in use. Within each group, connections + // less recently touched are less than those more recent. + bool operator<(const ConnectionInfo& rhs) const + { + const ConnectionInfo& lhs = *this; + return lhs.in_use == rhs.in_use ? + lhs.last_used < rhs.last_used : + lhs.in_use; + } + }; + typedef std::list PoolT; + typedef PoolT::iterator PoolIt; + + //// Internal support functions + Connection* find_mru(); + void remove_old_connections(); + + //// Internal data + PoolT pool_; + BeecryptMutex mutex_; +}; + +} // end namespace mysqlpp + +#endif // !defined(MYSQLPP_CPOOL_H) + ADDED lib/custom.h Index: lib/custom.h ================================================================== --- /dev/null +++ lib/custom.h @@ -0,0 +1,34 @@ +/// \file custom.h +/// \brief Backwards-compatibility header; loads ssqls.h + +/*********************************************************************** + Copyright (c) 2008 by Educational Technology Resources, Inc. + Others may also hold copyrights on code in this file. See the + CREDITS file in the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#if !defined(MYSQLPP_CUSTOM_H) +#define MYSQLPP_CUSTOM_H + +#warning MySQL++ header custom.h is now called ssqls.h. Please update your code. +#include "ssqls.h" + +#endif // !defined(MYSQLPP_CUSTOM_H) + ADDED lib/datetime.cpp Index: lib/datetime.cpp ================================================================== --- /dev/null +++ lib/datetime.cpp @@ -0,0 +1,323 @@ +/*********************************************************************** + datetime.cpp - Implements date and time classes compatible with MySQL's + various date and time column types. + + Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and + (c) 2004-2008 by Educational Technology Resources, Inc. Others may + also hold copyrights on code in this file. See the CREDITS file in + the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#define MYSQLPP_NOT_HEADER +#include "common.h" + +#include "datetime.h" +#include "stream2string.h" + +#include + +#include +#include + +using namespace std; + +namespace mysqlpp { + +static void +safe_localtime(struct tm* ptm, const time_t t) +{ +#if defined(MYSQLPP_HAVE_LOCALTIME_S) + // common.h detected localtime_s() from native RTL of VC++ 2005 and up + localtime_s(ptm, &t); +#elif defined(HAVE_LOCALTIME_R) + // autoconf detected POSIX's localtime_r() on this system + localtime_r(&t, ptm); +#else + // No explicitly thread-safe localtime() replacement found. This + // may still be thread-safe, as some C libraries take special steps + // within localtime() to get thread safety, such as TLS. + memcpy(ptm, localtime(&t), sizeof(tm)); +#endif +} + + +std::ostream& operator <<(std::ostream& os, const Date& d) +{ + char fill = os.fill('0'); + ios::fmtflags flags = os.setf(ios::right); + os << setw(4) << d.year() << '-' + << setw(2) << static_cast(d.month()) << '-' + << setw(2) << static_cast(d.day()); + os.flags(flags); + os.fill(fill); + return os; +} + + +std::ostream& operator <<(std::ostream& os, const Time& t) +{ + char fill = os.fill('0'); + ios::fmtflags flags = os.setf(ios::right); + os << setw(2) << static_cast(t.hour()) << ':' + << setw(2) << static_cast(t.minute()) << ':' + << setw(2) << static_cast(t.second()); + os.flags(flags); + os.fill(fill); + return os; +} + + +std::ostream& operator <<(std::ostream& os, const DateTime& dt) +{ + if (dt.is_now()) { + return os << "NOW()"; + } + else { + operator <<(os, Date(dt)); + os << ' '; + return operator <<(os, Time(dt)); + } +} + + +Date::Date(time_t t) +{ + struct tm tm; + safe_localtime(&tm, t); + + year_ = tm.tm_year + 1900; + month_ = tm.tm_mon + 1; + day_ = tm.tm_mday; +} + + +DateTime::DateTime(time_t t) +{ + struct tm tm; + safe_localtime(&tm, t); + + year_ = tm.tm_year + 1900; + month_ = tm.tm_mon + 1; + day_ = tm.tm_mday; + hour_ = tm.tm_hour; + minute_ = tm.tm_min; + second_ = tm.tm_sec; + + now_ = false; +} + + +Time::Time(time_t t) +{ + struct tm tm; + safe_localtime(&tm, t); + + hour_ = tm.tm_hour; + minute_ = tm.tm_min; + second_ = tm.tm_sec; +} + + +const char* +Date::convert(const char* str) +{ + char num[5]; + + num[0] = *str++; + num[1] = *str++; + num[2] = *str++; + num[3] = *str++; + num[4] = 0; + year_ = static_cast(strtol(num, 0, 10)); + if (*str == '-') str++; + + num[0] = *str++; + num[1] = *str++; + num[2] = 0; + month_ = static_cast(strtol(num, 0, 10)); + if (*str == '-') str++; + + num[0] = *str++; + num[1] = *str++; + num[2] = 0; + day_ = static_cast(strtol(num, 0, 10)); + + return str; +} + + +const char* +Time::convert(const char* str) +{ + char num[5]; + + num[0] = *str++; + num[1] = *str++; + num[2] = 0; + hour_ = static_cast(strtol(num,0,10)); + if (*str == ':') str++; + + num[0] = *str++; + num[1] = *str++; + num[2] = 0; + minute_ = static_cast(strtol(num,0,10)); + if (*str == ':') str++; + + num[0] = *str++; + num[1] = *str++; + num[2] = 0; + second_ = static_cast(strtol(num,0,10)); + + return str; +} + + +const char* +DateTime::convert(const char* str) +{ + Date d; + str = d.convert(str); + year_ = d.year(); + month_ = d.month(); + day_ = d.day(); + + if (*str == ' ') ++str; + + Time t; + str = t.convert(str); + hour_ = t.hour(); + minute_ = t.minute(); + second_ = t.second(); + + now_ = false; + + return str; +} + + +int +Date::compare(const Date& other) const +{ + if (year_ != other.year_) return year_ - other.year_; + if (month_ != other.month_) return month_ - other.month_; + return day_ - other.day_; +} + + +int +Time::compare(const Time& other) const +{ + if (hour_ != other.hour_) return hour_ - other.hour_; + if (minute_ != other.minute_) return minute_ - other.minute_; + return second_ - other.second_; +} + + +int +DateTime::compare(const DateTime& other) const +{ + if (now_ && other.now_) { + return 0; + } + else { + Date d(*this), od(other); + Time t(*this), ot(other); + + if (int x = d.compare(od)) { + return x; + } + else { + return t.compare(ot); + } + } +} + + +Date::operator std::string() const +{ + return stream2string(*this); +} + + +DateTime::operator std::string() const +{ + return stream2string(*this); +} + + +Time::operator std::string() const +{ + return stream2string(*this); +} + + +Date::operator time_t() const +{ + struct tm tm; + safe_localtime(&tm, time(0)); + + tm.tm_mday = day_; + tm.tm_mon = month_ - 1; + tm.tm_year = year_ - 1900; + tm.tm_isdst = -1; + + return mktime(&tm); +} + + +DateTime::operator time_t() const +{ + if (now_) { + // Many factors combine to make it almost impossible for this + // case to return the same value as you'd get if you used this + // in a query. But, you gotta better idea than to return the + // current time for an object initialized with the value "now"? + return time(0); + } + else { + struct tm tm; + tm.tm_sec = second_; + tm.tm_min = minute_; + tm.tm_hour = hour_; + tm.tm_mday = day_; + tm.tm_mon = month_ - 1; + tm.tm_year = year_ - 1900; + tm.tm_isdst = -1; + + return mktime(&tm); + } +} + + +Time::operator time_t() const +{ + struct tm tm; + safe_localtime(&tm, time(0)); + + tm.tm_sec = second_; + tm.tm_min = minute_; + tm.tm_hour = hour_; + tm.tm_isdst = -1; + + return mktime(&tm); +} + +} // end namespace mysqlpp + ADDED lib/datetime.h Index: lib/datetime.h ================================================================== --- /dev/null +++ lib/datetime.h @@ -0,0 +1,449 @@ +/// \file datetime.h +/// \brief Declares classes to add SQL-compatible date and time +/// types to C++'s type system. + +/*********************************************************************** + Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and + (c) 2004-2008 by Educational Technology Resources, Inc. Others may + also hold copyrights on code in this file. See the CREDITS file in + the top directory of the distribution for details. + + This file is part of MySQL++. + + MySQL++ 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. + + MySQL++ 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 MySQL++; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA +***********************************************************************/ + +#if !defined(MYSQLPP_DATETIME_H) +#define MYSQLPP_DATETIME_H + +#include "common.h" + +#include "comparable.h" + +#include +#include + +namespace mysqlpp { + +/// \brief C++ form of SQL's DATETIME type. +/// +/// This object exists primarily for conversion purposes. You can +/// initialize it in several different ways, and then convert the object +/// to SQL string form, extract the individual y/m/d h:m:s values, +/// convert it to C's time_t, etc. + +class MYSQLPP_EXPORT DateTime : public Comparable +{ +public: + /// \brief Default constructor + DateTime() : + Comparable(), + year_(0), + month_(0), + day_(0), + hour_(0), + minute_(0), + second_(0), + now_(true) + { + } + + /// \brief Initialize object from discrete y/m/d h:m:s values. + /// + /// \param y year_ + /// \param mon month_ + /// \param d day_ of month_ + /// \param h hour_ + /// \param min minute_ + /// \param s second_ + DateTime(unsigned short y, unsigned char mon, unsigned char d, + unsigned char h, unsigned char min, unsigned char s) : + Comparable(), + year_(y), + month_(mon), + day_(d), + hour_(h), + minute_(min), + second_(s), + now_(false) + { + } + + /// \brief Initialize object as a copy of another Date + DateTime(const DateTime& other) : + Comparable(), + year_(other.year_), + month_(other.month_), + day_(other.day_), + hour_(other.hour_), + minute_(other.minute_), + second_(other.second_), + now_(other.now_) + { + } + + /// \brief Initialize object from a C string containing a SQL + /// date-and-time string + /// + /// String must be in the HH:MM:SS format. It doesn't have to be + /// zero-padded. + explicit DateTime(const char* str) { convert(str); } + + /// \brief Initialize object from a C++ string containing a + /// SQL date-and-time string + /// + /// This works with any stringish class that declares a c_str() + /// member function: std::string, mysqlpp::String... + /// + /// \sa DateTime(const char*) + template + explicit DateTime(const Str& str) + { + convert(str.c_str()); + } + + /// \brief Initialize object from a \c time_t + explicit DateTime(time_t t); + + /// \brief Compare this object to another. + /// + /// Returns < 0 if this object is before the other, 0 of they are + /// equal, and > 0 if this object is after the other. + int compare(const DateTime& other) const; + + /// \brief Parse a SQL date and time string into this object. + const char* convert(const char*); + + /// \brief Get the date/time value's day part, 1-31 + unsigned char day() const { return day_; } + + /// \brief Change the date/time value's day part, 1-31 + void day(unsigned char d) { day_ = d; now_ = false; } + + /// \brief Get the date/time value's hour part, 0-23 + unsigned char hour() const { return hour_; } + + /// \brief Change the date/time value's hour part, 0-23 + void hour(unsigned char h) { hour_ = h; now_ = false; } + + /// \brief Returns true if object will evaluate to SQL "NOW()" on + /// conversion to string. + bool is_now() const { return now_; } + + /// \brief Get the date/time value's minute part, 0-59 + unsigned char minute() const { return minute_; } + + /// \brief Change the date/time value's minute part, 0-59 + void minute(unsigned char m) { minute_ = m; now_ = false; } + + /// \brief Get the date/time value's month part, 1-12 + unsigned char month() const { return month_; } + + /// \brief Change the date/time value's month part, 1-12 + void month(unsigned char m) { month_ = m; now_ = false; } + + /// \brief Factory to create an object instance that will convert + /// to SQL "NOW()" on insertion into a query + /// + /// This is just syntactic sugar around the default ctor + static DateTime now() { return DateTime(); } + + /// \brief Convert to std::string + operator std::string() const; + + /// \brief Convert to time_t + operator time_t() const; + + /// \brief Get the date/time value's second part, 0-59 + unsigned char second() const { return second_; } + + /// \brief Change the date/time value's second part, 0-59 + void second(unsigned char s) { second_ = s; now_ = false; } + + /// \brief Return our value in std::string form + std::string str() const { return *this; } + + /// \brief Get the date/time value's year part + /// + /// There's no trickery here like in some date/time implementations + /// where you have to add 1900 or something like that. + unsigned short year() const { return year_; } + + /// \brief Change the date/time value's year part + /// + /// Pass the year value normally; we don't optimize the value by + /// subtracting 1900 like some other date/time implementations. + void year(unsigned short y) { year_ = y; now_ = false; } + +private: + unsigned short year_; ///< the year, as a simple integer + unsigned char month_; ///< the month, 1-12 + unsigned char day_; ///< the day, 1-31 + unsigned char hour_; ///< the hour, 0-23 + unsigned char minute_; ///< the minute, 0-59 + unsigned char second_; ///< the second, 0-59 + + bool now_; ///< true if object not initialized with explicit value +}; + + +/// \brief Inserts a DateTime object into a C++ stream in a +/// SQL-compatible format. +/// +/// The date and time are inserted into the stream, in that order, +/// with a space between them. +/// +/// \param os stream to insert date and time into +/// \param dt date/time object to insert into stream +MYSQLPP_EXPORT std::ostream& operator <<(std::ostream& os, + const DateTime& dt); + + +/// \brief C++ form of SQL's DATE type. +/// +/// Objects of this class can be inserted into streams, and +/// initialized from SQL DATE strings. +class MYSQLPP_EXPORT Date : public Comparable +{ +public: + /// \brief Default constructor + Date() : year_(0), month_(0), day_(0) { } + + /// \brief Initialize object + Date(unsigned short y, unsigned char m, unsigned char d) : + Comparable(), + year_(y), + month_(m), + day_(d) + { + } + + /// \brief Initialize object as a copy of another Date + Date(const Date& other) : + Comparable(), + year_(other.year_), + month_(other.month_), + day_(other.day_) + { + } + + /// \brief Initialize object from date part of date/time object + Date(const DateTime& other) : + Comparable(), + year_(other.year()), + month_(other.month()), + day_(other.day()) + { + } + + /// \brief Initialize object from a C string containing a date + /// + /// String must be in the YYYY-MM-DD format. It doesn't have to be + /// zero-padded. + explicit Date(const char* str) { convert(str); } + + /// \brief Initialize object from a C++ string containing a date + /// + /// This works with any stringish class that declares a c_str() + /// member function: std::string, mysqlpp::String... + /// + /// \sa Date(const char*) + template + explicit Date(const Str& str) { convert(str.c_str()); } + + /// \brief Initialize object from a \c time_t + /// + /// Naturally, we throw away the "time" part of the \c time_t. If + /// you need to keep it, you want to use DateTime instead. + explicit Date(time_t t); + + /// \brief Compare this date to another. + /// + /// Returns < 0 if this date is before the other, 0 of they are + /// equal, and > 0 if this date is after the other. + int compare(const Date& other) const; + + /// \brief Parse a SQL date string into this object. + const char* convert(const char*); + + /// \brief Get the date's day part, 1-31 + unsigned char day() const { return day_; } + + /// \brief Change the date's day part, 1-31 + void day(unsigned char d) { day_ = d; } + + /// \brief Get the date's month part, 1-12 + unsigned char month() const { return month_; } + + /// \brief Change the date's month part, 1-12 + void month(unsigned char m) { month_ = m; } + + /// \brief Convert to std::string + operator std::string() const; + + /// \brief Convert to time_t + /// + /// The "time" part of the \c time_t is "now" + operator time_t() const; + + /// \brief Return our value in std::string form + std::string str() const { return *this; } + + /// \brief Get the date's year part + /// + /// There's no trickery here like in some date implementations + /// where you have to add 1900 or something like that. + unsigned short year() const { return year_; } + + /// \brief Change the date's year part + /// + /// Pass the year value normally; we don't optimize the value by + /// subtracting 1900 like some other date implementations. + void year(unsigned short y) { year_ = y; } + +private: + unsigned short year_; ///< the year, as a simple integer + unsigned char month_; ///< the month, 1-12 + unsigned char day_; ///< the day, 1-31 +}; + +/// \brief Inserts a Date object into a C++ stream +/// +/// The format is YYYY-MM-DD, zero-padded. +/// +/// \param os stream to insert date into +/// \param d date to insert into stream +MYSQLPP_EXPORT std::ostream& operator <<(std::ostream& os, + const Date& d); + + +/// \brief C++ form of SQL's TIME type. +/// +/// Objects of this class can be inserted into streams, and +/// initialized from SQL TIME strings. +class MYSQLPP_EXPORT Time : public Comparable