Patches for any of these thoughtfully considered! See the HACKERS file for instructions on sending patches. The items in the bug fix/maintenance section are the easiest to do without breaking things, so if you're looking for a project.... Here's a meta-item that doesn't really fit into any of the categories below: any time you must hand-roll some SQL code in your program, consider whether it could be reduced to an API feature that would be widely useful. Patches or proposals of this sort are always welcome. v2.2 Plan --------- This plan is not set in stone. These are simply the features we want to try and tackle for the v2.2 release. Items in this plan may slip to a future release. This typically happens when the proper solution is unclear, so the best way to prevent this is to get on the mailing list and help discuss it. Or even better, provide a patch; we rarely reject working code outright. Items from the following sections may make it in, but if you don't help make that happen, this will just be on the whim of one of MySQL++'s developers. Don't forget that it's possible to subclass yourself from the "MySQL++'s developers" base class. o Conditionally allow the Lockable mechanism to the Boost.Threads library. If MYSQLPP_BOOST_THREADS is defined, #include the proper header and use Boost's mutexes. Add a configure script option that defines this macro and adds any needed libraries to the tags. Mechanism must reflect these MySQL C API restrictions: - Only one query executing at once per connection - For "use" queries, Connection (and therefore Query) object must remain locked until last row is consumed - Safest to have one Connection per thread. Rules for sharing: http://dev.mysql.com/doc/mysql/en/threaded-clients.html Need some way to call mysql_thread_init() and mysql_thread_end() per thread. Also, work in some way to call mysql_thread_safe() automatically, perhaps the first time through the function that calls mysql_thread_init(). If the C API library reports that it is not thread-safe, report this to the caller, perhaps through an exception, or simply by refusing to init more than one thread. o Currently, all overloads for Query's execute(), store() and use() methods eventually call the const char* version, which does the actual work of executing the query. This rules out query strings with embedded nulls, as you're likely to get with BLOB columns. Also, it means MySQL++ must scan the string for length in a few places. The C API isn't limited in this way if you use mysql_real_query(), but you need an accurate length value to call it. We could get that length with binary data if the end of the call chain were a std::string overload, but we can't do that easily because each of these functions has a version taking a SQLString (a subclass of std:string) for template queries. One way around this is to add a parallel set of functions (e.g. do_execute(), or execute_(), or some such) that take a single std::string, which are the new terminus of the call chain. Reimplement const char* versions in terms of these. Another way is to add more overloads taking both a const char* and a length parameter. Make these new functions the terminus to each call chain. Yet another way is that we may be able to co-opt the first template query version of each of these functions, as it takes a single SQLString. o Viktor Stark reports that a BLOB of binary data containing 0's appears to be truncated when stored in an SSQLS with a std::string for the BLOB field. Investigate, and fix if confirmed. o Date and time classes are pretty minimalistic; they could be so much more powerful. Some ideas: - Add time_t conversion. - Arithmetic features. (See "Practical Algorithms for Programmers" by Binstock and Rex.) - It may be possible to get some nice syntactic sugar, such as a way to call SQL functions like NOW() when inserting certain Date/Time objects into a Query stream. Don't forget to write an example showing how to use these new mechanisms. It may be possible to find existing date and time classes that can be extended, instead of reinventing the wheel. Boost, perhaps? o Build a forward iterator mechanism for ResUse. Make it general enough that you can use it with STL algorithms like find_if(). Then make an example to demonstrate this augmentation of SELECT. Also, update usequery example to use the iterator. Tricky bit: how do we make it not interfere with subclass Result's random-access iterator? o Have resetdb create a second table containing a BLOB column that load_file and cgi_image can use. Rework load_image to take the standard command line parameters, and load a JPEG or something into the BLOB table. Include a suitable JPEG with the distribution. (A cheesy Photoshopped "MySQL++ Rocks!" thing should suffice.) Rework cgi_image so that you can drop it into a cgi-image directory and immediately use it to query the database and return the image data in CGI format. o It may be possible to optimize the use of ColData in the return from Row::operator[]. Currently, that operator returns a temporary ColData object, which contains a std::string buffer which is initialized by a const char* pointer to data within the Row object. Since the ColData object is temporary, you currently must copy the data a second time to store it when using Row::operator[]. If the end user just wants a const char*, this double copy could be prevented. See http://lists.mysql.com/plusplus/4451 for the proposal. o Add Chris Frey's packarray class? v3.0 Plan --------- Version 3.0 is primarily for those changes that will break the ABI. (i.e. removing functions, changing function signatures, etc.) This plan is very tenuous. Some of this could slip to v4.0. o Apply Richard Forrest's iterator patch. o The quote manipulator (and presumably the others as well) don't work properly with char*. See this for details: http://lists.mysql.com/plusplus/5617 o Change the unsigned int overloads for operator[] on const_subscript_iterator and its subclasses from unsigned int to a plain int. This should fix the ambiguous overload problems, such as with row[0]. See the following threads for reference: http://lists.mysql.com/plusplus/4947 http://lists.mysql.com/plusplus/4952 http://lists.mysql.com/plusplus/4960 o Several MySQL++ functions wrap the MySQL C API too literally: they indicate success by returning 0 instead of true, as most other wrapper functions do. o Apply Waba's patch allowing Null fields in SSQLSes: http://lists.mysql.com/plusplus/5433 o Deprecate sql_create_basic_* They have less functionality and they're no easier to use than sql_create and friends. o Consider whether some of the current boilerplate can be made into a base class that all SSQLSes derive from. Some template functions like Query::insert might become regular member functions, taking a reference to the SSQLS base class. o Abstract all uses of MySQL C API functions into a database driver class with a generic interface. This is a step towards database-independence, without the parallel class hierarchy required by the MySQL++ 1.7 design. Also, it will make it easier to make class Connection completely friend-less. Right now, the main reason it needs friends is because these other classes make C API calls using its private MYSQL data member. The other reasons for it having friends aren't nearly as compelling, so it wouldn't be hard to justify redesigning Connection to eliminate these final reasons. While it would be easy to have just one global database driver object, it's probably going to be necessary to have one per Connection. Consider what happens when you have one program connected to two very different MySQL databases, and you indirectly call C API functions that take MYSQL parameters. It's likely that those calls are supposed to behave different, depending on the data in that MYSQL object; for instance, different character encodings in the selected databases. So, there must somehow be a way to pass the database driver's instance pointer down to all objects that will need to use the driver. A side benefit is that a single program could talk to multiple different database server types. Imagine a program for importing data from PostgreSQL and loading it into a MySQL table, for instance. Future Features --------------- These changes are not assigned to any particular version. They could happen at any time. If you want one to appear at some definite date, get coding and provide a patch! 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 Row object currently depends on the associated ResUse object to stick around through all calls to .at(), because it needs the list of field types in the result set to construct ColData objects. This means it's not possible to store the result of several queries before accessing the data. Currently, this is just a documented limitation, but it would be nice if there were a clean way to avoid this. Obviously you could just copy the type list when constructing the Row object, but that seems pointlessly inefficient. o Define operator<< for Fields, Row, ResUse, etc. In other words, there should be a way to get a user-readable version of received data without a lot of code. Perhaps use a CSV output format, or a mysql(1) one (ASCII grid). o manip.cpp uses mysql_escape_string(), which doesn't take the selected database's character set into account. To do that, you must use mysql_real_escape_string(), which differs by taking a MYSQL instance as an additional parameter. The problem is, Connection owns the relevant MYSQL instance, and the manipulator functionality is implemented in global functions (operator<<() and such) so they have no direct access to the relevant Connection object. The key question for all operator<<'s for manipulators to ask is, "which Query object am I being inserted into?" From there, you can look up the associated Connection object. In some cases, this answer to the question is easy, because the operator takes an ostream parameter, which can be dynamically cast to Query. From there, it's just a lookup table problem. Other operator<<'s don't take an ostream, but they do take a manipulator. Right now, manipulators are just enum values, but they could in fact be classes. Classes can carry data, so there may be a way to "bind" them to the appropriate Connection object. If not, then perhaps some other method will pop out of the database driver class idea. The driver object may be able to look up a suitable Connection object for the manipulators. o MySQL++ handles automatic quoting and escaping differently for cout and cerr than for Query streams. This should probably be simplified so that automatic quoting is only done for Query streams. No other stream type should be treated specially. o Some field_list() functions use the do_nothing manipulator, while others use the quote manipulator. Need to pick one. In the vast majority of cases, quoting won't be necessary, so make that the default. But, it should be possible to turn it on, if needed. If all uses of quoting are in template code, this can be a #define, allowing different programs built on the same system to get different quoting rules. Otherwise, it will probably have to be a configure script flag, which will "burn" the choice into the built binary. o User-settable floating-point comparison precisions? Something like this: http://lists.mysql.com/plusplus/3984 As it currently stands, sql_cmp(double,double) is foolish. One shouldn't do exact equality comparison on floating point values. o Consider using MySQL C API enum constants in mysql_type_info::types definition instead of hard-coded values. This could potentially break a lot of infrastructure, though, so do it only with care. Bug Fix/Maintenance Items ------------------------- These items could happen in any version. o 64-bit integer support has been reported to work, but more confirmation is wanted. o Template ListInsert in lib/myset.h isn't being used within the library. It could probably be used in place of SetInsert in the same file, which things like type_info.h do use now, but it isn't clear how one would go about doing that without changing the library code. Document it or throw it away. o Update refman.css to use new Doxygen 1.4 CSS IDs.