diff --git a/lib/mysql/GPL-2.0 b/lib/mysql/GPL-2.0 new file mode 100644 index 00000000..d159169d --- /dev/null +++ b/lib/mysql/GPL-2.0 @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, 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 software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, 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 redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +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 give any other recipients of the Program a copy of this License +along with the Program. + +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 Program or any portion +of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +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 Program, 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 Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) 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; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, 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 executable. 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. + +If distribution of executable or 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 counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program 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. + + 5. 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 Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program 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. + + 7. 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 Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program 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 Program. + +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. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program 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. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 Program +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 Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, 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 + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), 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 Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. 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 program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/lib/mysql/HISTORY b/lib/mysql/HISTORY new file mode 100644 index 00000000..6a567d55 --- /dev/null +++ b/lib/mysql/HISTORY @@ -0,0 +1,193 @@ +===================== + What's new in 1.2.4 +===================== + +final +===== + +No changes. + + +rc 1 +==== + +Fixed a dangling reference to the old types module. + + +beta 5 +====== + +Another internal fix for handling remapped character sets. + +_mysql.c was broken for the case where read_timeout was *not* available. (Issue #6) + +Documentation was converted to sphinx but there is a lot of cleanup left to do. + + +beta 4 +====== + +Added support for the MySQL read_timeout option. Contributed by +Jean Schurger (jean@schurger.org). + +Added a workaround so that the MySQL character set utf8mb4 works with Python; utf8 is substituted +on the Python side. + + +beta 3 +====== + +Unified test database configuration, and set up CI testing with Travis. + +Applied several patches from André Malo (ndparker@users.sf.net) which fix some issues +with exception handling and reference counting and TEXT/BLOB conversion. + + +beta 2 +====== + +Reverted an accidental change in the exception format. (issue #1) + +Reverted some raise statements so that they will continue to work with Python < 2.6 + + +beta 1 +====== + +A lot of work has been done towards Python 3 compatibility, and avoiding warnings with Python 2.7. +This includes import changes, converting dict.has_kay(k) to k in dict, updating some test suite methods, etc. + +Due to the difficulties of supporting Python 3 and Python < 2.7, 1.2.4 will support Python 2.4 though 2.7. +1.3.0 will support Python 3 and Python 2.7 and 2.6. + +MySQLdb-2.0 is instead going to become moist-1.0. See https://github.com/farcepest/moist + +The Windows build has been simplified, and I plan to correct pre-built i386 packages built +against the python.org Python-2.7 package and MySQL Connector/C-6.0. Contact me if you +need ia64 packages. + +The connection's cursorclass (if not default) was being lost on reconnect. + +Newer versions of MySQL don't use OpenSSL and therefore don't have HAVE_SSL defined, but they do have +a different SSL library. Fixed this so SSL support would be enabled in this case. + +The regex that looked for SQL INSERT statement and VALUES in cursor.executemany() was made case-insensitive +again. + + +===================== + What's new in 1.2.3 +===================== + +ez_setup.py has been update to include various fixes that affect the build. + +Better Python version and dependency detection as well as eliminate exception +warnings under Python 2.6. + +Eliminated memory leaks related to Unicode and failed connections. + +Corrected connection .escape() functionality. + +Miscellaneous cleanups and and expanded testing suite to ensure ongoing release +quality. + +===================== + What's new in 1.2.2 +===================== + +The build system has been completely redone and should now build +on Windows without any patching; uses setuptools. + +Added compatibility for Python 2.5, including support for with statement. + +connection.ping() now takes an optional boolean argument which can +enable (or disable) automatic reconnection. + +Support returning SET columns as Python sets was removed due to an +API bug in MySQL; corresponding test removed. + +Added a test for single-character CHAR columns. + +BLOB columns are now returned as Python strings instead of byte arrays. + +BINARY character columns are always returned as Python strings, and not +unicode. + +Fixed a bug introduced in 1.2.1 where the new SHOW WARNINGS support broke +SSCursor. + +Only encode the query (convert to a string) when it is a unicode instance; +re-encoding encoded strings would break things. + +Make a deep copy of conv when connecting, since it can be modified. + +Added support for new VARCHAR and BIT column types. + +DBAPISet objects were broken, but nobody noticed. + + +======================== + What's new in 1.2.1_p2 +======================== + +There are some minor build fixes which probably only affect MySQL +older than 4.0. + +If you had MySQL older than 4.1, the new charset and sql_mode +parameters didn't work right. In fact, it was impossible to create +a connection due to the charset problem. + +If you are using MySQL-4.1 or newer, there is no practical difference +between 1.2.1 and 1.2.1_p2, and you don't need to upgrade. + + +===================== + What's new in 1.2.1 +===================== + +Switched to Subversion. Was going to do this for 1.3, but a +SourceForge CVS outage has forced the issue. + +Mapped a lot of new 4.1 and 5.0 error codes to Python exceptions + +Added an API call for mysql_set_character_set(charset) (MySQL > 5.0.7) + +Added an API call for mysql_get_character_set_info() (MySQL > 5.0.10) + +Revamped the build system. Edit site.cfg if necessary (probably not +in most cases) + +Python-2.3 is now the minimum version. + +Dropped support for mx.Datetime and stringtimes; always uses Python +datetime module now. + +Improved unit tests + +New connect() options: +* charset: sets character set, implies use_unicode +* sql_mode: sets SQL mode (i.e. ANSI, etc.; see MySQL docs) + +When using MySQL-4.1 or newer, enables MULTI_STATEMENTS + +When using MySQL-5.0 or newer, enables MULTI_RESULTS + +When using MySQL-4.1 or newer, more detailed warning messages +are produced + +SET columns returned as Python Set types; you can pass a Set as +a parameter to cursor.execute(). + +Support for the new MySQL-5.0 DECIMAL implementation + +Support for Python Decimal type + +Some use of weak references internally. Cursors no longer leak +if you don't close them. Connections still do, unfortunately. + +ursor.fetchXXXDict() methods raise DeprecationWarning + +cursor.begin() is making a brief reappearence. + +cursor.callproc() now works, with some limitations. + diff --git a/lib/mysql/INSTALL b/lib/mysql/INSTALL new file mode 100644 index 00000000..f44b410d --- /dev/null +++ b/lib/mysql/INSTALL @@ -0,0 +1,253 @@ +==================== +MySQLdb Installation +==================== + +.. contents:: +.. + +Prerequisites +------------- + ++ Python 2.3.4 or higher + + * http://www.python.org/ + + * Versions lower than 2.3 WON'T WORK. + + * 2.4 is the primary test environment. + + * Red Hat Linux: + + - Make sure you have the Python development headers and libraries + (python-devel). + ++ setuptools + + * http://pypi.python.org/pypi/setuptools + ++ MySQL 3.23.32 or higher + + * http://www.mysql.com/downloads/ + + * Versions lower than 3.22 definitely WON'T WORK. + + * Versions lower than 3.22.19 might not work. + + * MySQL-3.22 might work but isn't supported anymore. It's very old. + + * MySQL-3.23 ought to work, but it's pretty elderly. + + * MySQL-4.0 is supported, but not tested and slightly discouraged. + + * MySQL-4.1 is supported. The prepared statements API is not + supported, and won't be until MySQLdb-1.3 or 2.0, if ever. + + * MySQL-5.0 is supported and tested, including stored procedures. + + * MySQL-5.1 is supported (currently a release candidate) but untested. + It should work. + + * MySQL-6.0 is sorta-kinda-supported (currently alpha) but untested. + It should work. + + * Drizzle is a fork of MySQL. So far + the C API looks really similar except everything is renamed. + Drizzle support probably won't happen in 1.2. There may be have to + be an entirely different module, but still using DB-API. + + * MaxDB, formerly known as SAP DB (and maybe Adabas D?), is a + completely different animal. Use the sapdb.sql module that comes + with MaxDB. + + * Red Hat Linux packages: + + - mysql-devel to compile + + - mysql and/or mysql-devel to run + + * MySQL.com RPM packages: + + - MySQL-devel to compile + + - MySQL-shared if you want to use their shared + library. Otherwise you'll get a statically-linked module, + which may or may not be what you want. + + - MySQL-shared to run if you compiled with MySQL-shared installed + + * Transactions (particularly InnoDB tables) are supported for + MySQL-3.23 and up. You may need a special package from your vendor + with this support turned on. + ++ zlib + + * Required for MySQL-3.23 and newer. + + * Red Hat Linux + + - zlib-devel to compile + + - zlib to run + ++ openssl + + * May be needed for MySQL-4.0 or newer, depending on compilation + options. If you need it, you probably already have it. + + - you may need openssl-devel on some platforms + ++ C compiler + + * Most free software-based systems already have this, usually gcc. + + * Most commercial UNIX platforms also come with a C compiler, or + you can also use gcc. + + * If you have some Windows flavor, you usually have to pay extra + for this, or you can use Cygwin_. + +.. _Cygwin: http://www.cygwin.com/ + + +Building and installing +----------------------- + +The setup.py script uses mysql_config to find all compiler and linker +options, and should work as is on any POSIX-like platform, so long as +mysql_config is in your path. + +Depending on which version of MySQL you have, you may have the option +of using three different client libraries. To select the client library, +edit the [options] section of site.cfg: + + embedded + use embedded server library (libmysqld) if True; otherwise use + one of the client libraries (default). + + threadsafe + thread-safe client library (libmysqlclient_r) if True (default); + otherwise use non-thread-safe (libmysqlclient). You should + always use the thread-safe library if you have the option; + otherwise you *may* have problems. + + static + if True, try to link against a static library; otherwise link + against dynamic libraries (default). You may need static linking + to use the embedded server. + + +Finally, putting it together:: + + $ tar xfz MySQL-python-1.2.1.tar.gz + $ cd MySQL-python-1.2.1 + $ # edit site.cfg if necessary + $ python setup.py build + $ sudo python setup.py install # or su first + + +Windows +....... + +I don't do Windows. However if someone provides me with a package for +Windows, I'll make it available. Don't ask me for help with Windows +because I can't help you. + +Generally, though, running setup.py is similar to above:: + + C:\...> python setup.py install + C:\...> python setup.py bdist_wininst + +The latter example should build a Windows installer package, if you +have the correct tools. In any event, you *must* have a C compiler. +Additionally, you have to set an environment variable (mysqlroot) +which is the path to your MySQL installation. In theory, it would be +possible to get this information out of the registry, but like I said, +I don't do Windows, but I'll accept a patch that does this. + +On Windows, you will definitely have to edit site.cfg since there is +no mysql_config in the MySQL package. + + +Zope +.... + +If you are using a binary package of Zope, you need run setup.py with +the python executable that came with Zope. Otherwise, you'll install +into the wrong Python tree and Zope (ZMySQLDA) will not be able to +find _mysql. + + +Binary Packages +--------------- + +I don't plan to make binary packages any more. However, if someone +contributes one, I will make it available. Several OS vendors have +their own packages available. + + +RPMs +.... + +If you prefer to install RPMs, you can use the bdist_rpm command with +setup.py. This only builds the RPM; it does not install it. You may +want to use the --python=XXX option, where XXX is the name of the +Python executable, i.e. python, python2, python2.4; the default is +python. Using this will incorporate the Python executable name into +the package name for the RPM so you have install the package multiple +times if you need to support more than one version of Python. You can +also set this in setup.cfg. + + +Red Hat Linux +............. + +MySQL-python is pre-packaged in Red Hat Linux 7.x and newer. This +includes Fedora Core and Red Hat Enterprise Linux. You can also +build your own RPM packages as described above. + + +Debian GNU/Linux +................ + +Packaged as `python-mysqldb`_:: + + # apt-get install python-mysqldb + +Or use Synaptic. + +.. _`python-mysqldb`: http://packages.debian.org/python-mysqldb + + +Ubuntu +...... + +Same as with Debian. + + +Gentoo Linux +............ + +Packaged as `mysql-python`_. :: + + # emerge sync + # emerge mysql-python + # emerge zmysqlda # if you use Zope + +.. _`mysql-python`: http://packages.gentoo.org/search/?sstring=mysql-python + + +BSD +... + +MySQL-python is a ported package in FreeBSD, NetBSD, and OpenBSD, +although the name may vary to match OS conventions. + + +License +------- + +GPL or the original license based on Python 1.5.2's license. + + +:Author: Andy Dustman +:Revision: $Id$ diff --git a/lib/mysql/MANIFEST.in b/lib/mysql/MANIFEST.in new file mode 100644 index 00000000..54b1fd5a --- /dev/null +++ b/lib/mysql/MANIFEST.in @@ -0,0 +1,14 @@ +recursive-include doc *.rst +recursive-include tests *.py +include doc/conf.py +include MANIFEST.in +include HISTORY +include INSTALL +include README.md +include GPL-2.0 +include pymemcompat.h +include metadata.cfg +include site.cfg +include setup_common.py +include setup_posix.py +include setup_windows.py diff --git a/lib/mysql/MySQL_python.egg-info/PKG-INFO b/lib/mysql/MySQL_python.egg-info/PKG-INFO new file mode 100644 index 00000000..0d7a901a --- /dev/null +++ b/lib/mysql/MySQL_python.egg-info/PKG-INFO @@ -0,0 +1,43 @@ +Metadata-Version: 1.1 +Name: MySQL-python +Version: 1.2.5 +Summary: Python interface to MySQL +Home-page: https://github.com/farcepest/MySQLdb1 +Author: Andy Dustman +Author-email: farcepest@gmail.com +License: GPL +Description: + ========================= + Python interface to MySQL + ========================= + + MySQLdb is an interface to the popular MySQL_ database server for + Python. The design goals are: + + - Compliance with Python database API version 2.0 [PEP-0249]_ + - Thread-safety + - Thread-friendliness (threads will not block each other) + + MySQL-3.23 through 5.5 and Python-2.4 through 2.7 are currently + supported. Python-3.0 will be supported in a future release. + PyPy is supported. + + MySQLdb is `Free Software`_. + + .. _MySQL: http://www.mysql.com/ + .. _`Free Software`: http://www.gnu.org/ + .. [PEP-0249] http://www.python.org/peps/pep-0249.html +Platform: ALL +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Other Environment +Classifier: License :: OSI Approved :: GNU General Public License (GPL) +Classifier: Operating System :: MacOS :: MacOS X +Classifier: Operating System :: Microsoft :: Windows :: Windows NT/2000 +Classifier: Operating System :: OS Independent +Classifier: Operating System :: POSIX +Classifier: Operating System :: POSIX :: Linux +Classifier: Operating System :: Unix +Classifier: Programming Language :: C +Classifier: Programming Language :: Python +Classifier: Topic :: Database +Classifier: Topic :: Database :: Database Engines/Servers diff --git a/lib/mysql/MySQL_python.egg-info/SOURCES.txt b/lib/mysql/MySQL_python.egg-info/SOURCES.txt new file mode 100644 index 00000000..e0b09bd2 --- /dev/null +++ b/lib/mysql/MySQL_python.egg-info/SOURCES.txt @@ -0,0 +1,60 @@ +GPL-2.0 +HISTORY +INSTALL +MANIFEST.in +README.md +_mysql.c +_mysql_exceptions.py +metadata.cfg +pymemcompat.h +setup.cfg +setup.py +setup_common.py +setup_posix.py +setup_windows.py +site.cfg +MySQL_python.egg-info/PKG-INFO +MySQL_python.egg-info/SOURCES.txt +MySQL_python.egg-info/dependency_links.txt +MySQL_python.egg-info/top_level.txt +MySQLdb/__init__.py +MySQLdb/connections.py +MySQLdb/converters.py +MySQLdb/cursors.py +MySQLdb/release.py +MySQLdb/times.py +MySQLdb/constants/CLIENT.py +MySQLdb/constants/CR.py +MySQLdb/constants/ER.py +MySQLdb/constants/FIELD_TYPE.py +MySQLdb/constants/FLAG.py +MySQLdb/constants/REFRESH.py +MySQLdb/constants/__init__.py +doc/FAQ.rst +doc/MySQLdb.constants.rst +doc/MySQLdb.rst +doc/_mysql.rst +doc/_mysql_exceptions.rst +doc/conf.py +doc/index.rst +doc/modules.rst +doc/user_guide.rst +doc/_build/_sources/FAQ.txt +doc/_build/_sources/MySQLdb.constants.txt +doc/_build/_sources/MySQLdb.txt +doc/_build/_sources/_mysql.txt +doc/_build/_sources/_mysql_exceptions.txt +doc/_build/_sources/distribute_setup.txt +doc/_build/_sources/index.txt +doc/_build/_sources/modules.txt +doc/_build/_sources/setup.txt +doc/_build/_sources/setup_common.txt +doc/_build/_sources/setup_posix.txt +doc/_build/_sources/setup_windows.txt +doc/_build/_sources/user_guide.txt +tests/capabilities.py +tests/configdb.py +tests/dbapi20.py +tests/test_MySQLdb_capabilities.py +tests/test_MySQLdb_dbapi20.py +tests/test_MySQLdb_nonstandard.py \ No newline at end of file diff --git a/lib/mysql/MySQL_python.egg-info/dependency_links.txt b/lib/mysql/MySQL_python.egg-info/dependency_links.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/lib/mysql/MySQL_python.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/lib/mysql/MySQL_python.egg-info/top_level.txt b/lib/mysql/MySQL_python.egg-info/top_level.txt new file mode 100644 index 00000000..08d3b445 --- /dev/null +++ b/lib/mysql/MySQL_python.egg-info/top_level.txt @@ -0,0 +1,3 @@ +MySQLdb +_mysql +_mysql_exceptions diff --git a/lib/mysql/MySQLdb/__init__.py b/lib/mysql/MySQLdb/__init__.py new file mode 100644 index 00000000..dc18e876 --- /dev/null +++ b/lib/mysql/MySQLdb/__init__.py @@ -0,0 +1,98 @@ +"""MySQLdb - A DB API v2.0 compatible interface to MySQL. + +This package is a wrapper around _mysql, which mostly implements the +MySQL C API. + +connect() -- connects to server + +See the C API specification and the MySQL documentation for more info +on other items. + +For information on how MySQLdb handles type conversion, see the +MySQLdb.converters module. + +""" + +__revision__ = """$Revision$"""[11:-2] +from MySQLdb.release import __version__, version_info, __author__ + +import _mysql + +if version_info != _mysql.version_info: + raise ImportError("this is MySQLdb version %s, but _mysql is version %r" % + (version_info, _mysql.version_info)) + +threadsafety = 1 +apilevel = "2.0" +paramstyle = "format" + +from _mysql import * +from MySQLdb.constants import FIELD_TYPE +from MySQLdb.times import Date, Time, Timestamp, \ + DateFromTicks, TimeFromTicks, TimestampFromTicks + +try: + frozenset +except NameError: + from sets import ImmutableSet as frozenset + +class DBAPISet(frozenset): + + """A special type of set for which A == x is true if A is a + DBAPISet and x is a member of that set.""" + + def __eq__(self, other): + if isinstance(other, DBAPISet): + return not self.difference(other) + return other in self + + +STRING = DBAPISet([FIELD_TYPE.ENUM, FIELD_TYPE.STRING, + FIELD_TYPE.VAR_STRING]) +BINARY = DBAPISet([FIELD_TYPE.BLOB, FIELD_TYPE.LONG_BLOB, + FIELD_TYPE.MEDIUM_BLOB, FIELD_TYPE.TINY_BLOB]) +NUMBER = DBAPISet([FIELD_TYPE.DECIMAL, FIELD_TYPE.DOUBLE, FIELD_TYPE.FLOAT, + FIELD_TYPE.INT24, FIELD_TYPE.LONG, FIELD_TYPE.LONGLONG, + FIELD_TYPE.TINY, FIELD_TYPE.YEAR]) +DATE = DBAPISet([FIELD_TYPE.DATE, FIELD_TYPE.NEWDATE]) +TIME = DBAPISet([FIELD_TYPE.TIME]) +TIMESTAMP = DBAPISet([FIELD_TYPE.TIMESTAMP, FIELD_TYPE.DATETIME]) +DATETIME = TIMESTAMP +ROWID = DBAPISet() + +def test_DBAPISet_set_equality(): + assert STRING == STRING + +def test_DBAPISet_set_inequality(): + assert STRING != NUMBER + +def test_DBAPISet_set_equality_membership(): + assert FIELD_TYPE.VAR_STRING == STRING + +def test_DBAPISet_set_inequality_membership(): + assert FIELD_TYPE.DATE != STRING + +def Binary(x): + return str(x) + +def Connect(*args, **kwargs): + """Factory function for connections.Connection.""" + from MySQLdb.connections import Connection + return Connection(*args, **kwargs) + +connect = Connection = Connect + +__all__ = [ 'BINARY', 'Binary', 'Connect', 'Connection', 'DATE', + 'Date', 'Time', 'Timestamp', 'DateFromTicks', 'TimeFromTicks', + 'TimestampFromTicks', 'DataError', 'DatabaseError', 'Error', + 'FIELD_TYPE', 'IntegrityError', 'InterfaceError', 'InternalError', + 'MySQLError', 'NULL', 'NUMBER', 'NotSupportedError', 'DBAPISet', + 'OperationalError', 'ProgrammingError', 'ROWID', 'STRING', 'TIME', + 'TIMESTAMP', 'Warning', 'apilevel', 'connect', 'connections', + 'constants', 'converters', 'cursors', 'debug', 'escape', 'escape_dict', + 'escape_sequence', 'escape_string', 'get_client_info', + 'paramstyle', 'string_literal', 'threadsafety', 'version_info'] + + + + diff --git a/lib/mysql/MySQLdb/connections.py b/lib/mysql/MySQLdb/connections.py new file mode 100644 index 00000000..ac885cea --- /dev/null +++ b/lib/mysql/MySQLdb/connections.py @@ -0,0 +1,351 @@ +""" + +This module implements connections for MySQLdb. Presently there is +only one class: Connection. Others are unlikely. However, you might +want to make your own subclasses. In most cases, you will probably +override Connection.default_cursor with a non-standard Cursor class. + +""" +from MySQLdb import cursors +from _mysql_exceptions import Warning, Error, InterfaceError, DataError, \ + DatabaseError, OperationalError, IntegrityError, InternalError, \ + NotSupportedError, ProgrammingError +import types, _mysql +import re + + +def defaulterrorhandler(connection, cursor, errorclass, errorvalue): + """ + + If cursor is not None, (errorclass, errorvalue) is appended to + cursor.messages; otherwise it is appended to + connection.messages. Then errorclass is raised with errorvalue as + the value. + + You can override this with your own error handler by assigning it + to the instance. + + """ + error = errorclass, errorvalue + if cursor: + cursor.messages.append(error) + else: + connection.messages.append(error) + del cursor + del connection + raise errorclass, errorvalue + +re_numeric_part = re.compile(r"^(\d+)") + +def numeric_part(s): + """Returns the leading numeric part of a string. + + >>> numeric_part("20-alpha") + 20 + >>> numeric_part("foo") + >>> numeric_part("16b") + 16 + """ + + m = re_numeric_part.match(s) + if m: + return int(m.group(1)) + return None + + +class Connection(_mysql.connection): + + """MySQL Database Connection Object""" + + default_cursor = cursors.Cursor + + def __init__(self, *args, **kwargs): + """ + + Create a connection to the database. It is strongly recommended + that you only use keyword parameters. Consult the MySQL C API + documentation for more information. + + host + string, host to connect + + user + string, user to connect as + + passwd + string, password to use + + db + string, database to use + + port + integer, TCP/IP port to connect to + + unix_socket + string, location of unix_socket to use + + conv + conversion dictionary, see MySQLdb.converters + + connect_timeout + number of seconds to wait before the connection attempt + fails. + + compress + if set, compression is enabled + + named_pipe + if set, a named pipe is used to connect (Windows only) + + init_command + command which is run once the connection is created + + read_default_file + file from which default client values are read + + read_default_group + configuration group to use from the default file + + cursorclass + class object, used to create cursors (keyword only) + + use_unicode + If True, text-like columns are returned as unicode objects + using the connection's character set. Otherwise, text-like + columns are returned as strings. columns are returned as + normal strings. Unicode objects will always be encoded to + the connection's character set regardless of this setting. + + charset + If supplied, the connection character set will be changed + to this character set (MySQL-4.1 and newer). This implies + use_unicode=True. + + sql_mode + If supplied, the session SQL mode will be changed to this + setting (MySQL-4.1 and newer). For more details and legal + values, see the MySQL documentation. + + client_flag + integer, flags to use or 0 + (see MySQL docs or constants/CLIENTS.py) + + ssl + dictionary or mapping, contains SSL connection parameters; + see the MySQL documentation for more details + (mysql_ssl_set()). If this is set, and the client does not + support SSL, NotSupportedError will be raised. + + local_infile + integer, non-zero enables LOAD LOCAL INFILE; zero disables + + autocommit + If False (default), autocommit is disabled. + If True, autocommit is enabled. + If None, autocommit isn't set and server default is used. + + There are a number of undocumented, non-standard methods. See the + documentation for the MySQL C API for some hints on what they do. + + """ + from MySQLdb.constants import CLIENT, FIELD_TYPE + from MySQLdb.converters import conversions + from weakref import proxy + + kwargs2 = kwargs.copy() + + if 'conv' in kwargs: + conv = kwargs['conv'] + else: + conv = conversions + + conv2 = {} + for k, v in conv.items(): + if isinstance(k, int) and isinstance(v, list): + conv2[k] = v[:] + else: + conv2[k] = v + kwargs2['conv'] = conv2 + + cursorclass = kwargs2.pop('cursorclass', self.default_cursor) + charset = kwargs2.pop('charset', '') + + if charset: + use_unicode = True + else: + use_unicode = False + + use_unicode = kwargs2.pop('use_unicode', use_unicode) + sql_mode = kwargs2.pop('sql_mode', '') + + client_flag = kwargs.get('client_flag', 0) + client_version = tuple([ numeric_part(n) for n in _mysql.get_client_info().split('.')[:2] ]) + if client_version >= (4, 1): + client_flag |= CLIENT.MULTI_STATEMENTS + if client_version >= (5, 0): + client_flag |= CLIENT.MULTI_RESULTS + + kwargs2['client_flag'] = client_flag + + # PEP-249 requires autocommit to be initially off + autocommit = kwargs2.pop('autocommit', False) + + super(Connection, self).__init__(*args, **kwargs2) + self.cursorclass = cursorclass + self.encoders = dict([ (k, v) for k, v in conv.items() + if type(k) is not int ]) + + self._server_version = tuple([ numeric_part(n) for n in self.get_server_info().split('.')[:2] ]) + + db = proxy(self) + def _get_string_literal(): + def string_literal(obj, dummy=None): + return db.string_literal(obj) + return string_literal + + def _get_unicode_literal(): + def unicode_literal(u, dummy=None): + return db.literal(u.encode(unicode_literal.charset)) + return unicode_literal + + def _get_string_decoder(): + def string_decoder(s): + return s.decode(string_decoder.charset) + return string_decoder + + string_literal = _get_string_literal() + self.unicode_literal = unicode_literal = _get_unicode_literal() + self.string_decoder = string_decoder = _get_string_decoder() + if not charset: + charset = self.character_set_name() + self.set_character_set(charset) + + if sql_mode: + self.set_sql_mode(sql_mode) + + if use_unicode: + self.converter[FIELD_TYPE.STRING].append((None, string_decoder)) + self.converter[FIELD_TYPE.VAR_STRING].append((None, string_decoder)) + self.converter[FIELD_TYPE.VARCHAR].append((None, string_decoder)) + self.converter[FIELD_TYPE.BLOB].append((None, string_decoder)) + + self.encoders[types.StringType] = string_literal + self.encoders[types.UnicodeType] = unicode_literal + self._transactional = self.server_capabilities & CLIENT.TRANSACTIONS + if self._transactional: + if autocommit is not None: + self.autocommit(autocommit) + self.messages = [] + + def autocommit(self, on): + on = bool(on) + if self.get_autocommit() != on: + _mysql.connection.autocommit(self, on) + + def cursor(self, cursorclass=None): + """ + + Create a cursor on which queries may be performed. The + optional cursorclass parameter is used to create the + Cursor. By default, self.cursorclass=cursors.Cursor is + used. + + """ + return (cursorclass or self.cursorclass)(self) + + def __enter__(self): + if self.get_autocommit(): + self.query("BEGIN") + return self.cursor() + + def __exit__(self, exc, value, tb): + if exc: + self.rollback() + else: + self.commit() + + def literal(self, o): + """ + + If o is a single object, returns an SQL literal as a string. + If o is a non-string sequence, the items of the sequence are + converted and returned as a sequence. + + Non-standard. For internal use; do not use this in your + applications. + + """ + return self.escape(o, self.encoders) + + def begin(self): + """Explicitly begin a connection. Non-standard. + DEPRECATED: Will be removed in 1.3. + Use an SQL BEGIN statement instead.""" + from warnings import warn + warn("begin() is non-standard and will be removed in 1.3", + DeprecationWarning, 2) + self.query("BEGIN") + + if not hasattr(_mysql.connection, 'warning_count'): + + def warning_count(self): + """Return the number of warnings generated from the + last query. This is derived from the info() method.""" + from string import atoi + info = self.info() + if info: + return atoi(info.split()[-1]) + else: + return 0 + + def set_character_set(self, charset): + """Set the connection character set to charset. The character + set can only be changed in MySQL-4.1 and newer. If you try + to change the character set from the current value in an + older version, NotSupportedError will be raised.""" + if charset == "utf8mb4": + py_charset = "utf8" + else: + py_charset = charset + if self.character_set_name() != charset: + try: + super(Connection, self).set_character_set(charset) + except AttributeError: + if self._server_version < (4, 1): + raise NotSupportedError("server is too old to set charset") + self.query('SET NAMES %s' % charset) + self.store_result() + self.string_decoder.charset = py_charset + self.unicode_literal.charset = py_charset + + def set_sql_mode(self, sql_mode): + """Set the connection sql_mode. See MySQL documentation for + legal values.""" + if self._server_version < (4, 1): + raise NotSupportedError("server is too old to set sql_mode") + self.query("SET SESSION sql_mode='%s'" % sql_mode) + self.store_result() + + def show_warnings(self): + """Return detailed information about warnings as a + sequence of tuples of (Level, Code, Message). This + is only supported in MySQL-4.1 and up. If your server + is an earlier version, an empty sequence is returned.""" + if self._server_version < (4,1): return () + self.query("SHOW WARNINGS") + r = self.store_result() + warnings = r.fetch_row(0) + return warnings + + Warning = Warning + Error = Error + InterfaceError = InterfaceError + DatabaseError = DatabaseError + DataError = DataError + OperationalError = OperationalError + IntegrityError = IntegrityError + InternalError = InternalError + ProgrammingError = ProgrammingError + NotSupportedError = NotSupportedError + + errorhandler = defaulterrorhandler diff --git a/lib/mysql/MySQLdb/constants/CLIENT.py b/lib/mysql/MySQLdb/constants/CLIENT.py new file mode 100644 index 00000000..6559917b --- /dev/null +++ b/lib/mysql/MySQLdb/constants/CLIENT.py @@ -0,0 +1,29 @@ +"""MySQL CLIENT constants + +These constants are used when creating the connection. Use bitwise-OR +(|) to combine options together, and pass them as the client_flags +parameter to MySQLdb.Connection. For more information on these flags, +see the MySQL C API documentation for mysql_real_connect(). + +""" + +LONG_PASSWORD = 1 +FOUND_ROWS = 2 +LONG_FLAG = 4 +CONNECT_WITH_DB = 8 +NO_SCHEMA = 16 +COMPRESS = 32 +ODBC = 64 +LOCAL_FILES = 128 +IGNORE_SPACE = 256 +CHANGE_USER = 512 +INTERACTIVE = 1024 +SSL = 2048 +IGNORE_SIGPIPE = 4096 +TRANSACTIONS = 8192 # mysql_com.h was WRONG prior to 3.23.35 +RESERVED = 16384 +SECURE_CONNECTION = 32768 +MULTI_STATEMENTS = 65536 +MULTI_RESULTS = 131072 + + diff --git a/lib/mysql/MySQLdb/constants/CR.py b/lib/mysql/MySQLdb/constants/CR.py new file mode 100644 index 00000000..249dfec9 --- /dev/null +++ b/lib/mysql/MySQLdb/constants/CR.py @@ -0,0 +1,30 @@ +"""MySQL Connection Errors + +Nearly all of these raise OperationalError. COMMANDS_OUT_OF_SYNC +raises ProgrammingError. + +""" + +MIN_ERROR = 2000 +MAX_ERROR = 2999 +UNKNOWN_ERROR = 2000 +SOCKET_CREATE_ERROR = 2001 +CONNECTION_ERROR = 2002 +CONN_HOST_ERROR = 2003 +IPSOCK_ERROR = 2004 +UNKNOWN_HOST = 2005 +SERVER_GONE_ERROR = 2006 +VERSION_ERROR = 2007 +OUT_OF_MEMORY = 2008 +WRONG_HOST_INFO = 2009 +LOCALHOST_CONNECTION = 2010 +TCP_CONNECTION = 2011 +SERVER_HANDSHAKE_ERR = 2012 +SERVER_LOST = 2013 +COMMANDS_OUT_OF_SYNC = 2014 +NAMEDPIPE_CONNECTION = 2015 +NAMEDPIPEWAIT_ERROR = 2016 +NAMEDPIPEOPEN_ERROR = 2017 +NAMEDPIPESETSTATE_ERROR = 2018 +CANT_READ_CHARSET = 2019 +NET_PACKET_TOO_LARGE = 2020 diff --git a/lib/mysql/MySQLdb/constants/ER.py b/lib/mysql/MySQLdb/constants/ER.py new file mode 100644 index 00000000..ed45f3a1 --- /dev/null +++ b/lib/mysql/MySQLdb/constants/ER.py @@ -0,0 +1,467 @@ +"""MySQL ER Constants + +These constants are error codes for the bulk of the error conditions +that may occur. + +""" + +HASHCHK = 1000 +NISAMCHK = 1001 +NO = 1002 +YES = 1003 +CANT_CREATE_FILE = 1004 +CANT_CREATE_TABLE = 1005 +CANT_CREATE_DB = 1006 +DB_CREATE_EXISTS = 1007 +DB_DROP_EXISTS = 1008 +DB_DROP_DELETE = 1009 +DB_DROP_RMDIR = 1010 +CANT_DELETE_FILE = 1011 +CANT_FIND_SYSTEM_REC = 1012 +CANT_GET_STAT = 1013 +CANT_GET_WD = 1014 +CANT_LOCK = 1015 +CANT_OPEN_FILE = 1016 +FILE_NOT_FOUND = 1017 +CANT_READ_DIR = 1018 +CANT_SET_WD = 1019 +CHECKREAD = 1020 +DISK_FULL = 1021 +DUP_KEY = 1022 +ERROR_ON_CLOSE = 1023 +ERROR_ON_READ = 1024 +ERROR_ON_RENAME = 1025 +ERROR_ON_WRITE = 1026 +FILE_USED = 1027 +FILSORT_ABORT = 1028 +FORM_NOT_FOUND = 1029 +GET_ERRNO = 1030 +ILLEGAL_HA = 1031 +KEY_NOT_FOUND = 1032 +NOT_FORM_FILE = 1033 +NOT_KEYFILE = 1034 +OLD_KEYFILE = 1035 +OPEN_AS_READONLY = 1036 +OUTOFMEMORY = 1037 +OUT_OF_SORTMEMORY = 1038 +UNEXPECTED_EOF = 1039 +CON_COUNT_ERROR = 1040 +OUT_OF_RESOURCES = 1041 +BAD_HOST_ERROR = 1042 +HANDSHAKE_ERROR = 1043 +DBACCESS_DENIED_ERROR = 1044 +ACCESS_DENIED_ERROR = 1045 +NO_DB_ERROR = 1046 +UNKNOWN_COM_ERROR = 1047 +BAD_NULL_ERROR = 1048 +BAD_DB_ERROR = 1049 +TABLE_EXISTS_ERROR = 1050 +BAD_TABLE_ERROR = 1051 +NON_UNIQ_ERROR = 1052 +SERVER_SHUTDOWN = 1053 +BAD_FIELD_ERROR = 1054 +WRONG_FIELD_WITH_GROUP = 1055 +WRONG_GROUP_FIELD = 1056 +WRONG_SUM_SELECT = 1057 +WRONG_VALUE_COUNT = 1058 +TOO_LONG_IDENT = 1059 +DUP_FIELDNAME = 1060 +DUP_KEYNAME = 1061 +DUP_ENTRY = 1062 +WRONG_FIELD_SPEC = 1063 +PARSE_ERROR = 1064 +EMPTY_QUERY = 1065 +NONUNIQ_TABLE = 1066 +INVALID_DEFAULT = 1067 +MULTIPLE_PRI_KEY = 1068 +TOO_MANY_KEYS = 1069 +TOO_MANY_KEY_PARTS = 1070 +TOO_LONG_KEY = 1071 +KEY_COLUMN_DOES_NOT_EXITS = 1072 +BLOB_USED_AS_KEY = 1073 +TOO_BIG_FIELDLENGTH = 1074 +WRONG_AUTO_KEY = 1075 +READY = 1076 +NORMAL_SHUTDOWN = 1077 +GOT_SIGNAL = 1078 +SHUTDOWN_COMPLETE = 1079 +FORCING_CLOSE = 1080 +IPSOCK_ERROR = 1081 +NO_SUCH_INDEX = 1082 +WRONG_FIELD_TERMINATORS = 1083 +BLOBS_AND_NO_TERMINATED = 1084 +TEXTFILE_NOT_READABLE = 1085 +FILE_EXISTS_ERROR = 1086 +LOAD_INFO = 1087 +ALTER_INFO = 1088 +WRONG_SUB_KEY = 1089 +CANT_REMOVE_ALL_FIELDS = 1090 +CANT_DROP_FIELD_OR_KEY = 1091 +INSERT_INFO = 1092 +INSERT_TABLE_USED = 1093 +NO_SUCH_THREAD = 1094 +KILL_DENIED_ERROR = 1095 +NO_TABLES_USED = 1096 +TOO_BIG_SET = 1097 +NO_UNIQUE_LOGFILE = 1098 +TABLE_NOT_LOCKED_FOR_WRITE = 1099 +TABLE_NOT_LOCKED = 1100 +BLOB_CANT_HAVE_DEFAULT = 1101 +WRONG_DB_NAME = 1102 +WRONG_TABLE_NAME = 1103 +TOO_BIG_SELECT = 1104 +UNKNOWN_ERROR = 1105 +UNKNOWN_PROCEDURE = 1106 +WRONG_PARAMCOUNT_TO_PROCEDURE = 1107 +WRONG_PARAMETERS_TO_PROCEDURE = 1108 +UNKNOWN_TABLE = 1109 +FIELD_SPECIFIED_TWICE = 1110 +INVALID_GROUP_FUNC_USE = 1111 +UNSUPPORTED_EXTENSION = 1112 +TABLE_MUST_HAVE_COLUMNS = 1113 +RECORD_FILE_FULL = 1114 +UNKNOWN_CHARACTER_SET = 1115 +TOO_MANY_TABLES = 1116 +TOO_MANY_FIELDS = 1117 +TOO_BIG_ROWSIZE = 1118 +STACK_OVERRUN = 1119 +WRONG_OUTER_JOIN = 1120 +NULL_COLUMN_IN_INDEX = 1121 +CANT_FIND_UDF = 1122 +CANT_INITIALIZE_UDF = 1123 +UDF_NO_PATHS = 1124 +UDF_EXISTS = 1125 +CANT_OPEN_LIBRARY = 1126 +CANT_FIND_DL_ENTRY = 1127 +FUNCTION_NOT_DEFINED = 1128 +HOST_IS_BLOCKED = 1129 +HOST_NOT_PRIVILEGED = 1130 +PASSWORD_ANONYMOUS_USER = 1131 +PASSWORD_NOT_ALLOWED = 1132 +PASSWORD_NO_MATCH = 1133 +UPDATE_INFO = 1134 +CANT_CREATE_THREAD = 1135 +WRONG_VALUE_COUNT_ON_ROW = 1136 +CANT_REOPEN_TABLE = 1137 +INVALID_USE_OF_NULL = 1138 +REGEXP_ERROR = 1139 +MIX_OF_GROUP_FUNC_AND_FIELDS = 1140 +NONEXISTING_GRANT = 1141 +TABLEACCESS_DENIED_ERROR = 1142 +COLUMNACCESS_DENIED_ERROR = 1143 +ILLEGAL_GRANT_FOR_TABLE = 1144 +GRANT_WRONG_HOST_OR_USER = 1145 +NO_SUCH_TABLE = 1146 +NONEXISTING_TABLE_GRANT = 1147 +NOT_ALLOWED_COMMAND = 1148 +SYNTAX_ERROR = 1149 +DELAYED_CANT_CHANGE_LOCK = 1150 +TOO_MANY_DELAYED_THREADS = 1151 +ABORTING_CONNECTION = 1152 +NET_PACKET_TOO_LARGE = 1153 +NET_READ_ERROR_FROM_PIPE = 1154 +NET_FCNTL_ERROR = 1155 +NET_PACKETS_OUT_OF_ORDER = 1156 +NET_UNCOMPRESS_ERROR = 1157 +NET_READ_ERROR = 1158 +NET_READ_INTERRUPTED = 1159 +NET_ERROR_ON_WRITE = 1160 +NET_WRITE_INTERRUPTED = 1161 +TOO_LONG_STRING = 1162 +TABLE_CANT_HANDLE_BLOB = 1163 +TABLE_CANT_HANDLE_AUTO_INCREMENT = 1164 +DELAYED_INSERT_TABLE_LOCKED = 1165 +WRONG_COLUMN_NAME = 1166 +WRONG_KEY_COLUMN = 1167 +WRONG_MRG_TABLE = 1168 +DUP_UNIQUE = 1169 +BLOB_KEY_WITHOUT_LENGTH = 1170 +PRIMARY_CANT_HAVE_NULL = 1171 +TOO_MANY_ROWS = 1172 +REQUIRES_PRIMARY_KEY = 1173 +NO_RAID_COMPILED = 1174 +UPDATE_WITHOUT_KEY_IN_SAFE_MODE = 1175 +KEY_DOES_NOT_EXITS = 1176 +CHECK_NO_SUCH_TABLE = 1177 +CHECK_NOT_IMPLEMENTED = 1178 +CANT_DO_THIS_DURING_AN_TRANSACTION = 1179 +ERROR_DURING_COMMIT = 1180 +ERROR_DURING_ROLLBACK = 1181 +ERROR_DURING_FLUSH_LOGS = 1182 +ERROR_DURING_CHECKPOINT = 1183 +NEW_ABORTING_CONNECTION = 1184 +DUMP_NOT_IMPLEMENTED = 1185 +FLUSH_MASTER_BINLOG_CLOSED = 1186 +INDEX_REBUILD = 1187 +MASTER = 1188 +MASTER_NET_READ = 1189 +MASTER_NET_WRITE = 1190 +FT_MATCHING_KEY_NOT_FOUND = 1191 +LOCK_OR_ACTIVE_TRANSACTION = 1192 +UNKNOWN_SYSTEM_VARIABLE = 1193 +CRASHED_ON_USAGE = 1194 +CRASHED_ON_REPAIR = 1195 +WARNING_NOT_COMPLETE_ROLLBACK = 1196 +TRANS_CACHE_FULL = 1197 +SLAVE_MUST_STOP = 1198 +SLAVE_NOT_RUNNING = 1199 +BAD_SLAVE = 1200 +MASTER_INFO = 1201 +SLAVE_THREAD = 1202 +TOO_MANY_USER_CONNECTIONS = 1203 +SET_CONSTANTS_ONLY = 1204 +LOCK_WAIT_TIMEOUT = 1205 +LOCK_TABLE_FULL = 1206 +READ_ONLY_TRANSACTION = 1207 +DROP_DB_WITH_READ_LOCK = 1208 +CREATE_DB_WITH_READ_LOCK = 1209 +WRONG_ARGUMENTS = 1210 +NO_PERMISSION_TO_CREATE_USER = 1211 +UNION_TABLES_IN_DIFFERENT_DIR = 1212 +LOCK_DEADLOCK = 1213 +TABLE_CANT_HANDLE_FT = 1214 +CANNOT_ADD_FOREIGN = 1215 +NO_REFERENCED_ROW = 1216 +ROW_IS_REFERENCED = 1217 +CONNECT_TO_MASTER = 1218 +QUERY_ON_MASTER = 1219 +ERROR_WHEN_EXECUTING_COMMAND = 1220 +WRONG_USAGE = 1221 +WRONG_NUMBER_OF_COLUMNS_IN_SELECT = 1222 +CANT_UPDATE_WITH_READLOCK = 1223 +MIXING_NOT_ALLOWED = 1224 +DUP_ARGUMENT = 1225 +USER_LIMIT_REACHED = 1226 +SPECIFIC_ACCESS_DENIED_ERROR = 1227 +LOCAL_VARIABLE = 1228 +GLOBAL_VARIABLE = 1229 +NO_DEFAULT = 1230 +WRONG_VALUE_FOR_VAR = 1231 +WRONG_TYPE_FOR_VAR = 1232 +VAR_CANT_BE_READ = 1233 +CANT_USE_OPTION_HERE = 1234 +NOT_SUPPORTED_YET = 1235 +MASTER_FATAL_ERROR_READING_BINLOG = 1236 +SLAVE_IGNORED_TABLE = 1237 +INCORRECT_GLOBAL_LOCAL_VAR = 1238 +WRONG_FK_DEF = 1239 +KEY_REF_DO_NOT_MATCH_TABLE_REF = 1240 +OPERAND_COLUMNS = 1241 +SUBQUERY_NO_1_ROW = 1242 +UNKNOWN_STMT_HANDLER = 1243 +CORRUPT_HELP_DB = 1244 +CYCLIC_REFERENCE = 1245 +AUTO_CONVERT = 1246 +ILLEGAL_REFERENCE = 1247 +DERIVED_MUST_HAVE_ALIAS = 1248 +SELECT_REDUCED = 1249 +TABLENAME_NOT_ALLOWED_HERE = 1250 +NOT_SUPPORTED_AUTH_MODE = 1251 +SPATIAL_CANT_HAVE_NULL = 1252 +COLLATION_CHARSET_MISMATCH = 1253 +SLAVE_WAS_RUNNING = 1254 +SLAVE_WAS_NOT_RUNNING = 1255 +TOO_BIG_FOR_UNCOMPRESS = 1256 +ZLIB_Z_MEM_ERROR = 1257 +ZLIB_Z_BUF_ERROR = 1258 +ZLIB_Z_DATA_ERROR = 1259 +CUT_VALUE_GROUP_CONCAT = 1260 +WARN_TOO_FEW_RECORDS = 1261 +WARN_TOO_MANY_RECORDS = 1262 +WARN_NULL_TO_NOTNULL = 1263 +WARN_DATA_OUT_OF_RANGE = 1264 +WARN_DATA_TRUNCATED = 1265 +WARN_USING_OTHER_HANDLER = 1266 +CANT_AGGREGATE_2COLLATIONS = 1267 +DROP_USER = 1268 +REVOKE_GRANTS = 1269 +CANT_AGGREGATE_3COLLATIONS = 1270 +CANT_AGGREGATE_NCOLLATIONS = 1271 +VARIABLE_IS_NOT_STRUCT = 1272 +UNKNOWN_COLLATION = 1273 +SLAVE_IGNORED_SSL_PARAMS = 1274 +SERVER_IS_IN_SECURE_AUTH_MODE = 1275 +WARN_FIELD_RESOLVED = 1276 +BAD_SLAVE_UNTIL_COND = 1277 +MISSING_SKIP_SLAVE = 1278 +UNTIL_COND_IGNORED = 1279 +WRONG_NAME_FOR_INDEX = 1280 +WRONG_NAME_FOR_CATALOG = 1281 +WARN_QC_RESIZE = 1282 +BAD_FT_COLUMN = 1283 +UNKNOWN_KEY_CACHE = 1284 +WARN_HOSTNAME_WONT_WORK = 1285 +UNKNOWN_STORAGE_ENGINE = 1286 +WARN_DEPRECATED_SYNTAX = 1287 +NON_UPDATABLE_TABLE = 1288 +FEATURE_DISABLED = 1289 +OPTION_PREVENTS_STATEMENT = 1290 +DUPLICATED_VALUE_IN_TYPE = 1291 +TRUNCATED_WRONG_VALUE = 1292 +TOO_MUCH_AUTO_TIMESTAMP_COLS = 1293 +INVALID_ON_UPDATE = 1294 +UNSUPPORTED_PS = 1295 +GET_ERRMSG = 1296 +GET_TEMPORARY_ERRMSG = 1297 +UNKNOWN_TIME_ZONE = 1298 +WARN_INVALID_TIMESTAMP = 1299 +INVALID_CHARACTER_STRING = 1300 +WARN_ALLOWED_PACKET_OVERFLOWED = 1301 +CONFLICTING_DECLARATIONS = 1302 +SP_NO_RECURSIVE_CREATE = 1303 +SP_ALREADY_EXISTS = 1304 +SP_DOES_NOT_EXIST = 1305 +SP_DROP_FAILED = 1306 +SP_STORE_FAILED = 1307 +SP_LILABEL_MISMATCH = 1308 +SP_LABEL_REDEFINE = 1309 +SP_LABEL_MISMATCH = 1310 +SP_UNINIT_VAR = 1311 +SP_BADSELECT = 1312 +SP_BADRETURN = 1313 +SP_BADSTATEMENT = 1314 +UPDATE_LOG_DEPRECATED_IGNORED = 1315 +UPDATE_LOG_DEPRECATED_TRANSLATED = 1316 +QUERY_INTERRUPTED = 1317 +SP_WRONG_NO_OF_ARGS = 1318 +SP_COND_MISMATCH = 1319 +SP_NORETURN = 1320 +SP_NORETURNEND = 1321 +SP_BAD_CURSOR_QUERY = 1322 +SP_BAD_CURSOR_SELECT = 1323 +SP_CURSOR_MISMATCH = 1324 +SP_CURSOR_ALREADY_OPEN = 1325 +SP_CURSOR_NOT_OPEN = 1326 +SP_UNDECLARED_VAR = 1327 +SP_WRONG_NO_OF_FETCH_ARGS = 1328 +SP_FETCH_NO_DATA = 1329 +SP_DUP_PARAM = 1330 +SP_DUP_VAR = 1331 +SP_DUP_COND = 1332 +SP_DUP_CURS = 1333 +SP_CANT_ALTER = 1334 +SP_SUBSELECT_NYI = 1335 +STMT_NOT_ALLOWED_IN_SF_OR_TRG = 1336 +SP_VARCOND_AFTER_CURSHNDLR = 1337 +SP_CURSOR_AFTER_HANDLER = 1338 +SP_CASE_NOT_FOUND = 1339 +FPARSER_TOO_BIG_FILE = 1340 +FPARSER_BAD_HEADER = 1341 +FPARSER_EOF_IN_COMMENT = 1342 +FPARSER_ERROR_IN_PARAMETER = 1343 +FPARSER_EOF_IN_UNKNOWN_PARAMETER = 1344 +VIEW_NO_EXPLAIN = 1345 +FRM_UNKNOWN_TYPE = 1346 +WRONG_OBJECT = 1347 +NONUPDATEABLE_COLUMN = 1348 +VIEW_SELECT_DERIVED = 1349 +VIEW_SELECT_CLAUSE = 1350 +VIEW_SELECT_VARIABLE = 1351 +VIEW_SELECT_TMPTABLE = 1352 +VIEW_WRONG_LIST = 1353 +WARN_VIEW_MERGE = 1354 +WARN_VIEW_WITHOUT_KEY = 1355 +VIEW_INVALID = 1356 +SP_NO_DROP_SP = 1357 +SP_GOTO_IN_HNDLR = 1358 +TRG_ALREADY_EXISTS = 1359 +TRG_DOES_NOT_EXIST = 1360 +TRG_ON_VIEW_OR_TEMP_TABLE = 1361 +TRG_CANT_CHANGE_ROW = 1362 +TRG_NO_SUCH_ROW_IN_TRG = 1363 +NO_DEFAULT_FOR_FIELD = 1364 +DIVISION_BY_ZERO = 1365 +TRUNCATED_WRONG_VALUE_FOR_FIELD = 1366 +ILLEGAL_VALUE_FOR_TYPE = 1367 +VIEW_NONUPD_CHECK = 1368 +VIEW_CHECK_FAILED = 1369 +PROCACCESS_DENIED_ERROR = 1370 +RELAY_LOG_FAIL = 1371 +PASSWD_LENGTH = 1372 +UNKNOWN_TARGET_BINLOG = 1373 +IO_ERR_LOG_INDEX_READ = 1374 +BINLOG_PURGE_PROHIBITED = 1375 +FSEEK_FAIL = 1376 +BINLOG_PURGE_FATAL_ERR = 1377 +LOG_IN_USE = 1378 +LOG_PURGE_UNKNOWN_ERR = 1379 +RELAY_LOG_INIT = 1380 +NO_BINARY_LOGGING = 1381 +RESERVED_SYNTAX = 1382 +WSAS_FAILED = 1383 +DIFF_GROUPS_PROC = 1384 +NO_GROUP_FOR_PROC = 1385 +ORDER_WITH_PROC = 1386 +LOGGING_PROHIBIT_CHANGING_OF = 1387 +NO_FILE_MAPPING = 1388 +WRONG_MAGIC = 1389 +PS_MANY_PARAM = 1390 +KEY_PART_0 = 1391 +VIEW_CHECKSUM = 1392 +VIEW_MULTIUPDATE = 1393 +VIEW_NO_INSERT_FIELD_LIST = 1394 +VIEW_DELETE_MERGE_VIEW = 1395 +CANNOT_USER = 1396 +XAER_NOTA = 1397 +XAER_INVAL = 1398 +XAER_RMFAIL = 1399 +XAER_OUTSIDE = 1400 +XAER_RMERR = 1401 +XA_RBROLLBACK = 1402 +NONEXISTING_PROC_GRANT = 1403 +PROC_AUTO_GRANT_FAIL = 1404 +PROC_AUTO_REVOKE_FAIL = 1405 +DATA_TOO_LONG = 1406 +SP_BAD_SQLSTATE = 1407 +STARTUP = 1408 +LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR = 1409 +CANT_CREATE_USER_WITH_GRANT = 1410 +WRONG_VALUE_FOR_TYPE = 1411 +TABLE_DEF_CHANGED = 1412 +SP_DUP_HANDLER = 1413 +SP_NOT_VAR_ARG = 1414 +SP_NO_RETSET = 1415 +CANT_CREATE_GEOMETRY_OBJECT = 1416 +FAILED_ROUTINE_BREAK_BINLOG = 1417 +BINLOG_UNSAFE_ROUTINE = 1418 +BINLOG_CREATE_ROUTINE_NEED_SUPER = 1419 +EXEC_STMT_WITH_OPEN_CURSOR = 1420 +STMT_HAS_NO_OPEN_CURSOR = 1421 +COMMIT_NOT_ALLOWED_IN_SF_OR_TRG = 1422 +NO_DEFAULT_FOR_VIEW_FIELD = 1423 +SP_NO_RECURSION = 1424 +TOO_BIG_SCALE = 1425 +TOO_BIG_PRECISION = 1426 +M_BIGGER_THAN_D = 1427 +WRONG_LOCK_OF_SYSTEM_TABLE = 1428 +CONNECT_TO_FOREIGN_DATA_SOURCE = 1429 +QUERY_ON_FOREIGN_DATA_SOURCE = 1430 +FOREIGN_DATA_SOURCE_DOESNT_EXIST = 1431 +FOREIGN_DATA_STRING_INVALID_CANT_CREATE = 1432 +FOREIGN_DATA_STRING_INVALID = 1433 +CANT_CREATE_FEDERATED_TABLE = 1434 +TRG_IN_WRONG_SCHEMA = 1435 +STACK_OVERRUN_NEED_MORE = 1436 +TOO_LONG_BODY = 1437 +WARN_CANT_DROP_DEFAULT_KEYCACHE = 1438 +TOO_BIG_DISPLAYWIDTH = 1439 +XAER_DUPID = 1440 +DATETIME_FUNCTION_OVERFLOW = 1441 +CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG = 1442 +VIEW_PREVENT_UPDATE = 1443 +PS_NO_RECURSION = 1444 +SP_CANT_SET_AUTOCOMMIT = 1445 +MALFORMED_DEFINER = 1446 +VIEW_FRM_NO_USER = 1447 +VIEW_OTHER_USER = 1448 +NO_SUCH_USER = 1449 +FORBID_SCHEMA_CHANGE = 1450 +ROW_IS_REFERENCED_2 = 1451 +NO_REFERENCED_ROW_2 = 1452 +SP_BAD_VAR_SHADOW = 1453 +TRG_NO_DEFINER = 1454 +OLD_FILE_FORMAT = 1455 +SP_RECURSION_LIMIT = 1456 +SP_PROC_TABLE_CORRUPT = 1457 +ERROR_LAST = 1457 + diff --git a/lib/mysql/MySQLdb/constants/FIELD_TYPE.py b/lib/mysql/MySQLdb/constants/FIELD_TYPE.py new file mode 100644 index 00000000..8a57b171 --- /dev/null +++ b/lib/mysql/MySQLdb/constants/FIELD_TYPE.py @@ -0,0 +1,37 @@ +"""MySQL FIELD_TYPE Constants + +These constants represent the various column (field) types that are +supported by MySQL. + +""" + +DECIMAL = 0 +TINY = 1 +SHORT = 2 +LONG = 3 +FLOAT = 4 +DOUBLE = 5 +NULL = 6 +TIMESTAMP = 7 +LONGLONG = 8 +INT24 = 9 +DATE = 10 +TIME = 11 +DATETIME = 12 +YEAR = 13 +NEWDATE = 14 +VARCHAR = 15 +BIT = 16 +NEWDECIMAL = 246 +ENUM = 247 +SET = 248 +TINY_BLOB = 249 +MEDIUM_BLOB = 250 +LONG_BLOB = 251 +BLOB = 252 +VAR_STRING = 253 +STRING = 254 +GEOMETRY = 255 + +CHAR = TINY +INTERVAL = ENUM diff --git a/lib/mysql/MySQLdb/constants/FLAG.py b/lib/mysql/MySQLdb/constants/FLAG.py new file mode 100644 index 00000000..00e6c7c0 --- /dev/null +++ b/lib/mysql/MySQLdb/constants/FLAG.py @@ -0,0 +1,23 @@ +"""MySQL FLAG Constants + +These flags are used along with the FIELD_TYPE to indicate various +properties of columns in a result set. + +""" + +NOT_NULL = 1 +PRI_KEY = 2 +UNIQUE_KEY = 4 +MULTIPLE_KEY = 8 +BLOB = 16 +UNSIGNED = 32 +ZEROFILL = 64 +BINARY = 128 +ENUM = 256 +AUTO_INCREMENT = 512 +TIMESTAMP = 1024 +SET = 2048 +NUM = 32768 +PART_KEY = 16384 +GROUP = 32768 +UNIQUE = 65536 diff --git a/lib/mysql/MySQLdb/constants/REFRESH.py b/lib/mysql/MySQLdb/constants/REFRESH.py new file mode 100644 index 00000000..4a08b94e --- /dev/null +++ b/lib/mysql/MySQLdb/constants/REFRESH.py @@ -0,0 +1,17 @@ +"""MySQL REFRESH Constants + +These constants seem to mostly deal with things internal to the +MySQL server. Forget you saw this. + +""" + +GRANT = 1 +LOG = 2 +TABLES = 4 +HOSTS = 8 +STATUS = 16 +THREADS = 32 +SLAVE = 64 +MASTER = 128 +READ_LOCK = 16384 +FAST = 32768 diff --git a/lib/mysql/MySQLdb/constants/__init__.py b/lib/mysql/MySQLdb/constants/__init__.py new file mode 100644 index 00000000..3da4a0e7 --- /dev/null +++ b/lib/mysql/MySQLdb/constants/__init__.py @@ -0,0 +1 @@ +__all__ = ['CR', 'FIELD_TYPE','CLIENT','REFRESH','ER','FLAG'] diff --git a/lib/mysql/MySQLdb/converters.py b/lib/mysql/MySQLdb/converters.py new file mode 100644 index 00000000..35b9d0b1 --- /dev/null +++ b/lib/mysql/MySQLdb/converters.py @@ -0,0 +1,189 @@ +"""MySQLdb type conversion module + +This module handles all the type conversions for MySQL. If the default +type conversions aren't what you need, you can make your own. The +dictionary conversions maps some kind of type to a conversion function +which returns the corresponding value: + +Key: FIELD_TYPE.* (from MySQLdb.constants) + +Conversion function: + + Arguments: string + + Returns: Python object + +Key: Python type object (from types) or class + +Conversion function: + + Arguments: Python object of indicated type or class AND + conversion dictionary + + Returns: SQL literal value + + Notes: Most conversion functions can ignore the dictionary, but + it is a required parameter. It is necessary for converting + things like sequences and instances. + +Don't modify conversions if you can avoid it. Instead, make copies +(with the copy() method), modify the copies, and then pass them to +MySQL.connect(). + +""" + +from _mysql import string_literal, escape_sequence, escape_dict, escape, NULL +from MySQLdb.constants import FIELD_TYPE, FLAG +from MySQLdb.times import * + +try: + from types import IntType, LongType, FloatType, NoneType, TupleType, ListType, DictType, InstanceType, \ + StringType, UnicodeType, ObjectType, BooleanType, ClassType, TypeType +except ImportError: + # Python 3 + long = int + IntType, LongType, FloatType, NoneType = int, long, float, type(None) + TupleType, ListType, DictType, InstanceType = tuple, list, dict, None + StringType, UnicodeType, ObjectType, BooleanType = bytes, str, object, bool + +import array + +try: + ArrayType = array.ArrayType +except AttributeError: + ArrayType = array.array + +try: + set +except NameError: + from sets import Set as set + +def Bool2Str(s, d): return str(int(s)) + +def Str2Set(s): + return set([ i for i in s.split(',') if i ]) + +def Set2Str(s, d): + return string_literal(','.join(s), d) + +def Thing2Str(s, d): + """Convert something into a string via str().""" + return str(s) + +def Unicode2Str(s, d): + """Convert a unicode object to a string using the default encoding. + This is only used as a placeholder for the real function, which + is connection-dependent.""" + return s.encode() + +Long2Int = Thing2Str + +def Float2Str(o, d): + return '%.15g' % o + +def None2NULL(o, d): + """Convert None to NULL.""" + return NULL # duh + +def Thing2Literal(o, d): + + """Convert something into a SQL string literal. If using + MySQL-3.23 or newer, string_literal() is a method of the + _mysql.MYSQL object, and this function will be overridden with + that method when the connection is created.""" + + return string_literal(o, d) + + +def Instance2Str(o, d): + + """ + + Convert an Instance to a string representation. If the __str__() + method produces acceptable output, then you don't need to add the + class to conversions; it will be handled by the default + converter. If the exact class is not found in d, it will use the + first class it can find for which o is an instance. + + """ + + if o.__class__ in d: + return d[o.__class__](o, d) + cl = filter(lambda x,o=o: + type(x) is ClassType + and isinstance(o, x), d.keys()) + if not cl: + cl = filter(lambda x,o=o: + type(x) is TypeType + and isinstance(o, x) + and d[x] is not Instance2Str, + d.keys()) + if not cl: + return d[StringType](o,d) + d[o.__class__] = d[cl[0]] + return d[cl[0]](o, d) + +def char_array(s): + return array.array('c', s) + +def array2Str(o, d): + return Thing2Literal(o.tostring(), d) + +def quote_tuple(t, d): + return "(%s)" % (','.join(escape_sequence(t, d))) + +conversions = { + IntType: Thing2Str, + LongType: Long2Int, + FloatType: Float2Str, + NoneType: None2NULL, + TupleType: quote_tuple, + ListType: quote_tuple, + DictType: escape_dict, + InstanceType: Instance2Str, + ArrayType: array2Str, + StringType: Thing2Literal, # default + UnicodeType: Unicode2Str, + ObjectType: Instance2Str, + BooleanType: Bool2Str, + DateTimeType: DateTime2literal, + DateTimeDeltaType: DateTimeDelta2literal, + set: Set2Str, + FIELD_TYPE.TINY: int, + FIELD_TYPE.SHORT: int, + FIELD_TYPE.LONG: long, + FIELD_TYPE.FLOAT: float, + FIELD_TYPE.DOUBLE: float, + FIELD_TYPE.DECIMAL: float, + FIELD_TYPE.NEWDECIMAL: float, + FIELD_TYPE.LONGLONG: long, + FIELD_TYPE.INT24: int, + FIELD_TYPE.YEAR: int, + FIELD_TYPE.SET: Str2Set, + FIELD_TYPE.TIMESTAMP: mysql_timestamp_converter, + FIELD_TYPE.DATETIME: DateTime_or_None, + FIELD_TYPE.TIME: TimeDelta_or_None, + FIELD_TYPE.DATE: Date_or_None, + FIELD_TYPE.BLOB: [ + (FLAG.BINARY, str), + ], + FIELD_TYPE.STRING: [ + (FLAG.BINARY, str), + ], + FIELD_TYPE.VAR_STRING: [ + (FLAG.BINARY, str), + ], + FIELD_TYPE.VARCHAR: [ + (FLAG.BINARY, str), + ], + } + +try: + from decimal import Decimal + conversions[FIELD_TYPE.DECIMAL] = Decimal + conversions[FIELD_TYPE.NEWDECIMAL] = Decimal +except ImportError: + pass + + + diff --git a/lib/mysql/MySQLdb/cursors.py b/lib/mysql/MySQLdb/cursors.py new file mode 100644 index 00000000..e32cf388 --- /dev/null +++ b/lib/mysql/MySQLdb/cursors.py @@ -0,0 +1,541 @@ +"""MySQLdb Cursors + +This module implements Cursors of various types for MySQLdb. By +default, MySQLdb uses the Cursor class. + +""" + +import re +import sys +try: + from types import ListType, TupleType, UnicodeType +except ImportError: + # Python 3 + ListType = list + TupleType = tuple + UnicodeType = str + +restr = r""" + \s + values + \s* + ( + \( + [^()']* + (?: + (?: + (?:\( + # ( - editor hightlighting helper + .* + \)) + | + ' + [^\\']* + (?:\\.[^\\']*)* + ' + ) + [^()']* + )* + \) + ) +""" + +insert_values = re.compile(restr, re.S | re.I | re.X) + +from _mysql_exceptions import Warning, Error, InterfaceError, DataError, \ + DatabaseError, OperationalError, IntegrityError, InternalError, \ + NotSupportedError, ProgrammingError + + +class BaseCursor(object): + + """A base for Cursor classes. Useful attributes: + + description + A tuple of DB API 7-tuples describing the columns in + the last executed query; see PEP-249 for details. + + description_flags + Tuple of column flags for last query, one entry per column + in the result set. Values correspond to those in + MySQLdb.constants.FLAG. See MySQL documentation (C API) + for more information. Non-standard extension. + + arraysize + default number of rows fetchmany() will fetch + + """ + + from _mysql_exceptions import MySQLError, Warning, Error, InterfaceError, \ + DatabaseError, DataError, OperationalError, IntegrityError, \ + InternalError, ProgrammingError, NotSupportedError + + _defer_warnings = False + + def __init__(self, connection): + from weakref import proxy + + self.connection = proxy(connection) + self.description = None + self.description_flags = None + self.rowcount = -1 + self.arraysize = 1 + self._executed = None + self.lastrowid = None + self.messages = [] + self.errorhandler = connection.errorhandler + self._result = None + self._warnings = 0 + self._info = None + self.rownumber = None + + def __del__(self): + self.close() + self.errorhandler = None + self._result = None + + def close(self): + """Close the cursor. No further queries will be possible.""" + if not self.connection: return + while self.nextset(): pass + self.connection = None + + def _check_executed(self): + if not self._executed: + self.errorhandler(self, ProgrammingError, "execute() first") + + def _warning_check(self): + from warnings import warn + if self._warnings: + warnings = self._get_db().show_warnings() + if warnings: + # This is done in two loops in case + # Warnings are set to raise exceptions. + for w in warnings: + self.messages.append((self.Warning, w)) + for w in warnings: + warn(w[-1], self.Warning, 3) + elif self._info: + self.messages.append((self.Warning, self._info)) + warn(self._info, self.Warning, 3) + + def nextset(self): + """Advance to the next result set. + + Returns None if there are no more result sets. + """ + if self._executed: + self.fetchall() + del self.messages[:] + + db = self._get_db() + nr = db.next_result() + if nr == -1: + return None + self._do_get_result() + self._post_get_result() + self._warning_check() + return 1 + + def _post_get_result(self): pass + + def _do_get_result(self): + db = self._get_db() + self._result = self._get_result() + self.rowcount = db.affected_rows() + self.rownumber = 0 + self.description = self._result and self._result.describe() or None + self.description_flags = self._result and self._result.field_flags() or None + self.lastrowid = db.insert_id() + self._warnings = db.warning_count() + self._info = db.info() + + def setinputsizes(self, *args): + """Does nothing, required by DB API.""" + + def setoutputsizes(self, *args): + """Does nothing, required by DB API.""" + + def _get_db(self): + if not self.connection: + self.errorhandler(self, ProgrammingError, "cursor closed") + return self.connection + + def execute(self, query, args=None): + + """Execute a query. + + query -- string, query to execute on server + args -- optional sequence or mapping, parameters to use with query. + + Note: If args is a sequence, then %s must be used as the + parameter placeholder in the query. If a mapping is used, + %(key)s must be used as the placeholder. + + Returns long integer rows affected, if any + + """ + del self.messages[:] + db = self._get_db() + if isinstance(query, unicode): + query = query.encode(db.unicode_literal.charset) + if args is not None: + if isinstance(args, dict): + query = query % dict((key, db.literal(item)) + for key, item in args.iteritems()) + else: + query = query % tuple([db.literal(item) for item in args]) + try: + r = None + r = self._query(query) + except TypeError, m: + if m.args[0] in ("not enough arguments for format string", + "not all arguments converted"): + self.messages.append((ProgrammingError, m.args[0])) + self.errorhandler(self, ProgrammingError, m.args[0]) + else: + self.messages.append((TypeError, m)) + self.errorhandler(self, TypeError, m) + except (SystemExit, KeyboardInterrupt): + raise + except: + exc, value, tb = sys.exc_info() + del tb + self.messages.append((exc, value)) + self.errorhandler(self, exc, value) + self._executed = query + if not self._defer_warnings: self._warning_check() + return r + + def executemany(self, query, args): + + """Execute a multi-row query. + + query -- string, query to execute on server + + args + + Sequence of sequences or mappings, parameters to use with + query. + + Returns long integer rows affected, if any. + + This method improves performance on multiple-row INSERT and + REPLACE. Otherwise it is equivalent to looping over args with + execute(). + + """ + del self.messages[:] + db = self._get_db() + if not args: return + if isinstance(query, unicode): + query = query.encode(db.unicode_literal.charset) + m = insert_values.search(query) + if not m: + r = 0 + for a in args: + r = r + self.execute(query, a) + return r + p = m.start(1) + e = m.end(1) + qv = m.group(1) + try: + q = [] + for a in args: + if isinstance(a, dict): + q.append(qv % dict((key, db.literal(item)) + for key, item in a.iteritems())) + else: + q.append(qv % tuple([db.literal(item) for item in a])) + except TypeError, msg: + if msg.args[0] in ("not enough arguments for format string", + "not all arguments converted"): + self.errorhandler(self, ProgrammingError, msg.args[0]) + else: + self.errorhandler(self, TypeError, msg) + except (SystemExit, KeyboardInterrupt): + raise + except: + exc, value, tb = sys.exc_info() + del tb + self.errorhandler(self, exc, value) + r = self._query('\n'.join([query[:p], ',\n'.join(q), query[e:]])) + if not self._defer_warnings: self._warning_check() + return r + + def callproc(self, procname, args=()): + + """Execute stored procedure procname with args + + procname -- string, name of procedure to execute on server + + args -- Sequence of parameters to use with procedure + + Returns the original args. + + Compatibility warning: PEP-249 specifies that any modified + parameters must be returned. This is currently impossible + as they are only available by storing them in a server + variable and then retrieved by a query. Since stored + procedures return zero or more result sets, there is no + reliable way to get at OUT or INOUT parameters via callproc. + The server variables are named @_procname_n, where procname + is the parameter above and n is the position of the parameter + (from zero). Once all result sets generated by the procedure + have been fetched, you can issue a SELECT @_procname_0, ... + query using .execute() to get any OUT or INOUT values. + + Compatibility warning: The act of calling a stored procedure + itself creates an empty result set. This appears after any + result sets generated by the procedure. This is non-standard + behavior with respect to the DB-API. Be sure to use nextset() + to advance through all result sets; otherwise you may get + disconnected. + """ + + db = self._get_db() + for index, arg in enumerate(args): + q = "SET @_%s_%d=%s" % (procname, index, + db.literal(arg)) + if isinstance(q, unicode): + q = q.encode(db.unicode_literal.charset) + self._query(q) + self.nextset() + + q = "CALL %s(%s)" % (procname, + ','.join(['@_%s_%d' % (procname, i) + for i in range(len(args))])) + if type(q) is UnicodeType: + q = q.encode(db.unicode_literal.charset) + self._query(q) + self._executed = q + if not self._defer_warnings: self._warning_check() + return args + + def _do_query(self, q): + db = self._get_db() + self._last_executed = q + db.query(q) + self._do_get_result() + return self.rowcount + + def _query(self, q): return self._do_query(q) + + def _fetch_row(self, size=1): + if not self._result: + return () + return self._result.fetch_row(size, self._fetch_type) + + def __iter__(self): + return iter(self.fetchone, None) + + Warning = Warning + Error = Error + InterfaceError = InterfaceError + DatabaseError = DatabaseError + DataError = DataError + OperationalError = OperationalError + IntegrityError = IntegrityError + InternalError = InternalError + ProgrammingError = ProgrammingError + NotSupportedError = NotSupportedError + + +class CursorStoreResultMixIn(object): + + """This is a MixIn class which causes the entire result set to be + stored on the client side, i.e. it uses mysql_store_result(). If the + result set can be very large, consider adding a LIMIT clause to your + query, or using CursorUseResultMixIn instead.""" + + def _get_result(self): return self._get_db().store_result() + + def _query(self, q): + rowcount = self._do_query(q) + self._post_get_result() + return rowcount + + def _post_get_result(self): + self._rows = self._fetch_row(0) + self._result = None + + def fetchone(self): + """Fetches a single row from the cursor. None indicates that + no more rows are available.""" + self._check_executed() + if self.rownumber >= len(self._rows): return None + result = self._rows[self.rownumber] + self.rownumber = self.rownumber+1 + return result + + def fetchmany(self, size=None): + """Fetch up to size rows from the cursor. Result set may be smaller + than size. If size is not defined, cursor.arraysize is used.""" + self._check_executed() + end = self.rownumber + (size or self.arraysize) + result = self._rows[self.rownumber:end] + self.rownumber = min(end, len(self._rows)) + return result + + def fetchall(self): + """Fetchs all available rows from the cursor.""" + self._check_executed() + if self.rownumber: + result = self._rows[self.rownumber:] + else: + result = self._rows + self.rownumber = len(self._rows) + return result + + def scroll(self, value, mode='relative'): + """Scroll the cursor in the result set to a new position according + to mode. + + If mode is 'relative' (default), value is taken as offset to + the current position in the result set, if set to 'absolute', + value states an absolute target position.""" + self._check_executed() + if mode == 'relative': + r = self.rownumber + value + elif mode == 'absolute': + r = value + else: + self.errorhandler(self, ProgrammingError, + "unknown scroll mode %s" % repr(mode)) + if r < 0 or r >= len(self._rows): + self.errorhandler(self, IndexError, "out of range") + self.rownumber = r + + def __iter__(self): + self._check_executed() + result = self.rownumber and self._rows[self.rownumber:] or self._rows + return iter(result) + + +class CursorUseResultMixIn(object): + + """This is a MixIn class which causes the result set to be stored + in the server and sent row-by-row to client side, i.e. it uses + mysql_use_result(). You MUST retrieve the entire result set and + close() the cursor before additional queries can be peformed on + the connection.""" + + _defer_warnings = True + + def _get_result(self): return self._get_db().use_result() + + def fetchone(self): + """Fetches a single row from the cursor.""" + self._check_executed() + r = self._fetch_row(1) + if not r: + self._warning_check() + return None + self.rownumber = self.rownumber + 1 + return r[0] + + def fetchmany(self, size=None): + """Fetch up to size rows from the cursor. Result set may be smaller + than size. If size is not defined, cursor.arraysize is used.""" + self._check_executed() + r = self._fetch_row(size or self.arraysize) + self.rownumber = self.rownumber + len(r) + if not r: + self._warning_check() + return r + + def fetchall(self): + """Fetchs all available rows from the cursor.""" + self._check_executed() + r = self._fetch_row(0) + self.rownumber = self.rownumber + len(r) + self._warning_check() + return r + + def __iter__(self): + return self + + def next(self): + row = self.fetchone() + if row is None: + raise StopIteration + return row + + +class CursorTupleRowsMixIn(object): + + """This is a MixIn class that causes all rows to be returned as tuples, + which is the standard form required by DB API.""" + + _fetch_type = 0 + + +class CursorDictRowsMixIn(object): + + """This is a MixIn class that causes all rows to be returned as + dictionaries. This is a non-standard feature.""" + + _fetch_type = 1 + + def fetchoneDict(self): + """Fetch a single row as a dictionary. Deprecated: + Use fetchone() instead. Will be removed in 1.3.""" + from warnings import warn + warn("fetchoneDict() is non-standard and will be removed in 1.3", + DeprecationWarning, 2) + return self.fetchone() + + def fetchmanyDict(self, size=None): + """Fetch several rows as a list of dictionaries. Deprecated: + Use fetchmany() instead. Will be removed in 1.3.""" + from warnings import warn + warn("fetchmanyDict() is non-standard and will be removed in 1.3", + DeprecationWarning, 2) + return self.fetchmany(size) + + def fetchallDict(self): + """Fetch all available rows as a list of dictionaries. Deprecated: + Use fetchall() instead. Will be removed in 1.3.""" + from warnings import warn + warn("fetchallDict() is non-standard and will be removed in 1.3", + DeprecationWarning, 2) + return self.fetchall() + + +class CursorOldDictRowsMixIn(CursorDictRowsMixIn): + + """This is a MixIn class that returns rows as dictionaries with + the same key convention as the old Mysqldb (MySQLmodule). Don't + use this.""" + + _fetch_type = 2 + + +class Cursor(CursorStoreResultMixIn, CursorTupleRowsMixIn, + BaseCursor): + + """This is the standard Cursor class that returns rows as tuples + and stores the result set in the client.""" + + +class DictCursor(CursorStoreResultMixIn, CursorDictRowsMixIn, + BaseCursor): + + """This is a Cursor class that returns rows as dictionaries and + stores the result set in the client.""" + + +class SSCursor(CursorUseResultMixIn, CursorTupleRowsMixIn, + BaseCursor): + + """This is a Cursor class that returns rows as tuples and stores + the result set in the server.""" + + +class SSDictCursor(CursorUseResultMixIn, CursorDictRowsMixIn, + BaseCursor): + + """This is a Cursor class that returns rows as dictionaries and + stores the result set in the server.""" + + diff --git a/lib/mysql/MySQLdb/release.py b/lib/mysql/MySQLdb/release.py new file mode 100644 index 00000000..2e7119cf --- /dev/null +++ b/lib/mysql/MySQLdb/release.py @@ -0,0 +1,4 @@ + +__author__ = "Andy Dustman " +version_info = (1,2,5,'final',1) +__version__ = "1.2.5" diff --git a/lib/mysql/MySQLdb/times.py b/lib/mysql/MySQLdb/times.py new file mode 100644 index 00000000..f5f34d47 --- /dev/null +++ b/lib/mysql/MySQLdb/times.py @@ -0,0 +1,126 @@ +"""times module + +This module provides some Date and Time classes for dealing with MySQL data. + +Use Python datetime module to handle date and time columns.""" + +import math +from time import localtime +from datetime import date, datetime, time, timedelta +from _mysql import string_literal + +Date = date +Time = time +TimeDelta = timedelta +Timestamp = datetime + +DateTimeDeltaType = timedelta +DateTimeType = datetime + +def DateFromTicks(ticks): + """Convert UNIX ticks into a date instance.""" + return date(*localtime(ticks)[:3]) + +def TimeFromTicks(ticks): + """Convert UNIX ticks into a time instance.""" + return time(*localtime(ticks)[3:6]) + +def TimestampFromTicks(ticks): + """Convert UNIX ticks into a datetime instance.""" + return datetime(*localtime(ticks)[:6]) + +format_TIME = format_DATE = str + +def format_TIMEDELTA(v): + seconds = int(v.seconds) % 60 + minutes = int(v.seconds / 60) % 60 + hours = int(v.seconds / 3600) % 24 + return '%d %d:%d:%d' % (v.days, hours, minutes, seconds) + +def format_TIMESTAMP(d): + return d.isoformat(" ") + + +def DateTime_or_None(s): + if ' ' in s: + sep = ' ' + elif 'T' in s: + sep = 'T' + else: + return Date_or_None(s) + + try: + d, t = s.split(sep, 1) + if '.' in t: + t, ms = t.split('.',1) + ms = ms.ljust(6, '0') + else: + ms = 0 + return datetime(*[ int(x) for x in d.split('-')+t.split(':')+[ms] ]) + except (SystemExit, KeyboardInterrupt): + raise + except: + return Date_or_None(s) + +def TimeDelta_or_None(s): + try: + h, m, s = s.split(':') + if '.' in s: + s, ms = s.split('.') + ms = ms.ljust(6, '0') + else: + ms = 0 + h, m, s, ms = int(h), int(m), int(s), int(ms) + td = timedelta(hours=abs(h), minutes=m, seconds=s, + microseconds=ms) + if h < 0: + return -td + else: + return td + except ValueError: + # unpacking or int/float conversion failed + return None + +def Time_or_None(s): + try: + h, m, s = s.split(':') + if '.' in s: + s, ms = s.split('.') + ms = ms.ljust(6, '0') + else: + ms = 0 + h, m, s, ms = int(h), int(m), int(s), int(ms) + return time(hour=h, minute=m, second=s, + microsecond=ms) + except ValueError: + return None + +def Date_or_None(s): + try: + return date(*[ int(x) for x in s.split('-',2)]) + except (SystemExit, KeyboardInterrupt): + raise + except: + return None + +def DateTime2literal(d, c): + """Format a DateTime object as an ISO timestamp.""" + return string_literal(format_TIMESTAMP(d),c) + +def DateTimeDelta2literal(d, c): + """Format a DateTimeDelta object as a time.""" + return string_literal(format_TIMEDELTA(d),c) + +def mysql_timestamp_converter(s): + """Convert a MySQL TIMESTAMP to a Timestamp object.""" + # MySQL>4.1 returns TIMESTAMP in the same format as DATETIME + if s[4] == '-': return DateTime_or_None(s) + s = s + "0"*(14-len(s)) # padding + parts = map(int, filter(None, (s[:4],s[4:6],s[6:8], + s[8:10],s[10:12],s[12:14]))) + try: + return Timestamp(*parts) + except (SystemExit, KeyboardInterrupt): + raise + except: + return None diff --git a/lib/mysql/PKG-INFO b/lib/mysql/PKG-INFO new file mode 100644 index 00000000..0337c0a0 --- /dev/null +++ b/lib/mysql/PKG-INFO @@ -0,0 +1,43 @@ +Metadata-Version: 1.1 +Name: MySQL-python +Version: 1.2.5 +Summary: Python interface to MySQL +Home-page: https://github.com/farcepest/MySQLdb1 +Author: Andy Dustman +Author-email: farcepest@gmail.com +License: GPL +Description: + ========================= + Python interface to MySQL + ========================= + + MySQLdb is an interface to the popular MySQL_ database server for + Python. The design goals are: + + - Compliance with Python database API version 2.0 [PEP-0249]_ + - Thread-safety + - Thread-friendliness (threads will not block each other) + + MySQL-3.23 through 5.5 and Python-2.4 through 2.7 are currently + supported. Python-3.0 will be supported in a future release. + PyPy is supported. + + MySQLdb is `Free Software`_. + + .. _MySQL: http://www.mysql.com/ + .. _`Free Software`: http://www.gnu.org/ + .. [PEP-0249] http://www.python.org/peps/pep-0249.html +Platform: ALL +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Other Environment +Classifier: License :: OSI Approved :: GNU General Public License (GPL) +Classifier: Operating System :: MacOS :: MacOS X +Classifier: Operating System :: Microsoft :: Windows :: Windows NT/2000 +Classifier: Operating System :: OS Independent +Classifier: Operating System :: POSIX +Classifier: Operating System :: POSIX :: Linux +Classifier: Operating System :: Unix +Classifier: Programming Language :: C +Classifier: Programming Language :: Python +Classifier: Topic :: Database +Classifier: Topic :: Database :: Database Engines/Servers diff --git a/lib/mysql/README.md b/lib/mysql/README.md new file mode 100644 index 00000000..f0ca0321 --- /dev/null +++ b/lib/mysql/README.md @@ -0,0 +1,41 @@ +MySQLdb1 +======== + +This is the legacy (1.x) version of MySQLdb. While it is still being +maintained, there will not be a lot of new feature development. + +[![Build Status](https://secure.travis-ci.org/farcepest/MySQLdb1.png)](http://travis-ci.org/farcepest/MySQLdb1) + +TODO +---- + +* A bugfix 1.2.4 release +* A 1.3.0 release that will support Python 2.7-3.3 +* The 2.0 version is being renamed [moist][] and is heavily refactored. + +Projects +-------- + +* [MySQLdb-svn][] + + This is the old Subversion repository located on SourceForge. + It has all the early historical development of MySQLdb through 1.2.3, + and also is the working repository for ZMySQLDA. The trunk on this + repository was forked to create the [MySQLdb2][] repository. + +* [MySQLdb1][] + + This is the new (active) git repository. + Only updates to the 1.x series will happen here. + +* [MySQLdb2][] + + This is the now obsolete Mercurial repository for MySQLdb-2.0 + located on SourceForge. This repository has been migrated to the + [moist][] repository. + + +[MySQLdb1]: https://github.com/farcepest/MySQLdb1 +[moist]: https://github.com/farcepest/moist +[MySQLdb-svn]: https://sourceforge.net/p/mysql-python/svn/ +[MySQLdb2]: https://sourceforge.net/p/mysql-python/mysqldb-2/ \ No newline at end of file diff --git a/lib/mysql/_mysql.c b/lib/mysql/_mysql.c new file mode 100644 index 00000000..f0813464 --- /dev/null +++ b/lib/mysql/_mysql.c @@ -0,0 +1,3168 @@ +/* +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. Alternatively, you may use the original license +reproduced below. + +Copyright 1999 by Comstar.net, Inc., Atlanta, GA, US. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Comstar.net, Inc. +or COMSTAR not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior permission. + +COMSTAR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +EVENT SHALL COMSTAR BE LIABLE FOR ANY SPECIAL, INDIRECT OR +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +*/ + +#include "Python.h" +#if PY_MAJOR_VERSION >= 3 +#define IS_PY3K +#define PyInt_FromLong(n) PyLong_FromLong(n) +#define PyInt_Check(n) PyLong_Check(n) +#define PyInt_AS_LONG(n) PyLong_AS_LONG(n) +#endif +#if PY_VERSION_HEX > 0x02060000 +#include "bytesobject.h" +#endif +#include "pymemcompat.h" +#include "structmember.h" +#if defined(MS_WINDOWS) +#include +#else +#include "my_config.h" +#endif +#include "mysql.h" +#include "mysqld_error.h" +#include "errmsg.h" + +#if PY_VERSION_HEX < 0x02020000 +# define MyTuple_Resize(t,n,d) _PyTuple_Resize(t, n, d) +# define MyMember(a,b,c,d,e) {a,b,c,d} +# define MyMemberlist(x) struct memberlist x +# define MyAlloc(s,t) PyObject_New(s,&t) +# define MyFree(o) PyObject_Del(o) +#else +# define MyTuple_Resize(t,n,d) _PyTuple_Resize(t, n) +# define MyMember(a,b,c,d,e) {a,b,c,d,e} +# define MyMemberlist(x) struct PyMemberDef x +# define MyAlloc(s,t) (s *) t.tp_alloc(&t,0) +#ifdef IS_PY3K +# define MyFree(o) PyObject_Del(o) +#else +# define MyFree(ob) ob->ob_type->tp_free((PyObject *)ob) +#endif +#endif + +#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) +typedef int Py_ssize_t; +#define PY_SSIZE_T_MAX INT_MAX +#define PY_SSIZE_T_MIN INT_MIN +#endif + +static PyObject *_mysql_MySQLError; +static PyObject *_mysql_Warning; +static PyObject *_mysql_Error; +static PyObject *_mysql_DatabaseError; +static PyObject *_mysql_InterfaceError; +static PyObject *_mysql_DataError; +static PyObject *_mysql_OperationalError; +static PyObject *_mysql_IntegrityError; +static PyObject *_mysql_InternalError; +static PyObject *_mysql_ProgrammingError; +static PyObject *_mysql_NotSupportedError; + +typedef struct { + PyObject_HEAD + MYSQL connection; + int open; + PyObject *converter; +} _mysql_ConnectionObject; + +#define check_connection(c) if (!(c->open)) return _mysql_Exception(c) +#define result_connection(r) ((_mysql_ConnectionObject *)r->conn) +#define check_result_connection(r) check_connection(result_connection(r)) + +extern PyTypeObject _mysql_ConnectionObject_Type; + +typedef struct { + PyObject_HEAD + PyObject *conn; + MYSQL_RES *result; + int nfields; + int use; + PyObject *converter; +} _mysql_ResultObject; + +extern PyTypeObject _mysql_ResultObject_Type; + +static int _mysql_server_init_done = 0; +#if MYSQL_VERSION_ID >= 40000 +#define check_server_init(x) if (!_mysql_server_init_done) { if (mysql_server_init(0, NULL, NULL)) { _mysql_Exception(NULL); return x; } else { _mysql_server_init_done = 1;} } +#else +#define check_server_init(x) if (!_mysql_server_init_done) _mysql_server_init_done = 1 +#endif + +#if MYSQL_VERSION_ID >= 50500 +#define HAVE_OPENSSL 1 +#endif + +/* According to https://dev.mysql.com/doc/refman/5.1/en/mysql-options.html + The MYSQL_OPT_READ_TIMEOUT apear in the version 5.1.12 */ +#if MYSQL_VERSION_ID > 50112 +#define HAVE_MYSQL_OPT_TIMEOUTS 1 +#endif + +PyObject * +_mysql_Exception(_mysql_ConnectionObject *c) +{ + PyObject *t, *e; + int merr; + + if (!(t = PyTuple_New(2))) return NULL; + if (!_mysql_server_init_done) { + e = _mysql_InternalError; + PyTuple_SET_ITEM(t, 0, PyInt_FromLong(-1L)); +#ifdef IS_PY3K + PyTuple_SET_ITEM(t, 1, PyUnicode_FromString("server not initialized")); +#else + PyTuple_SET_ITEM(t, 1, PyString_FromString("server not initialized")); +#endif + PyErr_SetObject(e, t); + Py_DECREF(t); + return NULL; + } + merr = mysql_errno(&(c->connection)); + if (!merr) + e = _mysql_InterfaceError; + else if (merr > CR_MAX_ERROR) { + PyTuple_SET_ITEM(t, 0, PyInt_FromLong(-1L)); +#ifdef IS_PY3K + PyTuple_SET_ITEM(t, 1, PyUnicode_FromString("error totally whack")); +#else + PyTuple_SET_ITEM(t, 1, PyString_FromString("error totally whack")); +#endif + PyErr_SetObject(_mysql_InterfaceError, t); + Py_DECREF(t); + return NULL; + } + else switch (merr) { + case CR_COMMANDS_OUT_OF_SYNC: + case ER_DB_CREATE_EXISTS: + case ER_SYNTAX_ERROR: + case ER_PARSE_ERROR: + case ER_NO_SUCH_TABLE: + case ER_WRONG_DB_NAME: + case ER_WRONG_TABLE_NAME: + case ER_FIELD_SPECIFIED_TWICE: + case ER_INVALID_GROUP_FUNC_USE: + case ER_UNSUPPORTED_EXTENSION: + case ER_TABLE_MUST_HAVE_COLUMNS: +#ifdef ER_CANT_DO_THIS_DURING_AN_TRANSACTION + case ER_CANT_DO_THIS_DURING_AN_TRANSACTION: +#endif + e = _mysql_ProgrammingError; + break; +#ifdef WARN_DATA_TRUNCATED + case WARN_DATA_TRUNCATED: +#ifdef WARN_NULL_TO_NOTNULL + case WARN_NULL_TO_NOTNULL: +#endif +#ifdef ER_WARN_DATA_OUT_OF_RANGE + case ER_WARN_DATA_OUT_OF_RANGE: +#endif +#ifdef ER_NO_DEFAULT + case ER_NO_DEFAULT: +#endif +#ifdef ER_PRIMARY_CANT_HAVE_NULL + case ER_PRIMARY_CANT_HAVE_NULL: +#endif +#ifdef ER_DATA_TOO_LONG + case ER_DATA_TOO_LONG: +#endif +#ifdef ER_DATETIME_FUNCTION_OVERFLOW + case ER_DATETIME_FUNCTION_OVERFLOW: +#endif + e = _mysql_DataError; + break; +#endif + case ER_DUP_ENTRY: +#ifdef ER_DUP_UNIQUE + case ER_DUP_UNIQUE: +#endif +#ifdef ER_NO_REFERENCED_ROW + case ER_NO_REFERENCED_ROW: +#endif +#ifdef ER_NO_REFERENCED_ROW_2 + case ER_NO_REFERENCED_ROW_2: +#endif +#ifdef ER_ROW_IS_REFERENCED + case ER_ROW_IS_REFERENCED: +#endif +#ifdef ER_ROW_IS_REFERENCED_2 + case ER_ROW_IS_REFERENCED_2: +#endif +#ifdef ER_CANNOT_ADD_FOREIGN + case ER_CANNOT_ADD_FOREIGN: +#endif + e = _mysql_IntegrityError; + break; +#ifdef ER_WARNING_NOT_COMPLETE_ROLLBACK + case ER_WARNING_NOT_COMPLETE_ROLLBACK: +#endif +#ifdef ER_NOT_SUPPORTED_YET + case ER_NOT_SUPPORTED_YET: +#endif +#ifdef ER_FEATURE_DISABLED + case ER_FEATURE_DISABLED: +#endif +#ifdef ER_UNKNOWN_STORAGE_ENGINE + case ER_UNKNOWN_STORAGE_ENGINE: +#endif + e = _mysql_NotSupportedError; + break; + default: + if (merr < 1000) + e = _mysql_InternalError; + else + e = _mysql_OperationalError; + break; + } + PyTuple_SET_ITEM(t, 0, PyInt_FromLong((long)merr)); +#ifdef IS_PY3K + PyTuple_SET_ITEM(t, 1, PyUnicode_FromString(mysql_error(&(c->connection)))); +#else + PyTuple_SET_ITEM(t, 1, PyString_FromString(mysql_error(&(c->connection)))); +#endif + PyErr_SetObject(e, t); + Py_DECREF(t); + return NULL; +} + +static char _mysql_server_init__doc__[] = +"Initialize embedded server. If this client is not linked against\n\ +the embedded server library, this function does nothing.\n\ +\n\ +args -- sequence of command-line arguments\n\ +groups -- sequence of groups to use in defaults files\n\ +"; + +static PyObject *_mysql_server_init( + PyObject *self, + PyObject *args, + PyObject *kwargs) { + static char *kwlist[] = {"args", "groups", NULL}; + char **cmd_args_c=NULL, **groups_c=NULL, *s; + int cmd_argc=0, i, groupc; + PyObject *cmd_args=NULL, *groups=NULL, *ret=NULL, *item; + + if (_mysql_server_init_done) { + PyErr_SetString(_mysql_ProgrammingError, + "already initialized"); + return NULL; + } + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OO", kwlist, + &cmd_args, &groups)) + return NULL; + +#if MYSQL_VERSION_ID >= 40000 + if (cmd_args) { + if (!PySequence_Check(cmd_args)) { + PyErr_SetString(PyExc_TypeError, + "args must be a sequence"); + goto finish; + } + cmd_argc = PySequence_Size(cmd_args); + if (cmd_argc == -1) { + PyErr_SetString(PyExc_TypeError, + "args could not be sized"); + goto finish; + } + cmd_args_c = (char **) PyMem_Malloc(cmd_argc*sizeof(char *)); + for (i=0; i< cmd_argc; i++) { + item = PySequence_GetItem(cmd_args, i); +#ifdef IS_PY3K + s = PyUnicode_AS_DATA(item); +#else + s = PyString_AsString(item); +#endif + + Py_DECREF(item); + if (!s) { + PyErr_SetString(PyExc_TypeError, + "args must contain strings"); + goto finish; + } + cmd_args_c[i] = s; + } + } + if (groups) { + if (!PySequence_Check(groups)) { + PyErr_SetString(PyExc_TypeError, + "groups must be a sequence"); + goto finish; + } + groupc = PySequence_Size(groups); + if (groupc == -1) { + PyErr_SetString(PyExc_TypeError, + "groups could not be sized"); + goto finish; + } + groups_c = (char **) PyMem_Malloc((1+groupc)*sizeof(char *)); + for (i=0; i< groupc; i++) { + item = PySequence_GetItem(groups, i); +#ifdef IS_PY3K + s = PyUnicode_AS_DATA(item); +#else + s = PyString_AsString(item); +#endif + Py_DECREF(item); + if (!s) { + PyErr_SetString(PyExc_TypeError, + "groups must contain strings"); + goto finish; + } + groups_c[i] = s; + } + groups_c[groupc] = (char *)NULL; + } + /* even though this may block, don't give up the interpreter lock + so that the server can't be initialized multiple times. */ + if (mysql_server_init(cmd_argc, cmd_args_c, groups_c)) { + _mysql_Exception(NULL); + goto finish; + } +#endif + ret = Py_None; + Py_INCREF(Py_None); + _mysql_server_init_done = 1; + finish: + PyMem_Free(groups_c); + PyMem_Free(cmd_args_c); + return ret; +} + +static char _mysql_server_end__doc__[] = +"Shut down embedded server. If not using an embedded server, this\n\ +does nothing."; + +static PyObject *_mysql_server_end( + PyObject *self, + PyObject *args) { + if (_mysql_server_init_done) { +#if MYSQL_VERSION_ID >= 40000 + mysql_server_end(); +#endif + _mysql_server_init_done = 0; + Py_INCREF(Py_None); + return Py_None; + } + return _mysql_Exception(NULL); +} + +#if MYSQL_VERSION_ID >= 32314 +static char _mysql_thread_safe__doc__[] = +"Indicates whether the client is compiled as thread-safe."; + +static PyObject *_mysql_thread_safe( + PyObject *self, + PyObject *args) { + PyObject *flag; + if (!PyArg_ParseTuple(args, "")) return NULL; + check_server_init(NULL); + if (!(flag=PyInt_FromLong((long)mysql_thread_safe()))) return NULL; + return flag; +} +#endif + +static char _mysql_ResultObject__doc__[] = +"result(connection, use=0, converter={}) -- Result set from a query.\n\ +\n\ +Creating instances of this class directly is an excellent way to\n\ +shoot yourself in the foot. If using _mysql.connection directly,\n\ +use connection.store_result() or connection.use_result() instead.\n\ +If using MySQLdb.Connection, this is done by the cursor class.\n\ +Just forget you ever saw this. Forget... FOR-GET..."; + +static int +_mysql_ResultObject_Initialize( + _mysql_ResultObject *self, + PyObject *args, + PyObject *kwargs) +{ + static char *kwlist[] = {"connection", "use", "converter", NULL}; + MYSQL_RES *result; + _mysql_ConnectionObject *conn=NULL; + int use=0; + PyObject *conv=NULL; + int n, i; + MYSQL_FIELD *fields; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iO", kwlist, + &conn, &use, &conv)) + return -1; + if (!conv) { + if (!(conv = PyDict_New())) + return -1; + } + else + Py_INCREF(conv); + + self->conn = (PyObject *) conn; + Py_INCREF(conn); + self->use = use; + Py_BEGIN_ALLOW_THREADS ; + if (use) + result = mysql_use_result(&(conn->connection)); + else + result = mysql_store_result(&(conn->connection)); + self->result = result; + Py_END_ALLOW_THREADS ; + if (!result) { + if (mysql_field_count(&(conn->connection)) > 0) { + _mysql_Exception(conn); + return -1; + } + self->converter = PyTuple_New(0); + Py_DECREF(conv); + return 0; + } + n = mysql_num_fields(result); + self->nfields = n; + if (!(self->converter = PyTuple_New(n))) { + Py_DECREF(conv); + return -1; + } + fields = mysql_fetch_fields(result); + for (i=0; iconverter, i, fun); + } + + Py_DECREF(conv); + return 0; +} + +#if PY_VERSION_HEX >= 0x02020000 +static int _mysql_ResultObject_traverse( + _mysql_ResultObject *self, + visitproc visit, + void *arg) +{ + int r; + if (self->converter) { + if (!(r = visit(self->converter, arg))) return r; + } + if (self->conn) + return visit(self->conn, arg); + return 0; +} +#endif + +static int _mysql_ResultObject_clear( + _mysql_ResultObject *self) +{ + Py_XDECREF(self->converter); + self->converter = NULL; + Py_XDECREF(self->conn); + self->conn = NULL; + return 0; +} + +static int +_mysql_ConnectionObject_Initialize( + _mysql_ConnectionObject *self, + PyObject *args, + PyObject *kwargs) +{ + MYSQL *conn = NULL; + PyObject *conv = NULL; + PyObject *ssl = NULL; +#if HAVE_OPENSSL + char *key = NULL, *cert = NULL, *ca = NULL, + *capath = NULL, *cipher = NULL; +#endif + char *host = NULL, *user = NULL, *passwd = NULL, + *db = NULL, *unix_socket = NULL; + unsigned int port = 0; + unsigned int client_flag = 0; + static char *kwlist[] = { "host", "user", "passwd", "db", "port", + "unix_socket", "conv", + "connect_timeout", "compress", + "named_pipe", "init_command", + "read_default_file", "read_default_group", + "client_flag", "ssl", + "local_infile", +#ifdef HAVE_MYSQL_OPT_TIMEOUTS + "read_timeout", + "write_timeout", +#endif + NULL } ; + int connect_timeout = 0; +#ifdef HAVE_MYSQL_OPT_TIMEOUTS + int read_timeout = 0; + int write_timeout = 0; +#endif + int compress = -1, named_pipe = -1, local_infile = -1; + char *init_command=NULL, + *read_default_file=NULL, + *read_default_group=NULL; + + self->converter = NULL; + self->open = 0; + check_server_init(-1); + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, +#ifdef HAVE_MYSQL_OPT_TIMEOUTS + "|ssssisOiiisssiOiii:connect", +#else + "|ssssisOiiisssiOi:connect", +#endif + kwlist, + &host, &user, &passwd, &db, + &port, &unix_socket, &conv, + &connect_timeout, + &compress, &named_pipe, + &init_command, &read_default_file, + &read_default_group, + &client_flag, &ssl, + &local_infile +#ifdef HAVE_MYSQL_OPT_TIMEOUTS + , &read_timeout + , &write_timeout +#endif + )) + return -1; + +#ifdef IS_PY3K +#define _stringsuck(d,t,s) {t=PyMapping_GetItemString(s,#d);\ + if(t){d=PyUnicode_AS_DATA(t);Py_DECREF(t);}\ + PyErr_Clear();} +#else +#define _stringsuck(d,t,s) {t=PyMapping_GetItemString(s,#d);\ + if(t){d=PyString_AsString(t);Py_DECREF(t);}\ + PyErr_Clear();} +#endif + + if (ssl) { +#if HAVE_OPENSSL + PyObject *value = NULL; + _stringsuck(ca, value, ssl); + _stringsuck(capath, value, ssl); + _stringsuck(cert, value, ssl); + _stringsuck(key, value, ssl); + _stringsuck(cipher, value, ssl); +#else + PyErr_SetString(_mysql_NotSupportedError, + "client library does not have SSL support"); + return -1; +#endif + } + + Py_BEGIN_ALLOW_THREADS ; + conn = mysql_init(&(self->connection)); + if (connect_timeout) { + unsigned int timeout = connect_timeout; + mysql_options(&(self->connection), MYSQL_OPT_CONNECT_TIMEOUT, + (char *)&timeout); + } +#ifdef HAVE_MYSQL_OPT_TIMEOUTS + if (read_timeout) { + unsigned int timeout = read_timeout; + mysql_options(&(self->connection), MYSQL_OPT_READ_TIMEOUT, + (char *)&timeout); + } + if (write_timeout) { + unsigned int timeout = write_timeout; + mysql_options(&(self->connection), MYSQL_OPT_WRITE_TIMEOUT, + (char *)&timeout); + } +#endif + if (compress != -1) { + mysql_options(&(self->connection), MYSQL_OPT_COMPRESS, 0); + client_flag |= CLIENT_COMPRESS; + } + if (named_pipe != -1) + mysql_options(&(self->connection), MYSQL_OPT_NAMED_PIPE, 0); + if (init_command != NULL) + mysql_options(&(self->connection), MYSQL_INIT_COMMAND, init_command); + if (read_default_file != NULL) + mysql_options(&(self->connection), MYSQL_READ_DEFAULT_FILE, read_default_file); + if (read_default_group != NULL) + mysql_options(&(self->connection), MYSQL_READ_DEFAULT_GROUP, read_default_group); + + if (local_infile != -1) + mysql_options(&(self->connection), MYSQL_OPT_LOCAL_INFILE, (char *) &local_infile); + +#if HAVE_OPENSSL + if (ssl) + mysql_ssl_set(&(self->connection), + key, cert, ca, capath, cipher); +#endif + + conn = mysql_real_connect(&(self->connection), host, user, passwd, db, + port, unix_socket, client_flag); + + Py_END_ALLOW_THREADS ; + + if (!conn) { + _mysql_Exception(self); + return -1; + } + + /* Internal references to python-land objects */ + if (!conv) + conv = PyDict_New(); + else + Py_INCREF(conv); + + if (!conv) + return -1; + self->converter = conv; + + /* + PyType_GenericAlloc() automatically sets up GC allocation and + tracking for GC objects, at least in 2.2.1, so it does not need to + be done here. tp_dealloc still needs to call PyObject_GC_UnTrack(), + however. + */ + self->open = 1; + return 0; +} + +static char _mysql_connect__doc__[] = +"Returns a MYSQL connection object. Exclusive use of\n\ +keyword parameters strongly recommended. Consult the\n\ +MySQL C API documentation for more details.\n\ +\n\ +host\n\ + string, host to connect\n\ +\n\ +user\n\ + string, user to connect as\n\ +\n\ +passwd\n\ + string, password to use\n\ +\n\ +db\n\ + string, database to use\n\ +\n\ +port\n\ + integer, TCP/IP port to connect to\n\ +\n\ +unix_socket\n\ + string, location of unix_socket (UNIX-ish only)\n\ +\n\ +conv\n\ + mapping, maps MySQL FIELD_TYPE.* to Python functions which\n\ + convert a string to the appropriate Python type\n\ +\n\ +connect_timeout\n\ + number of seconds to wait before the connection\n\ + attempt fails.\n\ +\n\ +compress\n\ + if set, gzip compression is enabled\n\ +\n\ +named_pipe\n\ + if set, connect to server via named pipe (Windows only)\n\ +\n\ +init_command\n\ + command which is run once the connection is created\n\ +\n\ +read_default_file\n\ + see the MySQL documentation for mysql_options()\n\ +\n\ +read_default_group\n\ + see the MySQL documentation for mysql_options()\n\ +\n\ +client_flag\n\ + client flags from MySQLdb.constants.CLIENT\n\ +\n\ +load_infile\n\ + int, non-zero enables LOAD LOCAL INFILE, zero disables\n\ +\n\ +"; + +static PyObject * +_mysql_connect( + PyObject *self, + PyObject *args, + PyObject *kwargs) +{ + _mysql_ConnectionObject *c=NULL; + + c = MyAlloc(_mysql_ConnectionObject, _mysql_ConnectionObject_Type); + if (c == NULL) return NULL; + if (_mysql_ConnectionObject_Initialize(c, args, kwargs)) { + Py_DECREF(c); + c = NULL; + } + return (PyObject *) c; +} + +#if PY_VERSION_HEX >= 0x02020000 +static int _mysql_ConnectionObject_traverse( + _mysql_ConnectionObject *self, + visitproc visit, + void *arg) +{ + if (self->converter) + return visit(self->converter, arg); + return 0; +} +#endif + +static int _mysql_ConnectionObject_clear( + _mysql_ConnectionObject *self) +{ + Py_XDECREF(self->converter); + self->converter = NULL; + return 0; +} + +static char _mysql_ConnectionObject_close__doc__[] = +"Close the connection. No further activity possible."; + +static PyObject * +_mysql_ConnectionObject_close( + _mysql_ConnectionObject *self, + PyObject *args) +{ + if (args) { + if (!PyArg_ParseTuple(args, "")) return NULL; + } + if (self->open) { + Py_BEGIN_ALLOW_THREADS + mysql_close(&(self->connection)); + Py_END_ALLOW_THREADS + self->open = 0; + } else { + PyErr_SetString(_mysql_ProgrammingError, + "closing a closed connection"); + return NULL; + } + _mysql_ConnectionObject_clear(self); + Py_INCREF(Py_None); + return Py_None; +} + +static char _mysql_ConnectionObject_affected_rows__doc__ [] = +"Return number of rows affected by the last query.\n\ +Non-standard. Use Cursor.rowcount.\n\ +"; + +static PyObject * +_mysql_ConnectionObject_affected_rows( + _mysql_ConnectionObject *self, + PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) return NULL; + check_connection(self); + return PyLong_FromUnsignedLongLong(mysql_affected_rows(&(self->connection))); +} + +static char _mysql_debug__doc__[] = +"Does a DBUG_PUSH with the given string.\n\ +mysql_debug() uses the Fred Fish debug library.\n\ +To use this function, you must compile the client library to\n\ +support debugging.\n\ +"; +static PyObject * +_mysql_debug( + PyObject *self, + PyObject *args) +{ + char *debug; + if (!PyArg_ParseTuple(args, "s", &debug)) return NULL; + mysql_debug(debug); + Py_INCREF(Py_None); + return Py_None; +} + +static char _mysql_ConnectionObject_dump_debug_info__doc__[] = +"Instructs the server to write some debug information to the\n\ +log. The connected user must have the process privilege for\n\ +this to work. Non-standard.\n\ +"; + +static PyObject * +_mysql_ConnectionObject_dump_debug_info( + _mysql_ConnectionObject *self, + PyObject *args) +{ + int err; + if (!PyArg_ParseTuple(args, "")) return NULL; + check_connection(self); + Py_BEGIN_ALLOW_THREADS + err = mysql_dump_debug_info(&(self->connection)); + Py_END_ALLOW_THREADS + if (err) return _mysql_Exception(self); + Py_INCREF(Py_None); + return Py_None; +} + +static char _mysql_ConnectionObject_autocommit__doc__[] = +"Set the autocommit mode. True values enable; False value disable.\n\ +"; +static PyObject * +_mysql_ConnectionObject_autocommit( + _mysql_ConnectionObject *self, + PyObject *args) +{ + int flag, err; + if (!PyArg_ParseTuple(args, "i", &flag)) return NULL; + Py_BEGIN_ALLOW_THREADS +#if MYSQL_VERSION_ID >= 40100 + err = mysql_autocommit(&(self->connection), flag); +#else + { + char query[256]; + snprintf(query, 256, "SET AUTOCOMMIT=%d", flag); + err = mysql_query(&(self->connection), query); + } +#endif + Py_END_ALLOW_THREADS + if (err) return _mysql_Exception(self); + Py_INCREF(Py_None); + return Py_None; +} + +static char _mysql_ConnectionObject_get_autocommit__doc__[] = +"Get the autocommit mode. True when enable; False when disable.\n"; + +static PyObject * +_mysql_ConnectionObject_get_autocommit( + _mysql_ConnectionObject *self, + PyObject *args) +{ + if (self->connection.server_status & SERVER_STATUS_AUTOCOMMIT) { + Py_RETURN_TRUE; + } + Py_RETURN_FALSE; +} + +static char _mysql_ConnectionObject_commit__doc__[] = +"Commits the current transaction\n\ +"; +static PyObject * +_mysql_ConnectionObject_commit( + _mysql_ConnectionObject *self, + PyObject *args) +{ + int err; + if (!PyArg_ParseTuple(args, "")) return NULL; + Py_BEGIN_ALLOW_THREADS +#if MYSQL_VERSION_ID >= 40100 + err = mysql_commit(&(self->connection)); +#else + err = mysql_query(&(self->connection), "COMMIT"); +#endif + Py_END_ALLOW_THREADS + if (err) return _mysql_Exception(self); + Py_INCREF(Py_None); + return Py_None; +} + +static char _mysql_ConnectionObject_rollback__doc__[] = +"Rolls backs the current transaction\n\ +"; +static PyObject * +_mysql_ConnectionObject_rollback( + _mysql_ConnectionObject *self, + PyObject *args) +{ + int err; + if (!PyArg_ParseTuple(args, "")) return NULL; + Py_BEGIN_ALLOW_THREADS +#if MYSQL_VERSION_ID >= 40100 + err = mysql_rollback(&(self->connection)); +#else + err = mysql_query(&(self->connection), "ROLLBACK"); +#endif + Py_END_ALLOW_THREADS + if (err) return _mysql_Exception(self); + Py_INCREF(Py_None); + return Py_None; +} + +static char _mysql_ConnectionObject_next_result__doc__[] = +"If more query results exist, next_result() reads the next query\n\ +results and returns the status back to application.\n\ +\n\ +After calling next_result() the state of the connection is as if\n\ +you had called query() for the next query. This means that you can\n\ +now call store_result(), warning_count(), affected_rows()\n\ +, and so forth. \n\ +\n\ +Returns 0 if there are more results; -1 if there are no more results\n\ +\n\ +Non-standard.\n\ +"; +static PyObject * +_mysql_ConnectionObject_next_result( + _mysql_ConnectionObject *self, + PyObject *args) +{ + int err; + if (!PyArg_ParseTuple(args, "")) return NULL; + Py_BEGIN_ALLOW_THREADS +#if MYSQL_VERSION_ID >= 40100 + err = mysql_next_result(&(self->connection)); +#else + err = -1; +#endif + Py_END_ALLOW_THREADS + if (err > 0) return _mysql_Exception(self); + return PyInt_FromLong(err); +} + +#if MYSQL_VERSION_ID >= 40100 + +static char _mysql_ConnectionObject_set_server_option__doc__[] = +"set_server_option(option) -- Enables or disables an option\n\ +for the connection.\n\ +\n\ +Non-standard.\n\ +"; +static PyObject * +_mysql_ConnectionObject_set_server_option( + _mysql_ConnectionObject *self, + PyObject *args) +{ + int err, flags=0; + if (!PyArg_ParseTuple(args, "i", &flags)) + return NULL; + Py_BEGIN_ALLOW_THREADS + err = mysql_set_server_option(&(self->connection), flags); + Py_END_ALLOW_THREADS + if (err) return _mysql_Exception(self); + return PyInt_FromLong(err); +} + +static char _mysql_ConnectionObject_sqlstate__doc__[] = +"Returns a string containing the SQLSTATE error code\n\ +for the last error. The error code consists of five characters.\n\ +'00000' means \"no error.\" The values are specified by ANSI SQL\n\ +and ODBC. For a list of possible values, see section 23\n\ +Error Handling in MySQL in the MySQL Manual.\n\ +\n\ +Note that not all MySQL errors are yet mapped to SQLSTATE's.\n\ +The value 'HY000' (general error) is used for unmapped errors.\n\ +\n\ +Non-standard.\n\ +"; +static PyObject * +_mysql_ConnectionObject_sqlstate( + _mysql_ConnectionObject *self, + PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) return NULL; +#ifdef IS_PY3K + return PyUnicode_FromString(mysql_sqlstate(&(self->connection))); +#else + return PyString_FromString(mysql_sqlstate(&(self->connection))); +#endif +} + +static char _mysql_ConnectionObject_warning_count__doc__[] = +"Returns the number of warnings generated during execution\n\ +of the previous SQL statement.\n\ +\n\ +Non-standard.\n\ +"; +static PyObject * +_mysql_ConnectionObject_warning_count( + _mysql_ConnectionObject *self, + PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) return NULL; + return PyInt_FromLong(mysql_warning_count(&(self->connection))); +} + +#endif + +static char _mysql_ConnectionObject_errno__doc__[] = +"Returns the error code for the most recently invoked API function\n\ +that can succeed or fail. A return value of zero means that no error\n\ +occurred.\n\ +"; + +static PyObject * +_mysql_ConnectionObject_errno( + _mysql_ConnectionObject *self, + PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) return NULL; + check_connection(self); + return PyInt_FromLong((long)mysql_errno(&(self->connection))); +} + +static char _mysql_ConnectionObject_error__doc__[] = +"Returns the error message for the most recently invoked API function\n\ +that can succeed or fail. An empty string ("") is returned if no error\n\ +occurred.\n\ +"; + +static PyObject * +_mysql_ConnectionObject_error( + _mysql_ConnectionObject *self, + PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) return NULL; + check_connection(self); +#ifdef IS_PY3K + return PyUnicode_FromString(mysql_error(&(self->connection))); +#else + return PyString_FromString(mysql_error(&(self->connection))); +#endif +} + +static char _mysql_escape_string__doc__[] = +"escape_string(s) -- quote any SQL-interpreted characters in string s.\n\ +\n\ +Use connection.escape_string(s), if you use it at all.\n\ +_mysql.escape_string(s) cannot handle character sets. You are\n\ +probably better off using connection.escape(o) instead, since\n\ +it will escape entire sequences as well as strings."; + +static PyObject * +_mysql_escape_string( + _mysql_ConnectionObject *self, + PyObject *args) +{ + PyObject *str; + char *in, *out; + int len, size; + if (!PyArg_ParseTuple(args, "s#:escape_string", &in, &size)) return NULL; +#ifdef IS_PY3K + str = PyUnicode_FromStringAndSize((char *) NULL, size*2+1); +#else + str = PyString_FromStringAndSize((char *) NULL, size*2+1); +#endif + if (!str) return PyErr_NoMemory(); +#ifdef IS_PY3K + out = PyUnicode_AS_DATA(str); +#else + out = PyString_AS_STRING(str); +#endif +#if MYSQL_VERSION_ID < 32321 + len = mysql_escape_string(out, in, size); +#else + check_server_init(NULL); + if (self && self->open) + len = mysql_real_escape_string(&(self->connection), out, in, size); + else + len = mysql_escape_string(out, in, size); +#endif +#ifdef IS_PY3K + if (PyUnicode_Resize(&str, len) < 0) return NULL; +#else + if (_PyString_Resize(&str, len) < 0) return NULL; +#endif + return (str); +} + +static char _mysql_string_literal__doc__[] = +"string_literal(obj) -- converts object obj into a SQL string literal.\n\ +This means, any special SQL characters are escaped, and it is enclosed\n\ +within single quotes. In other words, it performs:\n\ +\n\ +\"'%s'\" % escape_string(str(obj))\n\ +\n\ +Use connection.string_literal(obj), if you use it at all.\n\ +_mysql.string_literal(obj) cannot handle character sets."; + +static PyObject * +_mysql_string_literal( + _mysql_ConnectionObject *self, + PyObject *args) +{ + PyObject *str, *s, *o, *d; + char *in, *out; + int len, size; + if (!PyArg_ParseTuple(args, "O|O:string_literal", &o, &d)) return NULL; + s = PyObject_Str(o); + if (!s) return NULL; +#ifdef IS_PY3K + in = PyUnicode_AS_DATA(s); + size = PyUnicode_GetSize(s); + str = PyUnicode_FromStringAndSize((char *) NULL, size*2+3); + if (!str) return PyErr_NoMemory(); + out = PyUnicode_AS_DATA(str); +#else + in = PyString_AsString(s); + size = PyString_GET_SIZE(s); + str = PyString_FromStringAndSize((char *) NULL, size*2+3); + if (!str) return PyErr_NoMemory(); + out = PyString_AS_STRING(str); +#endif +#if MYSQL_VERSION_ID < 32321 + len = mysql_escape_string(out+1, in, size); +#else + check_server_init(NULL); + if (self && self->open) + len = mysql_real_escape_string(&(self->connection), out+1, in, size); + else + len = mysql_escape_string(out+1, in, size); +#endif + *out = *(out+len+1) = '\''; +#ifdef IS_PY3K + if (PyUnicode_Resize(&str, len+2) < 0) return NULL; +#else + if (_PyString_Resize(&str, len+2) < 0) return NULL; +#endif + Py_DECREF(s); + return (str); +} + +static PyObject *_mysql_NULL; + +static PyObject * +_escape_item( + PyObject *item, + PyObject *d) +{ + PyObject *quoted=NULL, *itemtype, *itemconv; + if (!(itemtype = PyObject_Type(item))) + goto error; + itemconv = PyObject_GetItem(d, itemtype); + Py_DECREF(itemtype); + if (!itemconv) { + PyErr_Clear(); + itemconv = PyObject_GetItem(d, +#ifdef IS_PY3K + (PyObject *) &PyUnicode_Type); +#else + (PyObject *) &PyString_Type); +#endif + } + if (!itemconv) { + PyErr_SetString(PyExc_TypeError, + "no default type converter defined"); + goto error; + } + Py_INCREF(d); + quoted = PyObject_CallFunction(itemconv, "OO", item, d); + Py_DECREF(d); + Py_DECREF(itemconv); +error: + return quoted; +} + +static char _mysql_escape__doc__[] = +"escape(obj, dict) -- escape any special characters in object obj\n\ +using mapping dict to provide quoting functions for each type.\n\ +Returns a SQL literal string."; +static PyObject * +_mysql_escape( + PyObject *self, + PyObject *args) +{ + PyObject *o=NULL, *d=NULL; + if (!PyArg_ParseTuple(args, "O|O:escape", &o, &d)) + return NULL; + if (d) { + if (!PyMapping_Check(d)) { + PyErr_SetString(PyExc_TypeError, + "argument 2 must be a mapping"); + return NULL; + } + return _escape_item(o, d); + } else { + if (!self) { + PyErr_SetString(PyExc_TypeError, + "argument 2 must be a mapping"); + return NULL; + } + return _escape_item(o, + ((_mysql_ConnectionObject *) self)->converter); + } +} + +static char _mysql_escape_sequence__doc__[] = +"escape_sequence(seq, dict) -- escape any special characters in sequence\n\ +seq using mapping dict to provide quoting functions for each type.\n\ +Returns a tuple of escaped items."; +static PyObject * +_mysql_escape_sequence( + PyObject *self, + PyObject *args) +{ + PyObject *o=NULL, *d=NULL, *r=NULL, *item, *quoted; + int i, n; + if (!PyArg_ParseTuple(args, "OO:escape_sequence", &o, &d)) + goto error; + if (!PyMapping_Check(d)) { + PyErr_SetString(PyExc_TypeError, + "argument 2 must be a mapping"); + return NULL; + } + if ((n = PyObject_Length(o)) == -1) goto error; + if (!(r = PyTuple_New(n))) goto error; + for (i=0; iresult); + fields = mysql_fetch_fields(self->result); + if (!(d = PyTuple_New(n))) return NULL; + for (i=0; iresult); + fields = mysql_fetch_fields(self->result); + if (!(d = PyTuple_New(n))) return NULL; + for (i=0; iresult); + if (!(r = PyTuple_New(n))) return NULL; + length = mysql_fetch_lengths(self->result); + for (i=0; iconverter, i); + v = _mysql_field_to_python(c, row[i], length[i]); + if (!v) goto error; + PyTuple_SET_ITEM(r, i, v); + } + return r; + error: + Py_XDECREF(r); + return NULL; +} + +static PyObject * +_mysql_row_to_dict( + _mysql_ResultObject *self, + MYSQL_ROW row) +{ + unsigned int n, i; + unsigned long *length; + PyObject *r, *c; + MYSQL_FIELD *fields; + + n = mysql_num_fields(self->result); + if (!(r = PyDict_New())) return NULL; + length = mysql_fetch_lengths(self->result); + fields = mysql_fetch_fields(self->result); + for (i=0; iconverter, i); + v = _mysql_field_to_python(c, row[i], length[i]); + if (!v) goto error; + if (!PyMapping_HasKeyString(r, fields[i].name)) { + PyMapping_SetItemString(r, fields[i].name, v); + } else { + int len; + char buf[256]; + strncpy(buf, fields[i].table, 256); + len = strlen(buf); + strncat(buf, ".", 256-len); + len = strlen(buf); + strncat(buf, fields[i].name, 256-len); + PyMapping_SetItemString(r, buf, v); + } + Py_DECREF(v); + } + return r; + error: + Py_XDECREF(r); + return NULL; +} + +static PyObject * +_mysql_row_to_dict_old( + _mysql_ResultObject *self, + MYSQL_ROW row) +{ + unsigned int n, i; + unsigned long *length; + PyObject *r, *c; + MYSQL_FIELD *fields; + + n = mysql_num_fields(self->result); + if (!(r = PyDict_New())) return NULL; + length = mysql_fetch_lengths(self->result); + fields = mysql_fetch_fields(self->result); + for (i=0; iconverter, i); + v = _mysql_field_to_python(c, row[i], length[i]); + if (!v) goto error; + { + int len=0; + char buf[256]=""; + if (strlen(fields[i].table)) { + strncpy(buf, fields[i].table, 256); + len = strlen(buf); + strncat(buf, ".", 256-len); + len = strlen(buf); + } + strncat(buf, fields[i].name, 256-len); + PyMapping_SetItemString(r, buf, v); + } + Py_DECREF(v); + } + return r; + error: + Py_XDECREF(r); + return NULL; +} + +typedef PyObject *_PYFUNC(_mysql_ResultObject *, MYSQL_ROW); + +int +_mysql__fetch_row( + _mysql_ResultObject *self, + PyObject **r, + int skiprows, + int maxrows, + _PYFUNC *convert_row) +{ + unsigned int i; + MYSQL_ROW row; + + for (i = skiprows; i<(skiprows+maxrows); i++) { + PyObject *v; + if (!self->use) + row = mysql_fetch_row(self->result); + else { + Py_BEGIN_ALLOW_THREADS; + row = mysql_fetch_row(self->result); + Py_END_ALLOW_THREADS; + } + if (!row && mysql_errno(&(((_mysql_ConnectionObject *)(self->conn))->connection))) { + _mysql_Exception((_mysql_ConnectionObject *)self->conn); + goto error; + } + if (!row) { + if (MyTuple_Resize(r, i, 0) == -1) goto error; + break; + } + v = convert_row(self, row); + if (!v) goto error; + PyTuple_SET_ITEM(*r, i, v); + } + return i-skiprows; + error: + return -1; +} + +static char _mysql_ResultObject_fetch_row__doc__[] = +"fetch_row([maxrows, how]) -- Fetches up to maxrows as a tuple.\n\ +The rows are formatted according to how:\n\ +\n\ + 0 -- tuples (default)\n\ + 1 -- dictionaries, key=column or table.column if duplicated\n\ + 2 -- dictionaries, key=table.column\n\ +"; + +static PyObject * +_mysql_ResultObject_fetch_row( + _mysql_ResultObject *self, + PyObject *args, + PyObject *kwargs) +{ + typedef PyObject *_PYFUNC(_mysql_ResultObject *, MYSQL_ROW); + static char *kwlist[] = { "maxrows", "how", NULL }; + static _PYFUNC *row_converters[] = + { + _mysql_row_to_tuple, + _mysql_row_to_dict, + _mysql_row_to_dict_old + }; + _PYFUNC *convert_row; + unsigned int maxrows=1, how=0, skiprows=0, rowsadded; + PyObject *r=NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii:fetch_row", kwlist, + &maxrows, &how)) + return NULL; + check_result_connection(self); + if (how < 0 || how >= sizeof(row_converters)) { + PyErr_SetString(PyExc_ValueError, "how out of range"); + return NULL; + } + convert_row = row_converters[how]; + if (maxrows) { + if (!(r = PyTuple_New(maxrows))) goto error; + rowsadded = _mysql__fetch_row(self, &r, skiprows, maxrows, + convert_row); + if (rowsadded == -1) goto error; + } else { + if (self->use) { + maxrows = 1000; + if (!(r = PyTuple_New(maxrows))) goto error; + while (1) { + rowsadded = _mysql__fetch_row(self, &r, skiprows, + maxrows, convert_row); + if (rowsadded == -1) goto error; + skiprows += rowsadded; + if (rowsadded < maxrows) break; + if (MyTuple_Resize(&r, skiprows+maxrows, 0) == -1) + goto error; + } + } else { + /* XXX if overflow, maxrows<0? */ + maxrows = (int) mysql_num_rows(self->result); + if (!(r = PyTuple_New(maxrows))) goto error; + rowsadded = _mysql__fetch_row(self, &r, 0, + maxrows, convert_row); + if (rowsadded == -1) goto error; + } + } + return r; + error: + Py_XDECREF(r); + return NULL; +} + +#if MYSQL_VERSION_ID >= 32303 + +static char _mysql_ConnectionObject_change_user__doc__[] = +"Changes the user and causes the database specified by db to\n\ +become the default (current) database on the connection\n\ +specified by mysql. In subsequent queries, this database is\n\ +the default for table references that do not include an\n\ +explicit database specifier.\n\ +\n\ +This function was introduced in MySQL Version 3.23.3.\n\ +\n\ +Fails unless the connected user can be authenticated or if he\n\ +doesn't have permission to use the database. In this case the\n\ +user and database are not changed.\n\ +\n\ +The db parameter may be set to None if you don't want to have\n\ +a default database.\n\ +"; + +static PyObject * +_mysql_ConnectionObject_change_user( + _mysql_ConnectionObject *self, + PyObject *args, + PyObject *kwargs) +{ + char *user, *pwd=NULL, *db=NULL; + int r; + static char *kwlist[] = { "user", "passwd", "db", NULL } ; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|ss:change_user", + kwlist, &user, &pwd, &db)) + return NULL; + check_connection(self); + Py_BEGIN_ALLOW_THREADS + r = mysql_change_user(&(self->connection), user, pwd, db); + Py_END_ALLOW_THREADS + if (r) return _mysql_Exception(self); + Py_INCREF(Py_None); + return Py_None; +} +#endif + +static char _mysql_ConnectionObject_character_set_name__doc__[] = +"Returns the default character set for the current connection.\n\ +Non-standard.\n\ +"; + +static PyObject * +_mysql_ConnectionObject_character_set_name( + _mysql_ConnectionObject *self, + PyObject *args) +{ + const char *s; + if (!PyArg_ParseTuple(args, "")) return NULL; + check_connection(self); +#if MYSQL_VERSION_ID >= 32321 + s = mysql_character_set_name(&(self->connection)); +#else + s = "latin1"; +#endif +#ifdef IS_PY3K + return PyUnicode_FromString(s); +#else + return PyString_FromString(s); +#endif +} + +#if MYSQL_VERSION_ID >= 50007 +static char _mysql_ConnectionObject_set_character_set__doc__[] = +"Sets the default character set for the current connection.\n\ +Non-standard.\n\ +"; + +static PyObject * +_mysql_ConnectionObject_set_character_set( + _mysql_ConnectionObject *self, + PyObject *args) +{ + const char *s; + int err; + if (!PyArg_ParseTuple(args, "s", &s)) return NULL; + check_connection(self); + Py_BEGIN_ALLOW_THREADS + err = mysql_set_character_set(&(self->connection), s); + Py_END_ALLOW_THREADS + if (err) return _mysql_Exception(self); + Py_INCREF(Py_None); + return Py_None; +} +#endif + +#if MYSQL_VERSION_ID >= 50010 +static char _mysql_ConnectionObject_get_character_set_info__doc__[] = +"Returns a dict with information about the current character set:\n\ +\n\ +collation\n\ + collation name\n\ +name\n\ + character set name\n\ +comment\n\ + comment or descriptive name\n\ +dir\n\ + character set directory\n\ +mbminlen\n\ + min. length for multibyte string\n\ +mbmaxlen\n\ + max. length for multibyte string\n\ +\n\ +Not all keys may be present, particularly dir.\n\ +\n\ +Non-standard.\n\ +"; + +static PyObject * +_mysql_ConnectionObject_get_character_set_info( + _mysql_ConnectionObject *self, + PyObject *args) +{ + PyObject *result; + MY_CHARSET_INFO cs; + + if (!PyArg_ParseTuple(args, "")) return NULL; + check_connection(self); + mysql_get_character_set_info(&(self->connection), &cs); + if (!(result = PyDict_New())) return NULL; +#ifdef IS_PY3K + if (cs.csname) + PyDict_SetItemString(result, "name", PyUnicode_FromString(cs.csname)); + if (cs.name) + PyDict_SetItemString(result, "collation", PyUnicode_FromString(cs.name)); + if (cs.comment) + PyDict_SetItemString(result, "comment", PyUnicode_FromString(cs.comment)); + if (cs.dir) + PyDict_SetItemString(result, "dir", PyUnicode_FromString(cs.dir)); + PyDict_SetItemString(result, "mbminlen", PyInt_FromLong(cs.mbminlen)); + PyDict_SetItemString(result, "mbmaxlen", PyInt_FromLong(cs.mbmaxlen)); +#else + if (cs.csname) + PyDict_SetItemString(result, "name", PyString_FromString(cs.csname)); + if (cs.name) + PyDict_SetItemString(result, "collation", PyString_FromString(cs.name)); + if (cs.comment) + PyDict_SetItemString(result, "comment", PyString_FromString(cs.comment)); + if (cs.dir) + PyDict_SetItemString(result, "dir", PyString_FromString(cs.dir)); + PyDict_SetItemString(result, "mbminlen", PyInt_FromLong(cs.mbminlen)); + PyDict_SetItemString(result, "mbmaxlen", PyInt_FromLong(cs.mbmaxlen)); +#endif + return result; +} +#endif + +static char _mysql_get_client_info__doc__[] = +"get_client_info() -- Returns a string that represents\n\ +the client library version."; +static PyObject * +_mysql_get_client_info( + PyObject *self, + PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) return NULL; + check_server_init(NULL); +#ifdef IS_PY3K + return PyUnicode_FromString(mysql_get_client_info()); +#else + return PyString_FromString(mysql_get_client_info()); +#endif +} + +static char _mysql_ConnectionObject_get_host_info__doc__[] = +"Returns a string that represents the MySQL client library\n\ +version. Non-standard.\n\ +"; + +static PyObject * +_mysql_ConnectionObject_get_host_info( + _mysql_ConnectionObject *self, + PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) return NULL; + check_connection(self); +#ifdef IS_PY3K + return PyUnicode_FromString(mysql_get_host_info(&(self->connection))); +#else + return PyString_FromString(mysql_get_host_info(&(self->connection))); +#endif +} + +static char _mysql_ConnectionObject_get_proto_info__doc__[] = +"Returns an unsigned integer representing the protocol version\n\ +used by the current connection. Non-standard.\n\ +"; + +static PyObject * +_mysql_ConnectionObject_get_proto_info( + _mysql_ConnectionObject *self, + PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) return NULL; + check_connection(self); + return PyInt_FromLong((long)mysql_get_proto_info(&(self->connection))); +} + +static char _mysql_ConnectionObject_get_server_info__doc__[] = +"Returns a string that represents the server version number.\n\ +Non-standard.\n\ +"; + +static PyObject * +_mysql_ConnectionObject_get_server_info( + _mysql_ConnectionObject *self, + PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) return NULL; + check_connection(self); +#ifdef IS_PY3K + return PyUnicode_FromString(mysql_get_server_info(&(self->connection))); +#else + return PyString_FromString(mysql_get_server_info(&(self->connection))); +#endif +} + +static char _mysql_ConnectionObject_info__doc__[] = +"Retrieves a string providing information about the most\n\ +recently executed query. Non-standard. Use messages or\n\ +Cursor.messages.\n\ +"; + +static PyObject * +_mysql_ConnectionObject_info( + _mysql_ConnectionObject *self, + PyObject *args) +{ + const char *s; + if (!PyArg_ParseTuple(args, "")) return NULL; + check_connection(self); + s = mysql_info(&(self->connection)); +#ifdef IS_PY3K + if (s) return PyUnicode_FromString(s); +#else + if (s) return PyString_FromString(s); +#endif + Py_INCREF(Py_None); + return Py_None; +} + +static char _mysql_ConnectionObject_insert_id__doc__[] = +"Returns the ID generated for an AUTO_INCREMENT column by the previous\n\ +query. Use this function after you have performed an INSERT query into a\n\ +table that contains an AUTO_INCREMENT field.\n\ +\n\ +Note that this returns 0 if the previous query does not\n\ +generate an AUTO_INCREMENT value. If you need to save the value for\n\ +later, be sure to call this immediately after the query\n\ +that generates the value.\n\ +\n\ +The ID is updated after INSERT and UPDATE statements that generate\n\ +an AUTO_INCREMENT value or that set a column value to\n\ +LAST_INSERT_ID(expr). See section 6.3.5.2 Miscellaneous Functions\n\ +in the MySQL documentation.\n\ +\n\ +Also note that the value of the SQL LAST_INSERT_ID() function always\n\ +contains the most recently generated AUTO_INCREMENT value, and is not\n\ +reset between queries because the value of that function is maintained\n\ +in the server.\n\ +" ; + +static PyObject * +_mysql_ConnectionObject_insert_id( + _mysql_ConnectionObject *self, + PyObject *args) +{ + my_ulonglong r; + if (!PyArg_ParseTuple(args, "")) return NULL; + check_connection(self); + Py_BEGIN_ALLOW_THREADS + r = mysql_insert_id(&(self->connection)); + Py_END_ALLOW_THREADS + return PyLong_FromUnsignedLongLong(r); +} + +static char _mysql_ConnectionObject_kill__doc__[] = +"Asks the server to kill the thread specified by pid.\n\ +Non-standard."; + +static PyObject * +_mysql_ConnectionObject_kill( + _mysql_ConnectionObject *self, + PyObject *args) +{ + unsigned long pid; + int r; + if (!PyArg_ParseTuple(args, "k:kill", &pid)) return NULL; + check_connection(self); + Py_BEGIN_ALLOW_THREADS + r = mysql_kill(&(self->connection), pid); + Py_END_ALLOW_THREADS + if (r) return _mysql_Exception(self); + Py_INCREF(Py_None); + return Py_None; +} + +static char _mysql_ConnectionObject_field_count__doc__[] = +"Returns the number of columns for the most recent query on the\n\ +connection. Non-standard. Will probably give you bogus results\n\ +on most cursor classes. Use Cursor.rowcount.\n\ +"; + +static PyObject * +_mysql_ConnectionObject_field_count( + _mysql_ConnectionObject *self, + PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) return NULL; + check_connection(self); +#if MYSQL_VERSION_ID < 32224 + return PyInt_FromLong((long)mysql_num_fields(&(self->connection))); +#else + return PyInt_FromLong((long)mysql_field_count(&(self->connection))); +#endif +} + +static char _mysql_ResultObject_num_fields__doc__[] = +"Returns the number of fields (column) in the result." ; + +static PyObject * +_mysql_ResultObject_num_fields( + _mysql_ResultObject *self, + PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) return NULL; + check_result_connection(self); + return PyInt_FromLong((long)mysql_num_fields(self->result)); +} + +static char _mysql_ResultObject_num_rows__doc__[] = +"Returns the number of rows in the result set. Note that if\n\ +use=1, this will not return a valid value until the entire result\n\ +set has been read.\n\ +"; + +static PyObject * +_mysql_ResultObject_num_rows( + _mysql_ResultObject *self, + PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) return NULL; + check_result_connection(self); + return PyLong_FromUnsignedLongLong(mysql_num_rows(self->result)); +} + +static char _mysql_ConnectionObject_ping__doc__[] = +"Checks whether or not the connection to the server is\n\ +working. If it has gone down, an automatic reconnection is\n\ +attempted.\n\ +\n\ +This function can be used by clients that remain idle for a\n\ +long while, to check whether or not the server has closed the\n\ +connection and reconnect if necessary.\n\ +\n\ +New in 1.2.2: Accepts an optional reconnect parameter. If True,\n\ +then the client will attempt reconnection. Note that this setting\n\ +is persistent. By default, this is on in MySQL<5.0.3, and off\n\ +thereafter.\n\ +\n\ +Non-standard. You should assume that ping() performs an\n\ +implicit rollback; use only when starting a new transaction.\n\ +You have been warned.\n\ +"; + +static PyObject * +_mysql_ConnectionObject_ping( + _mysql_ConnectionObject *self, + PyObject *args) +{ + int r, reconnect = -1; + if (!PyArg_ParseTuple(args, "|I", &reconnect)) return NULL; + check_connection(self); + if ( reconnect != -1 ) self->connection.reconnect = reconnect; + Py_BEGIN_ALLOW_THREADS + r = mysql_ping(&(self->connection)); + Py_END_ALLOW_THREADS + if (r) return _mysql_Exception(self); + Py_INCREF(Py_None); + return Py_None; +} + +static char _mysql_ConnectionObject_query__doc__[] = +"Execute a query. store_result() or use_result() will get the\n\ +result set, if any. Non-standard. Use cursor() to create a cursor,\n\ +then cursor.execute().\n\ +" ; + +static PyObject * +_mysql_ConnectionObject_query( + _mysql_ConnectionObject *self, + PyObject *args) +{ + char *query; + int len, r; + if (!PyArg_ParseTuple(args, "s#:query", &query, &len)) return NULL; + check_connection(self); + Py_BEGIN_ALLOW_THREADS + r = mysql_real_query(&(self->connection), query, len); + Py_END_ALLOW_THREADS + if (r) return _mysql_Exception(self); + Py_INCREF(Py_None); + return Py_None; +} + + +static char _mysql_ConnectionObject_select_db__doc__[] = +"Causes the database specified by db to become the default\n\ +(current) database on the connection specified by mysql. In subsequent\n\ +queries, this database is the default for table references that do not\n\ +include an explicit database specifier.\n\ +\n\ +Fails unless the connected user can be authenticated as having\n\ +permission to use the database.\n\ +\n\ +Non-standard.\n\ +"; + +static PyObject * +_mysql_ConnectionObject_select_db( + _mysql_ConnectionObject *self, + PyObject *args) +{ + char *db; + int r; + if (!PyArg_ParseTuple(args, "s:select_db", &db)) return NULL; + check_connection(self); + Py_BEGIN_ALLOW_THREADS + r = mysql_select_db(&(self->connection), db); + Py_END_ALLOW_THREADS + if (r) return _mysql_Exception(self); + Py_INCREF(Py_None); + return Py_None; +} + +static char _mysql_ConnectionObject_shutdown__doc__[] = +"Asks the database server to shut down. The connected user must\n\ +have shutdown privileges. Non-standard.\n\ +"; + +static PyObject * +_mysql_ConnectionObject_shutdown( + _mysql_ConnectionObject *self, + PyObject *args) +{ + int r; + if (!PyArg_ParseTuple(args, "")) return NULL; + check_connection(self); + Py_BEGIN_ALLOW_THREADS + r = mysql_shutdown(&(self->connection) +#if MYSQL_VERSION_ID >= 40103 + , SHUTDOWN_DEFAULT +#endif + ); + Py_END_ALLOW_THREADS + if (r) return _mysql_Exception(self); + Py_INCREF(Py_None); + return Py_None; +} + +static char _mysql_ConnectionObject_stat__doc__[] = +"Returns a character string containing information similar to\n\ +that provided by the mysqladmin status command. This includes\n\ +uptime in seconds and the number of running threads,\n\ +questions, reloads, and open tables. Non-standard.\n\ +"; + +static PyObject * +_mysql_ConnectionObject_stat( + _mysql_ConnectionObject *self, + PyObject *args) +{ + const char *s; + if (!PyArg_ParseTuple(args, "")) return NULL; + check_connection(self); + Py_BEGIN_ALLOW_THREADS + s = mysql_stat(&(self->connection)); + Py_END_ALLOW_THREADS + if (!s) return _mysql_Exception(self); +#ifdef IS_PY3K + return PyUnicode_FromString(s); +#else + return PyString_FromString(s); +#endif + +} + +static char _mysql_ConnectionObject_store_result__doc__[] = +"Returns a result object acquired by mysql_store_result\n\ +(results stored in the client). If no results are available,\n\ +None is returned. Non-standard.\n\ +"; + +static PyObject * +_mysql_ConnectionObject_store_result( + _mysql_ConnectionObject *self, + PyObject *args) +{ + PyObject *arglist=NULL, *kwarglist=NULL, *result=NULL; + _mysql_ResultObject *r=NULL; + + if (!PyArg_ParseTuple(args, "")) return NULL; + check_connection(self); + arglist = Py_BuildValue("(OiO)", self, 0, self->converter); + if (!arglist) goto error; + kwarglist = PyDict_New(); + if (!kwarglist) goto error; + r = MyAlloc(_mysql_ResultObject, _mysql_ResultObject_Type); + if (!r) goto error; + if (_mysql_ResultObject_Initialize(r, arglist, kwarglist)) + goto error; + result = (PyObject *) r; + if (!(r->result)) { + Py_DECREF(result); + Py_INCREF(Py_None); + result = Py_None; + } + error: + Py_XDECREF(arglist); + Py_XDECREF(kwarglist); + return result; +} + +static char _mysql_ConnectionObject_thread_id__doc__[] = +"Returns the thread ID of the current connection. This value\n\ +can be used as an argument to kill() to kill the thread.\n\ +\n\ +If the connection is lost and you reconnect with ping(), the\n\ +thread ID will change. This means you should not get the\n\ +thread ID and store it for later. You should get it when you\n\ +need it.\n\ +\n\ +Non-standard."; + +static PyObject * +_mysql_ConnectionObject_thread_id( + _mysql_ConnectionObject *self, + PyObject *args) +{ + unsigned long pid; + if (!PyArg_ParseTuple(args, "")) return NULL; + check_connection(self); + Py_BEGIN_ALLOW_THREADS + pid = mysql_thread_id(&(self->connection)); + Py_END_ALLOW_THREADS + return PyInt_FromLong((long)pid); +} + +static char _mysql_ConnectionObject_use_result__doc__[] = +"Returns a result object acquired by mysql_use_result\n\ +(results stored in the server). If no results are available,\n\ +None is returned. Non-standard.\n\ +"; + +static PyObject * +_mysql_ConnectionObject_use_result( + _mysql_ConnectionObject *self, + PyObject *args) +{ + PyObject *arglist=NULL, *kwarglist=NULL, *result=NULL; + _mysql_ResultObject *r=NULL; + + if (!PyArg_ParseTuple(args, "")) return NULL; + check_connection(self); + arglist = Py_BuildValue("(OiO)", self, 1, self->converter); + if (!arglist) return NULL; + kwarglist = PyDict_New(); + if (!kwarglist) goto error; + r = MyAlloc(_mysql_ResultObject, _mysql_ResultObject_Type); + if (!r) goto error; + result = (PyObject *) r; + if (_mysql_ResultObject_Initialize(r, arglist, kwarglist)) + goto error; + if (!(r->result)) { + Py_DECREF(result); + Py_INCREF(Py_None); + result = Py_None; + } + error: + Py_DECREF(arglist); + Py_XDECREF(kwarglist); + return result; +} + +static void +_mysql_ConnectionObject_dealloc( + _mysql_ConnectionObject *self) +{ + PyObject *o; + + PyObject_GC_UnTrack(self); + if (self->open) { + o = _mysql_ConnectionObject_close(self, NULL); + Py_XDECREF(o); + } + MyFree(self); +} + +static PyObject * +_mysql_ConnectionObject_repr( + _mysql_ConnectionObject *self) +{ + char buf[300]; + if (self->open) + sprintf(buf, "<_mysql.connection open to '%.256s' at %lx>", + self->connection.host, + (long)self); + else + sprintf(buf, "<_mysql.connection closed at %lx>", + (long)self); +#ifdef IS_PY3K + return PyUnicode_FromString(buf); +#else + return PyString_FromString(buf); +#endif +} + +static char _mysql_ResultObject_data_seek__doc__[] = +"data_seek(n) -- seek to row n of result set"; +static PyObject * +_mysql_ResultObject_data_seek( + _mysql_ResultObject *self, + PyObject *args) +{ + unsigned int row; + if (!PyArg_ParseTuple(args, "i:data_seek", &row)) return NULL; + check_result_connection(self); + mysql_data_seek(self->result, row); + Py_INCREF(Py_None); + return Py_None; +} + +static char _mysql_ResultObject_row_seek__doc__[] = +"row_seek(n) -- seek by offset n rows of result set"; +static PyObject * +_mysql_ResultObject_row_seek( + _mysql_ResultObject *self, + PyObject *args) +{ + int offset; + MYSQL_ROW_OFFSET r; + if (!PyArg_ParseTuple(args, "i:row_seek", &offset)) return NULL; + check_result_connection(self); + if (self->use) { + PyErr_SetString(_mysql_ProgrammingError, + "cannot be used with connection.use_result()"); + return NULL; + } + r = mysql_row_tell(self->result); + mysql_row_seek(self->result, r+offset); + Py_INCREF(Py_None); + return Py_None; +} + +static char _mysql_ResultObject_row_tell__doc__[] = +"row_tell() -- return the current row number of the result set."; +static PyObject * +_mysql_ResultObject_row_tell( + _mysql_ResultObject *self, + PyObject *args) +{ + MYSQL_ROW_OFFSET r; + if (!PyArg_ParseTuple(args, "")) return NULL; + check_result_connection(self); + if (self->use) { + PyErr_SetString(_mysql_ProgrammingError, + "cannot be used with connection.use_result()"); + return NULL; + } + r = mysql_row_tell(self->result); + return PyInt_FromLong(r-self->result->data->data); +} + +static void +_mysql_ResultObject_dealloc( + _mysql_ResultObject *self) +{ + PyObject_GC_UnTrack((PyObject *)self); + mysql_free_result(self->result); + _mysql_ResultObject_clear(self); + MyFree(self); +} + +static PyObject * +_mysql_ResultObject_repr( + _mysql_ResultObject *self) +{ + char buf[300]; + sprintf(buf, "<_mysql.result object at %lx>", + (long)self); +#ifdef IS_PY3K + return PyUnicode_FromString(buf); +#else + return PyString_FromString(buf); +#endif +} + +static PyMethodDef _mysql_ConnectionObject_methods[] = { + { + "affected_rows", + (PyCFunction)_mysql_ConnectionObject_affected_rows, + METH_VARARGS, + _mysql_ConnectionObject_affected_rows__doc__ + }, + { + "autocommit", + (PyCFunction)_mysql_ConnectionObject_autocommit, + METH_VARARGS, + _mysql_ConnectionObject_autocommit__doc__ + }, + { + "get_autocommit", + (PyCFunction)_mysql_ConnectionObject_get_autocommit, + METH_NOARGS, + _mysql_ConnectionObject_get_autocommit__doc__ + }, + { + "commit", + (PyCFunction)_mysql_ConnectionObject_commit, + METH_VARARGS, + _mysql_ConnectionObject_commit__doc__ + }, + { + "rollback", + (PyCFunction)_mysql_ConnectionObject_rollback, + METH_VARARGS, + _mysql_ConnectionObject_rollback__doc__ + }, + { + "next_result", + (PyCFunction)_mysql_ConnectionObject_next_result, + METH_VARARGS, + _mysql_ConnectionObject_next_result__doc__ + }, +#if MYSQL_VERSION_ID >= 40100 + { + "set_server_option", + (PyCFunction)_mysql_ConnectionObject_set_server_option, + METH_VARARGS, + _mysql_ConnectionObject_set_server_option__doc__ + }, + { + "sqlstate", + (PyCFunction)_mysql_ConnectionObject_sqlstate, + METH_VARARGS, + _mysql_ConnectionObject_sqlstate__doc__ + }, + { + "warning_count", + (PyCFunction)_mysql_ConnectionObject_warning_count, + METH_VARARGS, + _mysql_ConnectionObject_warning_count__doc__ + }, +#endif +#if MYSQL_VERSION_ID >= 32303 + { + "change_user", + (PyCFunction)_mysql_ConnectionObject_change_user, + METH_VARARGS | METH_KEYWORDS, + _mysql_ConnectionObject_change_user__doc__ + }, +#endif + { + "character_set_name", + (PyCFunction)_mysql_ConnectionObject_character_set_name, + METH_VARARGS, + _mysql_ConnectionObject_character_set_name__doc__ + }, +#if MYSQL_VERSION_ID >= 50007 + { + "set_character_set", + (PyCFunction)_mysql_ConnectionObject_set_character_set, + METH_VARARGS, + _mysql_ConnectionObject_set_character_set__doc__ + }, +#endif +#if MYSQL_VERSION_ID >= 50010 + { + "get_character_set_info", + (PyCFunction)_mysql_ConnectionObject_get_character_set_info, + METH_VARARGS, + _mysql_ConnectionObject_get_character_set_info__doc__ + }, +#endif + { + "close", + (PyCFunction)_mysql_ConnectionObject_close, + METH_VARARGS, + _mysql_ConnectionObject_close__doc__ + }, + { + "dump_debug_info", + (PyCFunction)_mysql_ConnectionObject_dump_debug_info, + METH_VARARGS, + _mysql_ConnectionObject_dump_debug_info__doc__ + }, + { + "escape", + (PyCFunction)_mysql_escape, + METH_VARARGS, + _mysql_escape__doc__ + }, + { + "escape_string", + (PyCFunction)_mysql_escape_string, + METH_VARARGS, + _mysql_escape_string__doc__ + }, + { + "error", + (PyCFunction)_mysql_ConnectionObject_error, + METH_VARARGS, + _mysql_ConnectionObject_error__doc__ + }, + { + "errno", + (PyCFunction)_mysql_ConnectionObject_errno, + METH_VARARGS, + _mysql_ConnectionObject_errno__doc__ + }, + { + "field_count", + (PyCFunction)_mysql_ConnectionObject_field_count, + METH_VARARGS, + _mysql_ConnectionObject_field_count__doc__ + }, + { + "get_host_info", + (PyCFunction)_mysql_ConnectionObject_get_host_info, + METH_VARARGS, + _mysql_ConnectionObject_get_host_info__doc__ + }, + { + "get_proto_info", + (PyCFunction)_mysql_ConnectionObject_get_proto_info, + METH_VARARGS, + _mysql_ConnectionObject_get_proto_info__doc__ + }, + { + "get_server_info", + (PyCFunction)_mysql_ConnectionObject_get_server_info, + METH_VARARGS, + _mysql_ConnectionObject_get_server_info__doc__ + }, + { + "info", + (PyCFunction)_mysql_ConnectionObject_info, + METH_VARARGS, + _mysql_ConnectionObject_info__doc__ + }, + { + "insert_id", + (PyCFunction)_mysql_ConnectionObject_insert_id, + METH_VARARGS, + _mysql_ConnectionObject_insert_id__doc__ + }, + { + "kill", + (PyCFunction)_mysql_ConnectionObject_kill, + METH_VARARGS, + _mysql_ConnectionObject_kill__doc__ + }, + { + "ping", + (PyCFunction)_mysql_ConnectionObject_ping, + METH_VARARGS, + _mysql_ConnectionObject_ping__doc__ + }, + { + "query", + (PyCFunction)_mysql_ConnectionObject_query, + METH_VARARGS, + _mysql_ConnectionObject_query__doc__ + }, + { + "select_db", + (PyCFunction)_mysql_ConnectionObject_select_db, + METH_VARARGS, + _mysql_ConnectionObject_select_db__doc__ + }, + { + "shutdown", + (PyCFunction)_mysql_ConnectionObject_shutdown, + METH_VARARGS, + _mysql_ConnectionObject_shutdown__doc__ + }, + { + "stat", + (PyCFunction)_mysql_ConnectionObject_stat, + METH_VARARGS, + _mysql_ConnectionObject_stat__doc__ + }, + { + "store_result", + (PyCFunction)_mysql_ConnectionObject_store_result, + METH_VARARGS, + _mysql_ConnectionObject_store_result__doc__ + }, + { + "string_literal", + (PyCFunction)_mysql_string_literal, + METH_VARARGS, + _mysql_string_literal__doc__}, + { + "thread_id", + (PyCFunction)_mysql_ConnectionObject_thread_id, + METH_VARARGS, + _mysql_ConnectionObject_thread_id__doc__ + }, + { + "use_result", + (PyCFunction)_mysql_ConnectionObject_use_result, + METH_VARARGS, + _mysql_ConnectionObject_use_result__doc__ + }, + {NULL, NULL} /* sentinel */ +}; + +static MyMemberlist(_mysql_ConnectionObject_memberlist)[] = { + MyMember( + "open", + T_INT, + offsetof(_mysql_ConnectionObject,open), + READONLY, + "True if connection is open" + ), + MyMember( + "converter", + T_OBJECT, + offsetof(_mysql_ConnectionObject,converter), + 0, + "Type conversion mapping" + ), + MyMember( + "server_capabilities", + T_UINT, + offsetof(_mysql_ConnectionObject,connection.server_capabilities), + READONLY, + "Capabilites of server; consult MySQLdb.constants.CLIENT" + ), + MyMember( + "port", + T_UINT, + offsetof(_mysql_ConnectionObject,connection.port), + READONLY, + "TCP/IP port of the server connection" + ), + MyMember( + "client_flag", + T_UINT, + READONLY, + offsetof(_mysql_ConnectionObject,connection.client_flag), + "Client flags; refer to MySQLdb.constants.CLIENT" + ), + {NULL} /* Sentinel */ +}; + +static PyMethodDef _mysql_ResultObject_methods[] = { + { + "data_seek", + (PyCFunction)_mysql_ResultObject_data_seek, + METH_VARARGS, + _mysql_ResultObject_data_seek__doc__ + }, + { + "row_seek", + (PyCFunction)_mysql_ResultObject_row_seek, + METH_VARARGS, + _mysql_ResultObject_row_seek__doc__ + }, + { + "row_tell", + (PyCFunction)_mysql_ResultObject_row_tell, + METH_VARARGS, + _mysql_ResultObject_row_tell__doc__ + }, + { + "describe", + (PyCFunction)_mysql_ResultObject_describe, + METH_VARARGS, + _mysql_ResultObject_describe__doc__ + }, + { + "fetch_row", + (PyCFunction)_mysql_ResultObject_fetch_row, + METH_VARARGS | METH_KEYWORDS, + _mysql_ResultObject_fetch_row__doc__ + }, + { + "field_flags", + (PyCFunction)_mysql_ResultObject_field_flags, + METH_VARARGS, + _mysql_ResultObject_field_flags__doc__ + }, + { + "num_fields", + (PyCFunction)_mysql_ResultObject_num_fields, + METH_VARARGS, + _mysql_ResultObject_num_fields__doc__ + }, + { + "num_rows", + (PyCFunction)_mysql_ResultObject_num_rows, + METH_VARARGS, + _mysql_ResultObject_num_rows__doc__ + }, + {NULL, NULL} /* sentinel */ +}; + +static MyMemberlist(_mysql_ResultObject_memberlist)[] = { + MyMember( + "converter", + T_OBJECT, + offsetof(_mysql_ResultObject,converter), + READONLY, + "Type conversion mapping" + ), + {NULL} /* Sentinel */ +}; + +static PyObject * +_mysql_ConnectionObject_getattr( + _mysql_ConnectionObject *self, + char *name) +{ +#ifndef IS_PY3K + PyObject *res; + + res = Py_FindMethod(_mysql_ConnectionObject_methods, (PyObject *)self, name); + if (res != NULL) + return res; + PyErr_Clear(); +#endif + if (strcmp(name, "closed") == 0) + return PyInt_FromLong((long)!(self->open)); +#if PY_VERSION_HEX < 0x02020000 + return PyMember_Get((char *)self, _mysql_ConnectionObject_memberlist, name); +#else + { + MyMemberlist(*l); + for (l = _mysql_ConnectionObject_memberlist; l->name != NULL; l++) { + if (strcmp(l->name, name) == 0) + return PyMember_GetOne((char *)self, l); + } + PyErr_SetString(PyExc_AttributeError, name); + return NULL; + } +#endif +} + +static PyObject * +_mysql_ResultObject_getattr( + _mysql_ResultObject *self, + char *name) +{ +#ifndef IS_PY3K + PyObject *res; + + res = Py_FindMethod(_mysql_ResultObject_methods, (PyObject *)self, name); + if (res != NULL) + return res; + PyErr_Clear(); +#endif +#if PY_VERSION_HEX < 0x02020000 + return PyMember_Get((char *)self, _mysql_ResultObject_memberlist, name); +#else + { + MyMemberlist(*l); + for (l = _mysql_ResultObject_memberlist; l->name != NULL; l++) { + if (strcmp(l->name, name) == 0) + return PyMember_GetOne((char *)self, l); + } + PyErr_SetString(PyExc_AttributeError, name); + return NULL; + } +#endif +} + +static int +_mysql_ConnectionObject_setattr( + _mysql_ConnectionObject *self, + char *name, + PyObject *v) +{ + if (v == NULL) { + PyErr_SetString(PyExc_AttributeError, + "can't delete connection attributes"); + return -1; + } +#if PY_VERSION_HEX < 0x02020000 + return PyMember_Set((char *)self, _mysql_ConnectionObject_memberlist, name, v); +#else + { + MyMemberlist(*l); + for (l = _mysql_ConnectionObject_memberlist; l->name != NULL; l++) + if (strcmp(l->name, name) == 0) + return PyMember_SetOne((char *)self, l, v); + } + PyErr_SetString(PyExc_AttributeError, name); + return -1; +#endif +} + +static int +_mysql_ResultObject_setattr( + _mysql_ResultObject *self, + char *name, + PyObject *v) +{ + if (v == NULL) { + PyErr_SetString(PyExc_AttributeError, + "can't delete connection attributes"); + return -1; + } +#if PY_VERSION_HEX < 0x02020000 + return PyMember_Set((char *)self, _mysql_ResultObject_memberlist, name, v); +#else + { + MyMemberlist(*l); + for (l = _mysql_ResultObject_memberlist; l->name != NULL; l++) + if (strcmp(l->name, name) == 0) + return PyMember_SetOne((char *)self, l, v); + } + PyErr_SetString(PyExc_AttributeError, name); + return -1; +#endif +} + +PyTypeObject _mysql_ConnectionObject_Type = { +#ifdef IS_PY3K + PyVarObject_HEAD_INIT(NULL, 0) +#else + PyObject_HEAD_INIT(NULL) + 0, +#endif + "_mysql.connection", /* (char *)tp_name For printing */ + sizeof(_mysql_ConnectionObject), + 0, + (destructor)_mysql_ConnectionObject_dealloc, /* tp_dealloc */ + 0, /*tp_print*/ + (getattrfunc)_mysql_ConnectionObject_getattr, /* tp_getattr */ + (setattrfunc)_mysql_ConnectionObject_setattr, /* tp_setattr */ + 0, /*tp_compare*/ + (reprfunc)_mysql_ConnectionObject_repr, /* tp_repr */ + + /* Method suites for standard classes */ + + 0, /* (PyNumberMethods *) tp_as_number */ + 0, /* (PySequenceMethods *) tp_as_sequence */ + 0, /* (PyMappingMethods *) tp_as_mapping */ + + /* More standard operations (here for binary compatibility) */ + + 0, /* (hashfunc) tp_hash */ + 0, /* (ternaryfunc) tp_call */ + 0, /* (reprfunc) tp_str */ + 0, /* (getattrofunc) tp_getattro */ + 0, /* (setattrofunc) tp_setattro */ + + /* Functions to access object as input/output buffer */ + 0, /* (PyBufferProcs *) tp_as_buffer */ + + /* Flags to define presence of optional/expanded features */ +#if PY_VERSION_HEX < 0x02020000 + Py_TPFLAGS_DEFAULT, /* (long) tp_flags */ +#else + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, +#endif + _mysql_connect__doc__, /* (char *) tp_doc Documentation string */ +#if PY_VERSION_HEX >= 0x02000000 + /* Assigned meaning in release 2.0 */ +#if PY_VERSION_HEX >= 0x02020000 + /* call function for all accessible objects */ + (traverseproc) _mysql_ConnectionObject_traverse, /* tp_traverse */ + + /* delete references to contained objects */ + (inquiry) _mysql_ConnectionObject_clear, /* tp_clear */ +#else + /* not supporting pre-2.2 GC */ + 0, + 0, +#endif +#if PY_VERSION_HEX >= 0x02010000 + /* Assigned meaning in release 2.1 */ + /* rich comparisons */ + 0, /* (richcmpfunc) tp_richcompare */ + + /* weak reference enabler */ + 0, /* (long) tp_weaklistoffset */ +#if PY_VERSION_HEX >= 0x02020000 + /* Added in release 2.2 */ + /* Iterators */ + 0, /* (getiterfunc) tp_iter */ + 0, /* (iternextfunc) tp_iternext */ + + /* Attribute descriptor and subclassing stuff */ + (struct PyMethodDef *)_mysql_ConnectionObject_methods, /* tp_methods */ + (MyMemberlist(*))_mysql_ConnectionObject_memberlist, /* tp_members */ + 0, /* (struct getsetlist *) tp_getset; */ + 0, /* (struct _typeobject *) tp_base; */ + 0, /* (PyObject *) tp_dict */ + 0, /* (descrgetfunc) tp_descr_get */ + 0, /* (descrsetfunc) tp_descr_set */ + 0, /* (long) tp_dictoffset */ + (initproc)_mysql_ConnectionObject_Initialize, /* tp_init */ + NULL, /* tp_alloc */ + NULL, /* tp_new */ + NULL, /* tp_free Low-level free-memory routine */ + 0, /* (PyObject *) tp_bases */ + 0, /* (PyObject *) tp_mro method resolution order */ + 0, /* (PyObject *) tp_defined */ +#endif /* python 2.2 */ +#endif /* python 2.1 */ +#endif /* python 2.0 */ +} ; + +PyTypeObject _mysql_ResultObject_Type = { +#ifdef IS_PY3K + PyVarObject_HEAD_INIT(NULL, 0) +#else + PyObject_HEAD_INIT(NULL) + 0, +#endif + "_mysql.result", + sizeof(_mysql_ResultObject), + 0, + (destructor)_mysql_ResultObject_dealloc, /* tp_dealloc */ + 0, /*tp_print*/ + (getattrfunc)_mysql_ResultObject_getattr, /* tp_getattr */ + (setattrfunc)_mysql_ResultObject_setattr, /* tp_setattr */ + 0, /*tp_compare*/ + (reprfunc)_mysql_ResultObject_repr, /* tp_repr */ + + /* Method suites for standard classes */ + + 0, /* (PyNumberMethods *) tp_as_number */ + 0, /* (PySequenceMethods *) tp_as_sequence */ + 0, /* (PyMappingMethods *) tp_as_mapping */ + + /* More standard operations (here for binary compatibility) */ + + 0, /* (hashfunc) tp_hash */ + 0, /* (ternaryfunc) tp_call */ + 0, /* (reprfunc) tp_str */ + 0, /* (getattrofunc) tp_getattro */ + 0, /* (setattrofunc) tp_setattro */ + + /* Functions to access object as input/output buffer */ + 0, /* (PyBufferProcs *) tp_as_buffer */ + + /* Flags to define presence of optional/expanded features */ +#if PY_VERSION_HEX < 0x02020000 + Py_TPFLAGS_DEFAULT, /* (long) tp_flags */ +#else + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, +#endif + + _mysql_ResultObject__doc__, /* (char *) tp_doc Documentation string */ +#if PY_VERSION_HEX >= 0x02000000 + /* Assigned meaning in release 2.0 */ +#if PY_VERSION_HEX >= 0x02020000 + /* call function for all accessible objects */ + (traverseproc) _mysql_ResultObject_traverse, /* tp_traverse */ + + /* delete references to contained objects */ + (inquiry) _mysql_ResultObject_clear, /* tp_clear */ +#else + /* not supporting pre-2.2 GC */ + 0, + 0, +#endif +#if PY_VERSION_HEX >= 0x02010000 + /* Assigned meaning in release 2.1 */ + /* rich comparisons */ + 0, /* (richcmpfunc) tp_richcompare */ + + /* weak reference enabler */ + 0, /* (long) tp_weaklistoffset */ +#if PY_VERSION_HEX >= 0x02020000 + /* Added in release 2.2 */ + /* Iterators */ + 0, /* (getiterfunc) tp_iter */ + 0, /* (iternextfunc) tp_iternext */ + + /* Attribute descriptor and subclassing stuff */ + (struct PyMethodDef *) _mysql_ResultObject_methods, /* tp_methods */ + (MyMemberlist(*)) _mysql_ResultObject_memberlist, /*tp_members */ + 0, /* (struct getsetlist *) tp_getset; */ + 0, /* (struct _typeobject *) tp_base; */ + 0, /* (PyObject *) tp_dict */ + 0, /* (descrgetfunc) tp_descr_get */ + 0, /* (descrsetfunc) tp_descr_set */ + 0, /* (long) tp_dictoffset */ + (initproc)_mysql_ResultObject_Initialize, /* tp_init */ + NULL, /* tp_alloc */ + NULL, /* tp_new */ + NULL, /* tp_free Low-level free-memory routine */ + 0, /* (PyObject *) tp_bases */ + 0, /* (PyObject *) tp_mro method resolution order */ + 0, /* (PyObject *) tp_defined */ +#endif /* python 2.2 */ +#endif /* python 2.1 */ +#endif /* python 2.0 */ +}; + +static PyMethodDef +_mysql_methods[] = { + { + "connect", + (PyCFunction)_mysql_connect, + METH_VARARGS | METH_KEYWORDS, + _mysql_connect__doc__ + }, + { + "debug", + (PyCFunction)_mysql_debug, + METH_VARARGS, + _mysql_debug__doc__ + }, + { + "escape", + (PyCFunction)_mysql_escape, + METH_VARARGS, + _mysql_escape__doc__ + }, + { + "escape_sequence", + (PyCFunction)_mysql_escape_sequence, + METH_VARARGS, + _mysql_escape_sequence__doc__ + }, + { + "escape_dict", + (PyCFunction)_mysql_escape_dict, + METH_VARARGS, + _mysql_escape_dict__doc__ + }, + { + "escape_string", + (PyCFunction)_mysql_escape_string, + METH_VARARGS, + _mysql_escape_string__doc__ + }, + { + "string_literal", + (PyCFunction)_mysql_string_literal, + METH_VARARGS, + _mysql_string_literal__doc__ + }, + { + "get_client_info", + (PyCFunction)_mysql_get_client_info, + METH_VARARGS, + _mysql_get_client_info__doc__ + }, +#if MYSQL_VERSION_ID >= 32314 + { + "thread_safe", + (PyCFunction)_mysql_thread_safe, + METH_VARARGS, + _mysql_thread_safe__doc__ + }, +#endif + { + "server_init", + (PyCFunction)_mysql_server_init, + METH_VARARGS | METH_KEYWORDS, + _mysql_server_init__doc__ + }, + { + "server_end", + (PyCFunction)_mysql_server_end, + METH_VARARGS, + _mysql_server_end__doc__ + }, + {NULL, NULL} /* sentinel */ +}; + +static PyObject * +_mysql_NewException( + PyObject *dict, + PyObject *edict, + char *name) +{ + PyObject *e; + + if (!(e = PyDict_GetItemString(edict, name))) + return NULL; + if (PyDict_SetItemString(dict, name, e)) return NULL; +#ifdef PYPY_VERSION + Py_INCREF(e); +#endif + return e; +} + +#define QUOTE(X) _QUOTE(X) +#define _QUOTE(X) #X + +static char _mysql___doc__[] = +"an adaptation of the MySQL C API (mostly)\n\ +\n\ +You probably are better off using MySQLdb instead of using this\n\ +module directly.\n\ +\n\ +In general, renaming goes from mysql_* to _mysql.*. _mysql.connect()\n\ +returns a connection object (MYSQL). Functions which expect MYSQL * as\n\ +an argument are now methods of the connection object. A number of things\n\ +return result objects (MYSQL_RES). Functions which expect MYSQL_RES * as\n\ +an argument are now methods of the result object. Deprecated functions\n\ +(as of 3.23) are NOT implemented.\n\ +"; + +#ifdef IS_PY3K +static struct PyModuleDef _mysqlmodule = { + PyModuleDef_HEAD_INIT, + "_mysql", /* name of module */ + _mysql___doc__, /* module documentation, may be NULL */ + -1, /* size of per-interpreter state of the module, + or -1 if the module keeps state in global variables. */ + _mysql_methods +}; + +PyMODINIT_FUNC +PyInit__mysql(void) +#else +DL_EXPORT(void) +init_mysql(void) +#endif +{ + PyObject *dict, *module, *emod, *edict; +#ifdef IS_PY3K + module = PyModule_Create(&_mysqlmodule); + if (!module) return module; /* this really should never happen */ +#else + module = Py_InitModule4("_mysql", _mysql_methods, _mysql___doc__, + (PyObject *)NULL, PYTHON_API_VERSION); + if (!module) return; /* this really should never happen */ +#endif +#ifdef IS_PY3K + Py_TYPE(&_mysql_ConnectionObject_Type) = &PyType_Type; + Py_TYPE(&_mysql_ResultObject_Type) = &PyType_Type; +#else + _mysql_ConnectionObject_Type.ob_type = &PyType_Type; + _mysql_ResultObject_Type.ob_type = &PyType_Type; +#endif +#if PY_VERSION_HEX >= 0x02020000 + _mysql_ConnectionObject_Type.tp_alloc = PyType_GenericAlloc; + _mysql_ConnectionObject_Type.tp_new = PyType_GenericNew; +#ifndef IS_PY3K + _mysql_ConnectionObject_Type.tp_free = _PyObject_GC_Del; +#endif + _mysql_ResultObject_Type.tp_alloc = PyType_GenericAlloc; + _mysql_ResultObject_Type.tp_new = PyType_GenericNew; +#ifndef IS_PY3K + _mysql_ResultObject_Type.tp_free = _PyObject_GC_Del; +#endif +#endif + + if (!(dict = PyModule_GetDict(module))) goto error; + if (PyDict_SetItemString(dict, "version_info", + PyRun_String(QUOTE(version_info), Py_eval_input, + dict, dict))) + goto error; + if (PyDict_SetItemString(dict, "__version__", +#ifdef IS_PY3K + PyUnicode_FromString(QUOTE(__version__)))) +#else + PyString_FromString(QUOTE(__version__)))) +#endif + goto error; + if (PyDict_SetItemString(dict, "connection", + (PyObject *)&_mysql_ConnectionObject_Type)) + goto error; + Py_INCREF(&_mysql_ConnectionObject_Type); + if (PyDict_SetItemString(dict, "result", + (PyObject *)&_mysql_ResultObject_Type)) + goto error; + Py_INCREF(&_mysql_ResultObject_Type); + if (!(emod = PyImport_ImportModule("_mysql_exceptions"))) { + PyErr_Print(); + goto error; + } + if (!(edict = PyModule_GetDict(emod))) goto error; + if (!(_mysql_MySQLError = + _mysql_NewException(dict, edict, "MySQLError"))) + goto error; + if (!(_mysql_Warning = + _mysql_NewException(dict, edict, "Warning"))) + goto error; + if (!(_mysql_Error = + _mysql_NewException(dict, edict, "Error"))) + goto error; + if (!(_mysql_InterfaceError = + _mysql_NewException(dict, edict, "InterfaceError"))) + goto error; + if (!(_mysql_DatabaseError = + _mysql_NewException(dict, edict, "DatabaseError"))) + goto error; + if (!(_mysql_DataError = + _mysql_NewException(dict, edict, "DataError"))) + goto error; + if (!(_mysql_OperationalError = + _mysql_NewException(dict, edict, "OperationalError"))) + goto error; + if (!(_mysql_IntegrityError = + _mysql_NewException(dict, edict, "IntegrityError"))) + goto error; + if (!(_mysql_InternalError = + _mysql_NewException(dict, edict, "InternalError"))) + goto error; + if (!(_mysql_ProgrammingError = + _mysql_NewException(dict, edict, "ProgrammingError"))) + goto error; + if (!(_mysql_NotSupportedError = + _mysql_NewException(dict, edict, "NotSupportedError"))) + goto error; + Py_DECREF(emod); +#ifdef IS_PY3K + if (!(_mysql_NULL = PyUnicode_FromString("NULL"))) + goto error; +#else + if (!(_mysql_NULL = PyString_FromString("NULL"))) + goto error; +#endif + if (PyDict_SetItemString(dict, "NULL", _mysql_NULL)) goto error; + error: + if (PyErr_Occurred()) { + PyErr_SetString(PyExc_ImportError, + "_mysql: init failed"); + module = NULL; + } +#ifdef IS_PY3K + return module; +#endif +} + + diff --git a/lib/mysql/_mysql_exceptions.py b/lib/mysql/_mysql_exceptions.py new file mode 100644 index 00000000..3241e740 --- /dev/null +++ b/lib/mysql/_mysql_exceptions.py @@ -0,0 +1,87 @@ +"""_mysql_exceptions: Exception classes for _mysql and MySQLdb. + +These classes are dictated by the DB API v2.0: + + http://www.python.org/topics/database/DatabaseAPI-2.0.html +""" + +try: + from exceptions import Exception, StandardError, Warning +except ImportError: + # Python 3 + StandardError = Exception + + +class MySQLError(StandardError): + + """Exception related to operation with MySQL.""" + + +class Warning(Warning, MySQLError): + + """Exception raised for important warnings like data truncations + while inserting, etc.""" + +class Error(MySQLError): + + """Exception that is the base class of all other error exceptions + (not Warning).""" + + +class InterfaceError(Error): + + """Exception raised for errors that are related to the database + interface rather than the database itself.""" + + +class DatabaseError(Error): + + """Exception raised for errors that are related to the + database.""" + + +class DataError(DatabaseError): + + """Exception raised for errors that are due to problems with the + processed data like division by zero, numeric value out of range, + etc.""" + + +class OperationalError(DatabaseError): + + """Exception raised for errors that are related to the database's + operation and not necessarily under the control of the programmer, + e.g. an unexpected disconnect occurs, the data source name is not + found, a transaction could not be processed, a memory allocation + error occurred during processing, etc.""" + + +class IntegrityError(DatabaseError): + + """Exception raised when the relational integrity of the database + is affected, e.g. a foreign key check fails, duplicate key, + etc.""" + + +class InternalError(DatabaseError): + + """Exception raised when the database encounters an internal + error, e.g. the cursor is not valid anymore, the transaction is + out of sync, etc.""" + + +class ProgrammingError(DatabaseError): + + """Exception raised for programming errors, e.g. table not found + or already exists, syntax error in the SQL statement, wrong number + of parameters specified, etc.""" + + +class NotSupportedError(DatabaseError): + + """Exception raised in case a method or database API was used + which is not supported by the database, e.g. requesting a + .rollback() on a connection that does not support transaction or + has transactions turned off.""" + + diff --git a/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/__init__.py b/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/__init__.py new file mode 100644 index 00000000..dc18e876 --- /dev/null +++ b/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/__init__.py @@ -0,0 +1,98 @@ +"""MySQLdb - A DB API v2.0 compatible interface to MySQL. + +This package is a wrapper around _mysql, which mostly implements the +MySQL C API. + +connect() -- connects to server + +See the C API specification and the MySQL documentation for more info +on other items. + +For information on how MySQLdb handles type conversion, see the +MySQLdb.converters module. + +""" + +__revision__ = """$Revision$"""[11:-2] +from MySQLdb.release import __version__, version_info, __author__ + +import _mysql + +if version_info != _mysql.version_info: + raise ImportError("this is MySQLdb version %s, but _mysql is version %r" % + (version_info, _mysql.version_info)) + +threadsafety = 1 +apilevel = "2.0" +paramstyle = "format" + +from _mysql import * +from MySQLdb.constants import FIELD_TYPE +from MySQLdb.times import Date, Time, Timestamp, \ + DateFromTicks, TimeFromTicks, TimestampFromTicks + +try: + frozenset +except NameError: + from sets import ImmutableSet as frozenset + +class DBAPISet(frozenset): + + """A special type of set for which A == x is true if A is a + DBAPISet and x is a member of that set.""" + + def __eq__(self, other): + if isinstance(other, DBAPISet): + return not self.difference(other) + return other in self + + +STRING = DBAPISet([FIELD_TYPE.ENUM, FIELD_TYPE.STRING, + FIELD_TYPE.VAR_STRING]) +BINARY = DBAPISet([FIELD_TYPE.BLOB, FIELD_TYPE.LONG_BLOB, + FIELD_TYPE.MEDIUM_BLOB, FIELD_TYPE.TINY_BLOB]) +NUMBER = DBAPISet([FIELD_TYPE.DECIMAL, FIELD_TYPE.DOUBLE, FIELD_TYPE.FLOAT, + FIELD_TYPE.INT24, FIELD_TYPE.LONG, FIELD_TYPE.LONGLONG, + FIELD_TYPE.TINY, FIELD_TYPE.YEAR]) +DATE = DBAPISet([FIELD_TYPE.DATE, FIELD_TYPE.NEWDATE]) +TIME = DBAPISet([FIELD_TYPE.TIME]) +TIMESTAMP = DBAPISet([FIELD_TYPE.TIMESTAMP, FIELD_TYPE.DATETIME]) +DATETIME = TIMESTAMP +ROWID = DBAPISet() + +def test_DBAPISet_set_equality(): + assert STRING == STRING + +def test_DBAPISet_set_inequality(): + assert STRING != NUMBER + +def test_DBAPISet_set_equality_membership(): + assert FIELD_TYPE.VAR_STRING == STRING + +def test_DBAPISet_set_inequality_membership(): + assert FIELD_TYPE.DATE != STRING + +def Binary(x): + return str(x) + +def Connect(*args, **kwargs): + """Factory function for connections.Connection.""" + from MySQLdb.connections import Connection + return Connection(*args, **kwargs) + +connect = Connection = Connect + +__all__ = [ 'BINARY', 'Binary', 'Connect', 'Connection', 'DATE', + 'Date', 'Time', 'Timestamp', 'DateFromTicks', 'TimeFromTicks', + 'TimestampFromTicks', 'DataError', 'DatabaseError', 'Error', + 'FIELD_TYPE', 'IntegrityError', 'InterfaceError', 'InternalError', + 'MySQLError', 'NULL', 'NUMBER', 'NotSupportedError', 'DBAPISet', + 'OperationalError', 'ProgrammingError', 'ROWID', 'STRING', 'TIME', + 'TIMESTAMP', 'Warning', 'apilevel', 'connect', 'connections', + 'constants', 'converters', 'cursors', 'debug', 'escape', 'escape_dict', + 'escape_sequence', 'escape_string', 'get_client_info', + 'paramstyle', 'string_literal', 'threadsafety', 'version_info'] + + + + diff --git a/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/connections.py b/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/connections.py new file mode 100644 index 00000000..ac885cea --- /dev/null +++ b/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/connections.py @@ -0,0 +1,351 @@ +""" + +This module implements connections for MySQLdb. Presently there is +only one class: Connection. Others are unlikely. However, you might +want to make your own subclasses. In most cases, you will probably +override Connection.default_cursor with a non-standard Cursor class. + +""" +from MySQLdb import cursors +from _mysql_exceptions import Warning, Error, InterfaceError, DataError, \ + DatabaseError, OperationalError, IntegrityError, InternalError, \ + NotSupportedError, ProgrammingError +import types, _mysql +import re + + +def defaulterrorhandler(connection, cursor, errorclass, errorvalue): + """ + + If cursor is not None, (errorclass, errorvalue) is appended to + cursor.messages; otherwise it is appended to + connection.messages. Then errorclass is raised with errorvalue as + the value. + + You can override this with your own error handler by assigning it + to the instance. + + """ + error = errorclass, errorvalue + if cursor: + cursor.messages.append(error) + else: + connection.messages.append(error) + del cursor + del connection + raise errorclass, errorvalue + +re_numeric_part = re.compile(r"^(\d+)") + +def numeric_part(s): + """Returns the leading numeric part of a string. + + >>> numeric_part("20-alpha") + 20 + >>> numeric_part("foo") + >>> numeric_part("16b") + 16 + """ + + m = re_numeric_part.match(s) + if m: + return int(m.group(1)) + return None + + +class Connection(_mysql.connection): + + """MySQL Database Connection Object""" + + default_cursor = cursors.Cursor + + def __init__(self, *args, **kwargs): + """ + + Create a connection to the database. It is strongly recommended + that you only use keyword parameters. Consult the MySQL C API + documentation for more information. + + host + string, host to connect + + user + string, user to connect as + + passwd + string, password to use + + db + string, database to use + + port + integer, TCP/IP port to connect to + + unix_socket + string, location of unix_socket to use + + conv + conversion dictionary, see MySQLdb.converters + + connect_timeout + number of seconds to wait before the connection attempt + fails. + + compress + if set, compression is enabled + + named_pipe + if set, a named pipe is used to connect (Windows only) + + init_command + command which is run once the connection is created + + read_default_file + file from which default client values are read + + read_default_group + configuration group to use from the default file + + cursorclass + class object, used to create cursors (keyword only) + + use_unicode + If True, text-like columns are returned as unicode objects + using the connection's character set. Otherwise, text-like + columns are returned as strings. columns are returned as + normal strings. Unicode objects will always be encoded to + the connection's character set regardless of this setting. + + charset + If supplied, the connection character set will be changed + to this character set (MySQL-4.1 and newer). This implies + use_unicode=True. + + sql_mode + If supplied, the session SQL mode will be changed to this + setting (MySQL-4.1 and newer). For more details and legal + values, see the MySQL documentation. + + client_flag + integer, flags to use or 0 + (see MySQL docs or constants/CLIENTS.py) + + ssl + dictionary or mapping, contains SSL connection parameters; + see the MySQL documentation for more details + (mysql_ssl_set()). If this is set, and the client does not + support SSL, NotSupportedError will be raised. + + local_infile + integer, non-zero enables LOAD LOCAL INFILE; zero disables + + autocommit + If False (default), autocommit is disabled. + If True, autocommit is enabled. + If None, autocommit isn't set and server default is used. + + There are a number of undocumented, non-standard methods. See the + documentation for the MySQL C API for some hints on what they do. + + """ + from MySQLdb.constants import CLIENT, FIELD_TYPE + from MySQLdb.converters import conversions + from weakref import proxy + + kwargs2 = kwargs.copy() + + if 'conv' in kwargs: + conv = kwargs['conv'] + else: + conv = conversions + + conv2 = {} + for k, v in conv.items(): + if isinstance(k, int) and isinstance(v, list): + conv2[k] = v[:] + else: + conv2[k] = v + kwargs2['conv'] = conv2 + + cursorclass = kwargs2.pop('cursorclass', self.default_cursor) + charset = kwargs2.pop('charset', '') + + if charset: + use_unicode = True + else: + use_unicode = False + + use_unicode = kwargs2.pop('use_unicode', use_unicode) + sql_mode = kwargs2.pop('sql_mode', '') + + client_flag = kwargs.get('client_flag', 0) + client_version = tuple([ numeric_part(n) for n in _mysql.get_client_info().split('.')[:2] ]) + if client_version >= (4, 1): + client_flag |= CLIENT.MULTI_STATEMENTS + if client_version >= (5, 0): + client_flag |= CLIENT.MULTI_RESULTS + + kwargs2['client_flag'] = client_flag + + # PEP-249 requires autocommit to be initially off + autocommit = kwargs2.pop('autocommit', False) + + super(Connection, self).__init__(*args, **kwargs2) + self.cursorclass = cursorclass + self.encoders = dict([ (k, v) for k, v in conv.items() + if type(k) is not int ]) + + self._server_version = tuple([ numeric_part(n) for n in self.get_server_info().split('.')[:2] ]) + + db = proxy(self) + def _get_string_literal(): + def string_literal(obj, dummy=None): + return db.string_literal(obj) + return string_literal + + def _get_unicode_literal(): + def unicode_literal(u, dummy=None): + return db.literal(u.encode(unicode_literal.charset)) + return unicode_literal + + def _get_string_decoder(): + def string_decoder(s): + return s.decode(string_decoder.charset) + return string_decoder + + string_literal = _get_string_literal() + self.unicode_literal = unicode_literal = _get_unicode_literal() + self.string_decoder = string_decoder = _get_string_decoder() + if not charset: + charset = self.character_set_name() + self.set_character_set(charset) + + if sql_mode: + self.set_sql_mode(sql_mode) + + if use_unicode: + self.converter[FIELD_TYPE.STRING].append((None, string_decoder)) + self.converter[FIELD_TYPE.VAR_STRING].append((None, string_decoder)) + self.converter[FIELD_TYPE.VARCHAR].append((None, string_decoder)) + self.converter[FIELD_TYPE.BLOB].append((None, string_decoder)) + + self.encoders[types.StringType] = string_literal + self.encoders[types.UnicodeType] = unicode_literal + self._transactional = self.server_capabilities & CLIENT.TRANSACTIONS + if self._transactional: + if autocommit is not None: + self.autocommit(autocommit) + self.messages = [] + + def autocommit(self, on): + on = bool(on) + if self.get_autocommit() != on: + _mysql.connection.autocommit(self, on) + + def cursor(self, cursorclass=None): + """ + + Create a cursor on which queries may be performed. The + optional cursorclass parameter is used to create the + Cursor. By default, self.cursorclass=cursors.Cursor is + used. + + """ + return (cursorclass or self.cursorclass)(self) + + def __enter__(self): + if self.get_autocommit(): + self.query("BEGIN") + return self.cursor() + + def __exit__(self, exc, value, tb): + if exc: + self.rollback() + else: + self.commit() + + def literal(self, o): + """ + + If o is a single object, returns an SQL literal as a string. + If o is a non-string sequence, the items of the sequence are + converted and returned as a sequence. + + Non-standard. For internal use; do not use this in your + applications. + + """ + return self.escape(o, self.encoders) + + def begin(self): + """Explicitly begin a connection. Non-standard. + DEPRECATED: Will be removed in 1.3. + Use an SQL BEGIN statement instead.""" + from warnings import warn + warn("begin() is non-standard and will be removed in 1.3", + DeprecationWarning, 2) + self.query("BEGIN") + + if not hasattr(_mysql.connection, 'warning_count'): + + def warning_count(self): + """Return the number of warnings generated from the + last query. This is derived from the info() method.""" + from string import atoi + info = self.info() + if info: + return atoi(info.split()[-1]) + else: + return 0 + + def set_character_set(self, charset): + """Set the connection character set to charset. The character + set can only be changed in MySQL-4.1 and newer. If you try + to change the character set from the current value in an + older version, NotSupportedError will be raised.""" + if charset == "utf8mb4": + py_charset = "utf8" + else: + py_charset = charset + if self.character_set_name() != charset: + try: + super(Connection, self).set_character_set(charset) + except AttributeError: + if self._server_version < (4, 1): + raise NotSupportedError("server is too old to set charset") + self.query('SET NAMES %s' % charset) + self.store_result() + self.string_decoder.charset = py_charset + self.unicode_literal.charset = py_charset + + def set_sql_mode(self, sql_mode): + """Set the connection sql_mode. See MySQL documentation for + legal values.""" + if self._server_version < (4, 1): + raise NotSupportedError("server is too old to set sql_mode") + self.query("SET SESSION sql_mode='%s'" % sql_mode) + self.store_result() + + def show_warnings(self): + """Return detailed information about warnings as a + sequence of tuples of (Level, Code, Message). This + is only supported in MySQL-4.1 and up. If your server + is an earlier version, an empty sequence is returned.""" + if self._server_version < (4,1): return () + self.query("SHOW WARNINGS") + r = self.store_result() + warnings = r.fetch_row(0) + return warnings + + Warning = Warning + Error = Error + InterfaceError = InterfaceError + DatabaseError = DatabaseError + DataError = DataError + OperationalError = OperationalError + IntegrityError = IntegrityError + InternalError = InternalError + ProgrammingError = ProgrammingError + NotSupportedError = NotSupportedError + + errorhandler = defaulterrorhandler diff --git a/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/constants/CLIENT.py b/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/constants/CLIENT.py new file mode 100644 index 00000000..6559917b --- /dev/null +++ b/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/constants/CLIENT.py @@ -0,0 +1,29 @@ +"""MySQL CLIENT constants + +These constants are used when creating the connection. Use bitwise-OR +(|) to combine options together, and pass them as the client_flags +parameter to MySQLdb.Connection. For more information on these flags, +see the MySQL C API documentation for mysql_real_connect(). + +""" + +LONG_PASSWORD = 1 +FOUND_ROWS = 2 +LONG_FLAG = 4 +CONNECT_WITH_DB = 8 +NO_SCHEMA = 16 +COMPRESS = 32 +ODBC = 64 +LOCAL_FILES = 128 +IGNORE_SPACE = 256 +CHANGE_USER = 512 +INTERACTIVE = 1024 +SSL = 2048 +IGNORE_SIGPIPE = 4096 +TRANSACTIONS = 8192 # mysql_com.h was WRONG prior to 3.23.35 +RESERVED = 16384 +SECURE_CONNECTION = 32768 +MULTI_STATEMENTS = 65536 +MULTI_RESULTS = 131072 + + diff --git a/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/constants/CR.py b/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/constants/CR.py new file mode 100644 index 00000000..249dfec9 --- /dev/null +++ b/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/constants/CR.py @@ -0,0 +1,30 @@ +"""MySQL Connection Errors + +Nearly all of these raise OperationalError. COMMANDS_OUT_OF_SYNC +raises ProgrammingError. + +""" + +MIN_ERROR = 2000 +MAX_ERROR = 2999 +UNKNOWN_ERROR = 2000 +SOCKET_CREATE_ERROR = 2001 +CONNECTION_ERROR = 2002 +CONN_HOST_ERROR = 2003 +IPSOCK_ERROR = 2004 +UNKNOWN_HOST = 2005 +SERVER_GONE_ERROR = 2006 +VERSION_ERROR = 2007 +OUT_OF_MEMORY = 2008 +WRONG_HOST_INFO = 2009 +LOCALHOST_CONNECTION = 2010 +TCP_CONNECTION = 2011 +SERVER_HANDSHAKE_ERR = 2012 +SERVER_LOST = 2013 +COMMANDS_OUT_OF_SYNC = 2014 +NAMEDPIPE_CONNECTION = 2015 +NAMEDPIPEWAIT_ERROR = 2016 +NAMEDPIPEOPEN_ERROR = 2017 +NAMEDPIPESETSTATE_ERROR = 2018 +CANT_READ_CHARSET = 2019 +NET_PACKET_TOO_LARGE = 2020 diff --git a/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/constants/ER.py b/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/constants/ER.py new file mode 100644 index 00000000..ed45f3a1 --- /dev/null +++ b/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/constants/ER.py @@ -0,0 +1,467 @@ +"""MySQL ER Constants + +These constants are error codes for the bulk of the error conditions +that may occur. + +""" + +HASHCHK = 1000 +NISAMCHK = 1001 +NO = 1002 +YES = 1003 +CANT_CREATE_FILE = 1004 +CANT_CREATE_TABLE = 1005 +CANT_CREATE_DB = 1006 +DB_CREATE_EXISTS = 1007 +DB_DROP_EXISTS = 1008 +DB_DROP_DELETE = 1009 +DB_DROP_RMDIR = 1010 +CANT_DELETE_FILE = 1011 +CANT_FIND_SYSTEM_REC = 1012 +CANT_GET_STAT = 1013 +CANT_GET_WD = 1014 +CANT_LOCK = 1015 +CANT_OPEN_FILE = 1016 +FILE_NOT_FOUND = 1017 +CANT_READ_DIR = 1018 +CANT_SET_WD = 1019 +CHECKREAD = 1020 +DISK_FULL = 1021 +DUP_KEY = 1022 +ERROR_ON_CLOSE = 1023 +ERROR_ON_READ = 1024 +ERROR_ON_RENAME = 1025 +ERROR_ON_WRITE = 1026 +FILE_USED = 1027 +FILSORT_ABORT = 1028 +FORM_NOT_FOUND = 1029 +GET_ERRNO = 1030 +ILLEGAL_HA = 1031 +KEY_NOT_FOUND = 1032 +NOT_FORM_FILE = 1033 +NOT_KEYFILE = 1034 +OLD_KEYFILE = 1035 +OPEN_AS_READONLY = 1036 +OUTOFMEMORY = 1037 +OUT_OF_SORTMEMORY = 1038 +UNEXPECTED_EOF = 1039 +CON_COUNT_ERROR = 1040 +OUT_OF_RESOURCES = 1041 +BAD_HOST_ERROR = 1042 +HANDSHAKE_ERROR = 1043 +DBACCESS_DENIED_ERROR = 1044 +ACCESS_DENIED_ERROR = 1045 +NO_DB_ERROR = 1046 +UNKNOWN_COM_ERROR = 1047 +BAD_NULL_ERROR = 1048 +BAD_DB_ERROR = 1049 +TABLE_EXISTS_ERROR = 1050 +BAD_TABLE_ERROR = 1051 +NON_UNIQ_ERROR = 1052 +SERVER_SHUTDOWN = 1053 +BAD_FIELD_ERROR = 1054 +WRONG_FIELD_WITH_GROUP = 1055 +WRONG_GROUP_FIELD = 1056 +WRONG_SUM_SELECT = 1057 +WRONG_VALUE_COUNT = 1058 +TOO_LONG_IDENT = 1059 +DUP_FIELDNAME = 1060 +DUP_KEYNAME = 1061 +DUP_ENTRY = 1062 +WRONG_FIELD_SPEC = 1063 +PARSE_ERROR = 1064 +EMPTY_QUERY = 1065 +NONUNIQ_TABLE = 1066 +INVALID_DEFAULT = 1067 +MULTIPLE_PRI_KEY = 1068 +TOO_MANY_KEYS = 1069 +TOO_MANY_KEY_PARTS = 1070 +TOO_LONG_KEY = 1071 +KEY_COLUMN_DOES_NOT_EXITS = 1072 +BLOB_USED_AS_KEY = 1073 +TOO_BIG_FIELDLENGTH = 1074 +WRONG_AUTO_KEY = 1075 +READY = 1076 +NORMAL_SHUTDOWN = 1077 +GOT_SIGNAL = 1078 +SHUTDOWN_COMPLETE = 1079 +FORCING_CLOSE = 1080 +IPSOCK_ERROR = 1081 +NO_SUCH_INDEX = 1082 +WRONG_FIELD_TERMINATORS = 1083 +BLOBS_AND_NO_TERMINATED = 1084 +TEXTFILE_NOT_READABLE = 1085 +FILE_EXISTS_ERROR = 1086 +LOAD_INFO = 1087 +ALTER_INFO = 1088 +WRONG_SUB_KEY = 1089 +CANT_REMOVE_ALL_FIELDS = 1090 +CANT_DROP_FIELD_OR_KEY = 1091 +INSERT_INFO = 1092 +INSERT_TABLE_USED = 1093 +NO_SUCH_THREAD = 1094 +KILL_DENIED_ERROR = 1095 +NO_TABLES_USED = 1096 +TOO_BIG_SET = 1097 +NO_UNIQUE_LOGFILE = 1098 +TABLE_NOT_LOCKED_FOR_WRITE = 1099 +TABLE_NOT_LOCKED = 1100 +BLOB_CANT_HAVE_DEFAULT = 1101 +WRONG_DB_NAME = 1102 +WRONG_TABLE_NAME = 1103 +TOO_BIG_SELECT = 1104 +UNKNOWN_ERROR = 1105 +UNKNOWN_PROCEDURE = 1106 +WRONG_PARAMCOUNT_TO_PROCEDURE = 1107 +WRONG_PARAMETERS_TO_PROCEDURE = 1108 +UNKNOWN_TABLE = 1109 +FIELD_SPECIFIED_TWICE = 1110 +INVALID_GROUP_FUNC_USE = 1111 +UNSUPPORTED_EXTENSION = 1112 +TABLE_MUST_HAVE_COLUMNS = 1113 +RECORD_FILE_FULL = 1114 +UNKNOWN_CHARACTER_SET = 1115 +TOO_MANY_TABLES = 1116 +TOO_MANY_FIELDS = 1117 +TOO_BIG_ROWSIZE = 1118 +STACK_OVERRUN = 1119 +WRONG_OUTER_JOIN = 1120 +NULL_COLUMN_IN_INDEX = 1121 +CANT_FIND_UDF = 1122 +CANT_INITIALIZE_UDF = 1123 +UDF_NO_PATHS = 1124 +UDF_EXISTS = 1125 +CANT_OPEN_LIBRARY = 1126 +CANT_FIND_DL_ENTRY = 1127 +FUNCTION_NOT_DEFINED = 1128 +HOST_IS_BLOCKED = 1129 +HOST_NOT_PRIVILEGED = 1130 +PASSWORD_ANONYMOUS_USER = 1131 +PASSWORD_NOT_ALLOWED = 1132 +PASSWORD_NO_MATCH = 1133 +UPDATE_INFO = 1134 +CANT_CREATE_THREAD = 1135 +WRONG_VALUE_COUNT_ON_ROW = 1136 +CANT_REOPEN_TABLE = 1137 +INVALID_USE_OF_NULL = 1138 +REGEXP_ERROR = 1139 +MIX_OF_GROUP_FUNC_AND_FIELDS = 1140 +NONEXISTING_GRANT = 1141 +TABLEACCESS_DENIED_ERROR = 1142 +COLUMNACCESS_DENIED_ERROR = 1143 +ILLEGAL_GRANT_FOR_TABLE = 1144 +GRANT_WRONG_HOST_OR_USER = 1145 +NO_SUCH_TABLE = 1146 +NONEXISTING_TABLE_GRANT = 1147 +NOT_ALLOWED_COMMAND = 1148 +SYNTAX_ERROR = 1149 +DELAYED_CANT_CHANGE_LOCK = 1150 +TOO_MANY_DELAYED_THREADS = 1151 +ABORTING_CONNECTION = 1152 +NET_PACKET_TOO_LARGE = 1153 +NET_READ_ERROR_FROM_PIPE = 1154 +NET_FCNTL_ERROR = 1155 +NET_PACKETS_OUT_OF_ORDER = 1156 +NET_UNCOMPRESS_ERROR = 1157 +NET_READ_ERROR = 1158 +NET_READ_INTERRUPTED = 1159 +NET_ERROR_ON_WRITE = 1160 +NET_WRITE_INTERRUPTED = 1161 +TOO_LONG_STRING = 1162 +TABLE_CANT_HANDLE_BLOB = 1163 +TABLE_CANT_HANDLE_AUTO_INCREMENT = 1164 +DELAYED_INSERT_TABLE_LOCKED = 1165 +WRONG_COLUMN_NAME = 1166 +WRONG_KEY_COLUMN = 1167 +WRONG_MRG_TABLE = 1168 +DUP_UNIQUE = 1169 +BLOB_KEY_WITHOUT_LENGTH = 1170 +PRIMARY_CANT_HAVE_NULL = 1171 +TOO_MANY_ROWS = 1172 +REQUIRES_PRIMARY_KEY = 1173 +NO_RAID_COMPILED = 1174 +UPDATE_WITHOUT_KEY_IN_SAFE_MODE = 1175 +KEY_DOES_NOT_EXITS = 1176 +CHECK_NO_SUCH_TABLE = 1177 +CHECK_NOT_IMPLEMENTED = 1178 +CANT_DO_THIS_DURING_AN_TRANSACTION = 1179 +ERROR_DURING_COMMIT = 1180 +ERROR_DURING_ROLLBACK = 1181 +ERROR_DURING_FLUSH_LOGS = 1182 +ERROR_DURING_CHECKPOINT = 1183 +NEW_ABORTING_CONNECTION = 1184 +DUMP_NOT_IMPLEMENTED = 1185 +FLUSH_MASTER_BINLOG_CLOSED = 1186 +INDEX_REBUILD = 1187 +MASTER = 1188 +MASTER_NET_READ = 1189 +MASTER_NET_WRITE = 1190 +FT_MATCHING_KEY_NOT_FOUND = 1191 +LOCK_OR_ACTIVE_TRANSACTION = 1192 +UNKNOWN_SYSTEM_VARIABLE = 1193 +CRASHED_ON_USAGE = 1194 +CRASHED_ON_REPAIR = 1195 +WARNING_NOT_COMPLETE_ROLLBACK = 1196 +TRANS_CACHE_FULL = 1197 +SLAVE_MUST_STOP = 1198 +SLAVE_NOT_RUNNING = 1199 +BAD_SLAVE = 1200 +MASTER_INFO = 1201 +SLAVE_THREAD = 1202 +TOO_MANY_USER_CONNECTIONS = 1203 +SET_CONSTANTS_ONLY = 1204 +LOCK_WAIT_TIMEOUT = 1205 +LOCK_TABLE_FULL = 1206 +READ_ONLY_TRANSACTION = 1207 +DROP_DB_WITH_READ_LOCK = 1208 +CREATE_DB_WITH_READ_LOCK = 1209 +WRONG_ARGUMENTS = 1210 +NO_PERMISSION_TO_CREATE_USER = 1211 +UNION_TABLES_IN_DIFFERENT_DIR = 1212 +LOCK_DEADLOCK = 1213 +TABLE_CANT_HANDLE_FT = 1214 +CANNOT_ADD_FOREIGN = 1215 +NO_REFERENCED_ROW = 1216 +ROW_IS_REFERENCED = 1217 +CONNECT_TO_MASTER = 1218 +QUERY_ON_MASTER = 1219 +ERROR_WHEN_EXECUTING_COMMAND = 1220 +WRONG_USAGE = 1221 +WRONG_NUMBER_OF_COLUMNS_IN_SELECT = 1222 +CANT_UPDATE_WITH_READLOCK = 1223 +MIXING_NOT_ALLOWED = 1224 +DUP_ARGUMENT = 1225 +USER_LIMIT_REACHED = 1226 +SPECIFIC_ACCESS_DENIED_ERROR = 1227 +LOCAL_VARIABLE = 1228 +GLOBAL_VARIABLE = 1229 +NO_DEFAULT = 1230 +WRONG_VALUE_FOR_VAR = 1231 +WRONG_TYPE_FOR_VAR = 1232 +VAR_CANT_BE_READ = 1233 +CANT_USE_OPTION_HERE = 1234 +NOT_SUPPORTED_YET = 1235 +MASTER_FATAL_ERROR_READING_BINLOG = 1236 +SLAVE_IGNORED_TABLE = 1237 +INCORRECT_GLOBAL_LOCAL_VAR = 1238 +WRONG_FK_DEF = 1239 +KEY_REF_DO_NOT_MATCH_TABLE_REF = 1240 +OPERAND_COLUMNS = 1241 +SUBQUERY_NO_1_ROW = 1242 +UNKNOWN_STMT_HANDLER = 1243 +CORRUPT_HELP_DB = 1244 +CYCLIC_REFERENCE = 1245 +AUTO_CONVERT = 1246 +ILLEGAL_REFERENCE = 1247 +DERIVED_MUST_HAVE_ALIAS = 1248 +SELECT_REDUCED = 1249 +TABLENAME_NOT_ALLOWED_HERE = 1250 +NOT_SUPPORTED_AUTH_MODE = 1251 +SPATIAL_CANT_HAVE_NULL = 1252 +COLLATION_CHARSET_MISMATCH = 1253 +SLAVE_WAS_RUNNING = 1254 +SLAVE_WAS_NOT_RUNNING = 1255 +TOO_BIG_FOR_UNCOMPRESS = 1256 +ZLIB_Z_MEM_ERROR = 1257 +ZLIB_Z_BUF_ERROR = 1258 +ZLIB_Z_DATA_ERROR = 1259 +CUT_VALUE_GROUP_CONCAT = 1260 +WARN_TOO_FEW_RECORDS = 1261 +WARN_TOO_MANY_RECORDS = 1262 +WARN_NULL_TO_NOTNULL = 1263 +WARN_DATA_OUT_OF_RANGE = 1264 +WARN_DATA_TRUNCATED = 1265 +WARN_USING_OTHER_HANDLER = 1266 +CANT_AGGREGATE_2COLLATIONS = 1267 +DROP_USER = 1268 +REVOKE_GRANTS = 1269 +CANT_AGGREGATE_3COLLATIONS = 1270 +CANT_AGGREGATE_NCOLLATIONS = 1271 +VARIABLE_IS_NOT_STRUCT = 1272 +UNKNOWN_COLLATION = 1273 +SLAVE_IGNORED_SSL_PARAMS = 1274 +SERVER_IS_IN_SECURE_AUTH_MODE = 1275 +WARN_FIELD_RESOLVED = 1276 +BAD_SLAVE_UNTIL_COND = 1277 +MISSING_SKIP_SLAVE = 1278 +UNTIL_COND_IGNORED = 1279 +WRONG_NAME_FOR_INDEX = 1280 +WRONG_NAME_FOR_CATALOG = 1281 +WARN_QC_RESIZE = 1282 +BAD_FT_COLUMN = 1283 +UNKNOWN_KEY_CACHE = 1284 +WARN_HOSTNAME_WONT_WORK = 1285 +UNKNOWN_STORAGE_ENGINE = 1286 +WARN_DEPRECATED_SYNTAX = 1287 +NON_UPDATABLE_TABLE = 1288 +FEATURE_DISABLED = 1289 +OPTION_PREVENTS_STATEMENT = 1290 +DUPLICATED_VALUE_IN_TYPE = 1291 +TRUNCATED_WRONG_VALUE = 1292 +TOO_MUCH_AUTO_TIMESTAMP_COLS = 1293 +INVALID_ON_UPDATE = 1294 +UNSUPPORTED_PS = 1295 +GET_ERRMSG = 1296 +GET_TEMPORARY_ERRMSG = 1297 +UNKNOWN_TIME_ZONE = 1298 +WARN_INVALID_TIMESTAMP = 1299 +INVALID_CHARACTER_STRING = 1300 +WARN_ALLOWED_PACKET_OVERFLOWED = 1301 +CONFLICTING_DECLARATIONS = 1302 +SP_NO_RECURSIVE_CREATE = 1303 +SP_ALREADY_EXISTS = 1304 +SP_DOES_NOT_EXIST = 1305 +SP_DROP_FAILED = 1306 +SP_STORE_FAILED = 1307 +SP_LILABEL_MISMATCH = 1308 +SP_LABEL_REDEFINE = 1309 +SP_LABEL_MISMATCH = 1310 +SP_UNINIT_VAR = 1311 +SP_BADSELECT = 1312 +SP_BADRETURN = 1313 +SP_BADSTATEMENT = 1314 +UPDATE_LOG_DEPRECATED_IGNORED = 1315 +UPDATE_LOG_DEPRECATED_TRANSLATED = 1316 +QUERY_INTERRUPTED = 1317 +SP_WRONG_NO_OF_ARGS = 1318 +SP_COND_MISMATCH = 1319 +SP_NORETURN = 1320 +SP_NORETURNEND = 1321 +SP_BAD_CURSOR_QUERY = 1322 +SP_BAD_CURSOR_SELECT = 1323 +SP_CURSOR_MISMATCH = 1324 +SP_CURSOR_ALREADY_OPEN = 1325 +SP_CURSOR_NOT_OPEN = 1326 +SP_UNDECLARED_VAR = 1327 +SP_WRONG_NO_OF_FETCH_ARGS = 1328 +SP_FETCH_NO_DATA = 1329 +SP_DUP_PARAM = 1330 +SP_DUP_VAR = 1331 +SP_DUP_COND = 1332 +SP_DUP_CURS = 1333 +SP_CANT_ALTER = 1334 +SP_SUBSELECT_NYI = 1335 +STMT_NOT_ALLOWED_IN_SF_OR_TRG = 1336 +SP_VARCOND_AFTER_CURSHNDLR = 1337 +SP_CURSOR_AFTER_HANDLER = 1338 +SP_CASE_NOT_FOUND = 1339 +FPARSER_TOO_BIG_FILE = 1340 +FPARSER_BAD_HEADER = 1341 +FPARSER_EOF_IN_COMMENT = 1342 +FPARSER_ERROR_IN_PARAMETER = 1343 +FPARSER_EOF_IN_UNKNOWN_PARAMETER = 1344 +VIEW_NO_EXPLAIN = 1345 +FRM_UNKNOWN_TYPE = 1346 +WRONG_OBJECT = 1347 +NONUPDATEABLE_COLUMN = 1348 +VIEW_SELECT_DERIVED = 1349 +VIEW_SELECT_CLAUSE = 1350 +VIEW_SELECT_VARIABLE = 1351 +VIEW_SELECT_TMPTABLE = 1352 +VIEW_WRONG_LIST = 1353 +WARN_VIEW_MERGE = 1354 +WARN_VIEW_WITHOUT_KEY = 1355 +VIEW_INVALID = 1356 +SP_NO_DROP_SP = 1357 +SP_GOTO_IN_HNDLR = 1358 +TRG_ALREADY_EXISTS = 1359 +TRG_DOES_NOT_EXIST = 1360 +TRG_ON_VIEW_OR_TEMP_TABLE = 1361 +TRG_CANT_CHANGE_ROW = 1362 +TRG_NO_SUCH_ROW_IN_TRG = 1363 +NO_DEFAULT_FOR_FIELD = 1364 +DIVISION_BY_ZERO = 1365 +TRUNCATED_WRONG_VALUE_FOR_FIELD = 1366 +ILLEGAL_VALUE_FOR_TYPE = 1367 +VIEW_NONUPD_CHECK = 1368 +VIEW_CHECK_FAILED = 1369 +PROCACCESS_DENIED_ERROR = 1370 +RELAY_LOG_FAIL = 1371 +PASSWD_LENGTH = 1372 +UNKNOWN_TARGET_BINLOG = 1373 +IO_ERR_LOG_INDEX_READ = 1374 +BINLOG_PURGE_PROHIBITED = 1375 +FSEEK_FAIL = 1376 +BINLOG_PURGE_FATAL_ERR = 1377 +LOG_IN_USE = 1378 +LOG_PURGE_UNKNOWN_ERR = 1379 +RELAY_LOG_INIT = 1380 +NO_BINARY_LOGGING = 1381 +RESERVED_SYNTAX = 1382 +WSAS_FAILED = 1383 +DIFF_GROUPS_PROC = 1384 +NO_GROUP_FOR_PROC = 1385 +ORDER_WITH_PROC = 1386 +LOGGING_PROHIBIT_CHANGING_OF = 1387 +NO_FILE_MAPPING = 1388 +WRONG_MAGIC = 1389 +PS_MANY_PARAM = 1390 +KEY_PART_0 = 1391 +VIEW_CHECKSUM = 1392 +VIEW_MULTIUPDATE = 1393 +VIEW_NO_INSERT_FIELD_LIST = 1394 +VIEW_DELETE_MERGE_VIEW = 1395 +CANNOT_USER = 1396 +XAER_NOTA = 1397 +XAER_INVAL = 1398 +XAER_RMFAIL = 1399 +XAER_OUTSIDE = 1400 +XAER_RMERR = 1401 +XA_RBROLLBACK = 1402 +NONEXISTING_PROC_GRANT = 1403 +PROC_AUTO_GRANT_FAIL = 1404 +PROC_AUTO_REVOKE_FAIL = 1405 +DATA_TOO_LONG = 1406 +SP_BAD_SQLSTATE = 1407 +STARTUP = 1408 +LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR = 1409 +CANT_CREATE_USER_WITH_GRANT = 1410 +WRONG_VALUE_FOR_TYPE = 1411 +TABLE_DEF_CHANGED = 1412 +SP_DUP_HANDLER = 1413 +SP_NOT_VAR_ARG = 1414 +SP_NO_RETSET = 1415 +CANT_CREATE_GEOMETRY_OBJECT = 1416 +FAILED_ROUTINE_BREAK_BINLOG = 1417 +BINLOG_UNSAFE_ROUTINE = 1418 +BINLOG_CREATE_ROUTINE_NEED_SUPER = 1419 +EXEC_STMT_WITH_OPEN_CURSOR = 1420 +STMT_HAS_NO_OPEN_CURSOR = 1421 +COMMIT_NOT_ALLOWED_IN_SF_OR_TRG = 1422 +NO_DEFAULT_FOR_VIEW_FIELD = 1423 +SP_NO_RECURSION = 1424 +TOO_BIG_SCALE = 1425 +TOO_BIG_PRECISION = 1426 +M_BIGGER_THAN_D = 1427 +WRONG_LOCK_OF_SYSTEM_TABLE = 1428 +CONNECT_TO_FOREIGN_DATA_SOURCE = 1429 +QUERY_ON_FOREIGN_DATA_SOURCE = 1430 +FOREIGN_DATA_SOURCE_DOESNT_EXIST = 1431 +FOREIGN_DATA_STRING_INVALID_CANT_CREATE = 1432 +FOREIGN_DATA_STRING_INVALID = 1433 +CANT_CREATE_FEDERATED_TABLE = 1434 +TRG_IN_WRONG_SCHEMA = 1435 +STACK_OVERRUN_NEED_MORE = 1436 +TOO_LONG_BODY = 1437 +WARN_CANT_DROP_DEFAULT_KEYCACHE = 1438 +TOO_BIG_DISPLAYWIDTH = 1439 +XAER_DUPID = 1440 +DATETIME_FUNCTION_OVERFLOW = 1441 +CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG = 1442 +VIEW_PREVENT_UPDATE = 1443 +PS_NO_RECURSION = 1444 +SP_CANT_SET_AUTOCOMMIT = 1445 +MALFORMED_DEFINER = 1446 +VIEW_FRM_NO_USER = 1447 +VIEW_OTHER_USER = 1448 +NO_SUCH_USER = 1449 +FORBID_SCHEMA_CHANGE = 1450 +ROW_IS_REFERENCED_2 = 1451 +NO_REFERENCED_ROW_2 = 1452 +SP_BAD_VAR_SHADOW = 1453 +TRG_NO_DEFINER = 1454 +OLD_FILE_FORMAT = 1455 +SP_RECURSION_LIMIT = 1456 +SP_PROC_TABLE_CORRUPT = 1457 +ERROR_LAST = 1457 + diff --git a/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/constants/FIELD_TYPE.py b/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/constants/FIELD_TYPE.py new file mode 100644 index 00000000..8a57b171 --- /dev/null +++ b/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/constants/FIELD_TYPE.py @@ -0,0 +1,37 @@ +"""MySQL FIELD_TYPE Constants + +These constants represent the various column (field) types that are +supported by MySQL. + +""" + +DECIMAL = 0 +TINY = 1 +SHORT = 2 +LONG = 3 +FLOAT = 4 +DOUBLE = 5 +NULL = 6 +TIMESTAMP = 7 +LONGLONG = 8 +INT24 = 9 +DATE = 10 +TIME = 11 +DATETIME = 12 +YEAR = 13 +NEWDATE = 14 +VARCHAR = 15 +BIT = 16 +NEWDECIMAL = 246 +ENUM = 247 +SET = 248 +TINY_BLOB = 249 +MEDIUM_BLOB = 250 +LONG_BLOB = 251 +BLOB = 252 +VAR_STRING = 253 +STRING = 254 +GEOMETRY = 255 + +CHAR = TINY +INTERVAL = ENUM diff --git a/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/constants/FLAG.py b/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/constants/FLAG.py new file mode 100644 index 00000000..00e6c7c0 --- /dev/null +++ b/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/constants/FLAG.py @@ -0,0 +1,23 @@ +"""MySQL FLAG Constants + +These flags are used along with the FIELD_TYPE to indicate various +properties of columns in a result set. + +""" + +NOT_NULL = 1 +PRI_KEY = 2 +UNIQUE_KEY = 4 +MULTIPLE_KEY = 8 +BLOB = 16 +UNSIGNED = 32 +ZEROFILL = 64 +BINARY = 128 +ENUM = 256 +AUTO_INCREMENT = 512 +TIMESTAMP = 1024 +SET = 2048 +NUM = 32768 +PART_KEY = 16384 +GROUP = 32768 +UNIQUE = 65536 diff --git a/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/constants/REFRESH.py b/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/constants/REFRESH.py new file mode 100644 index 00000000..4a08b94e --- /dev/null +++ b/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/constants/REFRESH.py @@ -0,0 +1,17 @@ +"""MySQL REFRESH Constants + +These constants seem to mostly deal with things internal to the +MySQL server. Forget you saw this. + +""" + +GRANT = 1 +LOG = 2 +TABLES = 4 +HOSTS = 8 +STATUS = 16 +THREADS = 32 +SLAVE = 64 +MASTER = 128 +READ_LOCK = 16384 +FAST = 32768 diff --git a/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/constants/__init__.py b/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/constants/__init__.py new file mode 100644 index 00000000..3da4a0e7 --- /dev/null +++ b/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/constants/__init__.py @@ -0,0 +1 @@ +__all__ = ['CR', 'FIELD_TYPE','CLIENT','REFRESH','ER','FLAG'] diff --git a/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/converters.py b/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/converters.py new file mode 100644 index 00000000..35b9d0b1 --- /dev/null +++ b/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/converters.py @@ -0,0 +1,189 @@ +"""MySQLdb type conversion module + +This module handles all the type conversions for MySQL. If the default +type conversions aren't what you need, you can make your own. The +dictionary conversions maps some kind of type to a conversion function +which returns the corresponding value: + +Key: FIELD_TYPE.* (from MySQLdb.constants) + +Conversion function: + + Arguments: string + + Returns: Python object + +Key: Python type object (from types) or class + +Conversion function: + + Arguments: Python object of indicated type or class AND + conversion dictionary + + Returns: SQL literal value + + Notes: Most conversion functions can ignore the dictionary, but + it is a required parameter. It is necessary for converting + things like sequences and instances. + +Don't modify conversions if you can avoid it. Instead, make copies +(with the copy() method), modify the copies, and then pass them to +MySQL.connect(). + +""" + +from _mysql import string_literal, escape_sequence, escape_dict, escape, NULL +from MySQLdb.constants import FIELD_TYPE, FLAG +from MySQLdb.times import * + +try: + from types import IntType, LongType, FloatType, NoneType, TupleType, ListType, DictType, InstanceType, \ + StringType, UnicodeType, ObjectType, BooleanType, ClassType, TypeType +except ImportError: + # Python 3 + long = int + IntType, LongType, FloatType, NoneType = int, long, float, type(None) + TupleType, ListType, DictType, InstanceType = tuple, list, dict, None + StringType, UnicodeType, ObjectType, BooleanType = bytes, str, object, bool + +import array + +try: + ArrayType = array.ArrayType +except AttributeError: + ArrayType = array.array + +try: + set +except NameError: + from sets import Set as set + +def Bool2Str(s, d): return str(int(s)) + +def Str2Set(s): + return set([ i for i in s.split(',') if i ]) + +def Set2Str(s, d): + return string_literal(','.join(s), d) + +def Thing2Str(s, d): + """Convert something into a string via str().""" + return str(s) + +def Unicode2Str(s, d): + """Convert a unicode object to a string using the default encoding. + This is only used as a placeholder for the real function, which + is connection-dependent.""" + return s.encode() + +Long2Int = Thing2Str + +def Float2Str(o, d): + return '%.15g' % o + +def None2NULL(o, d): + """Convert None to NULL.""" + return NULL # duh + +def Thing2Literal(o, d): + + """Convert something into a SQL string literal. If using + MySQL-3.23 or newer, string_literal() is a method of the + _mysql.MYSQL object, and this function will be overridden with + that method when the connection is created.""" + + return string_literal(o, d) + + +def Instance2Str(o, d): + + """ + + Convert an Instance to a string representation. If the __str__() + method produces acceptable output, then you don't need to add the + class to conversions; it will be handled by the default + converter. If the exact class is not found in d, it will use the + first class it can find for which o is an instance. + + """ + + if o.__class__ in d: + return d[o.__class__](o, d) + cl = filter(lambda x,o=o: + type(x) is ClassType + and isinstance(o, x), d.keys()) + if not cl: + cl = filter(lambda x,o=o: + type(x) is TypeType + and isinstance(o, x) + and d[x] is not Instance2Str, + d.keys()) + if not cl: + return d[StringType](o,d) + d[o.__class__] = d[cl[0]] + return d[cl[0]](o, d) + +def char_array(s): + return array.array('c', s) + +def array2Str(o, d): + return Thing2Literal(o.tostring(), d) + +def quote_tuple(t, d): + return "(%s)" % (','.join(escape_sequence(t, d))) + +conversions = { + IntType: Thing2Str, + LongType: Long2Int, + FloatType: Float2Str, + NoneType: None2NULL, + TupleType: quote_tuple, + ListType: quote_tuple, + DictType: escape_dict, + InstanceType: Instance2Str, + ArrayType: array2Str, + StringType: Thing2Literal, # default + UnicodeType: Unicode2Str, + ObjectType: Instance2Str, + BooleanType: Bool2Str, + DateTimeType: DateTime2literal, + DateTimeDeltaType: DateTimeDelta2literal, + set: Set2Str, + FIELD_TYPE.TINY: int, + FIELD_TYPE.SHORT: int, + FIELD_TYPE.LONG: long, + FIELD_TYPE.FLOAT: float, + FIELD_TYPE.DOUBLE: float, + FIELD_TYPE.DECIMAL: float, + FIELD_TYPE.NEWDECIMAL: float, + FIELD_TYPE.LONGLONG: long, + FIELD_TYPE.INT24: int, + FIELD_TYPE.YEAR: int, + FIELD_TYPE.SET: Str2Set, + FIELD_TYPE.TIMESTAMP: mysql_timestamp_converter, + FIELD_TYPE.DATETIME: DateTime_or_None, + FIELD_TYPE.TIME: TimeDelta_or_None, + FIELD_TYPE.DATE: Date_or_None, + FIELD_TYPE.BLOB: [ + (FLAG.BINARY, str), + ], + FIELD_TYPE.STRING: [ + (FLAG.BINARY, str), + ], + FIELD_TYPE.VAR_STRING: [ + (FLAG.BINARY, str), + ], + FIELD_TYPE.VARCHAR: [ + (FLAG.BINARY, str), + ], + } + +try: + from decimal import Decimal + conversions[FIELD_TYPE.DECIMAL] = Decimal + conversions[FIELD_TYPE.NEWDECIMAL] = Decimal +except ImportError: + pass + + + diff --git a/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/cursors.py b/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/cursors.py new file mode 100644 index 00000000..e32cf388 --- /dev/null +++ b/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/cursors.py @@ -0,0 +1,541 @@ +"""MySQLdb Cursors + +This module implements Cursors of various types for MySQLdb. By +default, MySQLdb uses the Cursor class. + +""" + +import re +import sys +try: + from types import ListType, TupleType, UnicodeType +except ImportError: + # Python 3 + ListType = list + TupleType = tuple + UnicodeType = str + +restr = r""" + \s + values + \s* + ( + \( + [^()']* + (?: + (?: + (?:\( + # ( - editor hightlighting helper + .* + \)) + | + ' + [^\\']* + (?:\\.[^\\']*)* + ' + ) + [^()']* + )* + \) + ) +""" + +insert_values = re.compile(restr, re.S | re.I | re.X) + +from _mysql_exceptions import Warning, Error, InterfaceError, DataError, \ + DatabaseError, OperationalError, IntegrityError, InternalError, \ + NotSupportedError, ProgrammingError + + +class BaseCursor(object): + + """A base for Cursor classes. Useful attributes: + + description + A tuple of DB API 7-tuples describing the columns in + the last executed query; see PEP-249 for details. + + description_flags + Tuple of column flags for last query, one entry per column + in the result set. Values correspond to those in + MySQLdb.constants.FLAG. See MySQL documentation (C API) + for more information. Non-standard extension. + + arraysize + default number of rows fetchmany() will fetch + + """ + + from _mysql_exceptions import MySQLError, Warning, Error, InterfaceError, \ + DatabaseError, DataError, OperationalError, IntegrityError, \ + InternalError, ProgrammingError, NotSupportedError + + _defer_warnings = False + + def __init__(self, connection): + from weakref import proxy + + self.connection = proxy(connection) + self.description = None + self.description_flags = None + self.rowcount = -1 + self.arraysize = 1 + self._executed = None + self.lastrowid = None + self.messages = [] + self.errorhandler = connection.errorhandler + self._result = None + self._warnings = 0 + self._info = None + self.rownumber = None + + def __del__(self): + self.close() + self.errorhandler = None + self._result = None + + def close(self): + """Close the cursor. No further queries will be possible.""" + if not self.connection: return + while self.nextset(): pass + self.connection = None + + def _check_executed(self): + if not self._executed: + self.errorhandler(self, ProgrammingError, "execute() first") + + def _warning_check(self): + from warnings import warn + if self._warnings: + warnings = self._get_db().show_warnings() + if warnings: + # This is done in two loops in case + # Warnings are set to raise exceptions. + for w in warnings: + self.messages.append((self.Warning, w)) + for w in warnings: + warn(w[-1], self.Warning, 3) + elif self._info: + self.messages.append((self.Warning, self._info)) + warn(self._info, self.Warning, 3) + + def nextset(self): + """Advance to the next result set. + + Returns None if there are no more result sets. + """ + if self._executed: + self.fetchall() + del self.messages[:] + + db = self._get_db() + nr = db.next_result() + if nr == -1: + return None + self._do_get_result() + self._post_get_result() + self._warning_check() + return 1 + + def _post_get_result(self): pass + + def _do_get_result(self): + db = self._get_db() + self._result = self._get_result() + self.rowcount = db.affected_rows() + self.rownumber = 0 + self.description = self._result and self._result.describe() or None + self.description_flags = self._result and self._result.field_flags() or None + self.lastrowid = db.insert_id() + self._warnings = db.warning_count() + self._info = db.info() + + def setinputsizes(self, *args): + """Does nothing, required by DB API.""" + + def setoutputsizes(self, *args): + """Does nothing, required by DB API.""" + + def _get_db(self): + if not self.connection: + self.errorhandler(self, ProgrammingError, "cursor closed") + return self.connection + + def execute(self, query, args=None): + + """Execute a query. + + query -- string, query to execute on server + args -- optional sequence or mapping, parameters to use with query. + + Note: If args is a sequence, then %s must be used as the + parameter placeholder in the query. If a mapping is used, + %(key)s must be used as the placeholder. + + Returns long integer rows affected, if any + + """ + del self.messages[:] + db = self._get_db() + if isinstance(query, unicode): + query = query.encode(db.unicode_literal.charset) + if args is not None: + if isinstance(args, dict): + query = query % dict((key, db.literal(item)) + for key, item in args.iteritems()) + else: + query = query % tuple([db.literal(item) for item in args]) + try: + r = None + r = self._query(query) + except TypeError, m: + if m.args[0] in ("not enough arguments for format string", + "not all arguments converted"): + self.messages.append((ProgrammingError, m.args[0])) + self.errorhandler(self, ProgrammingError, m.args[0]) + else: + self.messages.append((TypeError, m)) + self.errorhandler(self, TypeError, m) + except (SystemExit, KeyboardInterrupt): + raise + except: + exc, value, tb = sys.exc_info() + del tb + self.messages.append((exc, value)) + self.errorhandler(self, exc, value) + self._executed = query + if not self._defer_warnings: self._warning_check() + return r + + def executemany(self, query, args): + + """Execute a multi-row query. + + query -- string, query to execute on server + + args + + Sequence of sequences or mappings, parameters to use with + query. + + Returns long integer rows affected, if any. + + This method improves performance on multiple-row INSERT and + REPLACE. Otherwise it is equivalent to looping over args with + execute(). + + """ + del self.messages[:] + db = self._get_db() + if not args: return + if isinstance(query, unicode): + query = query.encode(db.unicode_literal.charset) + m = insert_values.search(query) + if not m: + r = 0 + for a in args: + r = r + self.execute(query, a) + return r + p = m.start(1) + e = m.end(1) + qv = m.group(1) + try: + q = [] + for a in args: + if isinstance(a, dict): + q.append(qv % dict((key, db.literal(item)) + for key, item in a.iteritems())) + else: + q.append(qv % tuple([db.literal(item) for item in a])) + except TypeError, msg: + if msg.args[0] in ("not enough arguments for format string", + "not all arguments converted"): + self.errorhandler(self, ProgrammingError, msg.args[0]) + else: + self.errorhandler(self, TypeError, msg) + except (SystemExit, KeyboardInterrupt): + raise + except: + exc, value, tb = sys.exc_info() + del tb + self.errorhandler(self, exc, value) + r = self._query('\n'.join([query[:p], ',\n'.join(q), query[e:]])) + if not self._defer_warnings: self._warning_check() + return r + + def callproc(self, procname, args=()): + + """Execute stored procedure procname with args + + procname -- string, name of procedure to execute on server + + args -- Sequence of parameters to use with procedure + + Returns the original args. + + Compatibility warning: PEP-249 specifies that any modified + parameters must be returned. This is currently impossible + as they are only available by storing them in a server + variable and then retrieved by a query. Since stored + procedures return zero or more result sets, there is no + reliable way to get at OUT or INOUT parameters via callproc. + The server variables are named @_procname_n, where procname + is the parameter above and n is the position of the parameter + (from zero). Once all result sets generated by the procedure + have been fetched, you can issue a SELECT @_procname_0, ... + query using .execute() to get any OUT or INOUT values. + + Compatibility warning: The act of calling a stored procedure + itself creates an empty result set. This appears after any + result sets generated by the procedure. This is non-standard + behavior with respect to the DB-API. Be sure to use nextset() + to advance through all result sets; otherwise you may get + disconnected. + """ + + db = self._get_db() + for index, arg in enumerate(args): + q = "SET @_%s_%d=%s" % (procname, index, + db.literal(arg)) + if isinstance(q, unicode): + q = q.encode(db.unicode_literal.charset) + self._query(q) + self.nextset() + + q = "CALL %s(%s)" % (procname, + ','.join(['@_%s_%d' % (procname, i) + for i in range(len(args))])) + if type(q) is UnicodeType: + q = q.encode(db.unicode_literal.charset) + self._query(q) + self._executed = q + if not self._defer_warnings: self._warning_check() + return args + + def _do_query(self, q): + db = self._get_db() + self._last_executed = q + db.query(q) + self._do_get_result() + return self.rowcount + + def _query(self, q): return self._do_query(q) + + def _fetch_row(self, size=1): + if not self._result: + return () + return self._result.fetch_row(size, self._fetch_type) + + def __iter__(self): + return iter(self.fetchone, None) + + Warning = Warning + Error = Error + InterfaceError = InterfaceError + DatabaseError = DatabaseError + DataError = DataError + OperationalError = OperationalError + IntegrityError = IntegrityError + InternalError = InternalError + ProgrammingError = ProgrammingError + NotSupportedError = NotSupportedError + + +class CursorStoreResultMixIn(object): + + """This is a MixIn class which causes the entire result set to be + stored on the client side, i.e. it uses mysql_store_result(). If the + result set can be very large, consider adding a LIMIT clause to your + query, or using CursorUseResultMixIn instead.""" + + def _get_result(self): return self._get_db().store_result() + + def _query(self, q): + rowcount = self._do_query(q) + self._post_get_result() + return rowcount + + def _post_get_result(self): + self._rows = self._fetch_row(0) + self._result = None + + def fetchone(self): + """Fetches a single row from the cursor. None indicates that + no more rows are available.""" + self._check_executed() + if self.rownumber >= len(self._rows): return None + result = self._rows[self.rownumber] + self.rownumber = self.rownumber+1 + return result + + def fetchmany(self, size=None): + """Fetch up to size rows from the cursor. Result set may be smaller + than size. If size is not defined, cursor.arraysize is used.""" + self._check_executed() + end = self.rownumber + (size or self.arraysize) + result = self._rows[self.rownumber:end] + self.rownumber = min(end, len(self._rows)) + return result + + def fetchall(self): + """Fetchs all available rows from the cursor.""" + self._check_executed() + if self.rownumber: + result = self._rows[self.rownumber:] + else: + result = self._rows + self.rownumber = len(self._rows) + return result + + def scroll(self, value, mode='relative'): + """Scroll the cursor in the result set to a new position according + to mode. + + If mode is 'relative' (default), value is taken as offset to + the current position in the result set, if set to 'absolute', + value states an absolute target position.""" + self._check_executed() + if mode == 'relative': + r = self.rownumber + value + elif mode == 'absolute': + r = value + else: + self.errorhandler(self, ProgrammingError, + "unknown scroll mode %s" % repr(mode)) + if r < 0 or r >= len(self._rows): + self.errorhandler(self, IndexError, "out of range") + self.rownumber = r + + def __iter__(self): + self._check_executed() + result = self.rownumber and self._rows[self.rownumber:] or self._rows + return iter(result) + + +class CursorUseResultMixIn(object): + + """This is a MixIn class which causes the result set to be stored + in the server and sent row-by-row to client side, i.e. it uses + mysql_use_result(). You MUST retrieve the entire result set and + close() the cursor before additional queries can be peformed on + the connection.""" + + _defer_warnings = True + + def _get_result(self): return self._get_db().use_result() + + def fetchone(self): + """Fetches a single row from the cursor.""" + self._check_executed() + r = self._fetch_row(1) + if not r: + self._warning_check() + return None + self.rownumber = self.rownumber + 1 + return r[0] + + def fetchmany(self, size=None): + """Fetch up to size rows from the cursor. Result set may be smaller + than size. If size is not defined, cursor.arraysize is used.""" + self._check_executed() + r = self._fetch_row(size or self.arraysize) + self.rownumber = self.rownumber + len(r) + if not r: + self._warning_check() + return r + + def fetchall(self): + """Fetchs all available rows from the cursor.""" + self._check_executed() + r = self._fetch_row(0) + self.rownumber = self.rownumber + len(r) + self._warning_check() + return r + + def __iter__(self): + return self + + def next(self): + row = self.fetchone() + if row is None: + raise StopIteration + return row + + +class CursorTupleRowsMixIn(object): + + """This is a MixIn class that causes all rows to be returned as tuples, + which is the standard form required by DB API.""" + + _fetch_type = 0 + + +class CursorDictRowsMixIn(object): + + """This is a MixIn class that causes all rows to be returned as + dictionaries. This is a non-standard feature.""" + + _fetch_type = 1 + + def fetchoneDict(self): + """Fetch a single row as a dictionary. Deprecated: + Use fetchone() instead. Will be removed in 1.3.""" + from warnings import warn + warn("fetchoneDict() is non-standard and will be removed in 1.3", + DeprecationWarning, 2) + return self.fetchone() + + def fetchmanyDict(self, size=None): + """Fetch several rows as a list of dictionaries. Deprecated: + Use fetchmany() instead. Will be removed in 1.3.""" + from warnings import warn + warn("fetchmanyDict() is non-standard and will be removed in 1.3", + DeprecationWarning, 2) + return self.fetchmany(size) + + def fetchallDict(self): + """Fetch all available rows as a list of dictionaries. Deprecated: + Use fetchall() instead. Will be removed in 1.3.""" + from warnings import warn + warn("fetchallDict() is non-standard and will be removed in 1.3", + DeprecationWarning, 2) + return self.fetchall() + + +class CursorOldDictRowsMixIn(CursorDictRowsMixIn): + + """This is a MixIn class that returns rows as dictionaries with + the same key convention as the old Mysqldb (MySQLmodule). Don't + use this.""" + + _fetch_type = 2 + + +class Cursor(CursorStoreResultMixIn, CursorTupleRowsMixIn, + BaseCursor): + + """This is the standard Cursor class that returns rows as tuples + and stores the result set in the client.""" + + +class DictCursor(CursorStoreResultMixIn, CursorDictRowsMixIn, + BaseCursor): + + """This is a Cursor class that returns rows as dictionaries and + stores the result set in the client.""" + + +class SSCursor(CursorUseResultMixIn, CursorTupleRowsMixIn, + BaseCursor): + + """This is a Cursor class that returns rows as tuples and stores + the result set in the server.""" + + +class SSDictCursor(CursorUseResultMixIn, CursorDictRowsMixIn, + BaseCursor): + + """This is a Cursor class that returns rows as dictionaries and + stores the result set in the server.""" + + diff --git a/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/release.py b/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/release.py new file mode 100644 index 00000000..2e7119cf --- /dev/null +++ b/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/release.py @@ -0,0 +1,4 @@ + +__author__ = "Andy Dustman " +version_info = (1,2,5,'final',1) +__version__ = "1.2.5" diff --git a/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/times.py b/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/times.py new file mode 100644 index 00000000..f5f34d47 --- /dev/null +++ b/lib/mysql/build/lib.linux-x86_64-2.7/MySQLdb/times.py @@ -0,0 +1,126 @@ +"""times module + +This module provides some Date and Time classes for dealing with MySQL data. + +Use Python datetime module to handle date and time columns.""" + +import math +from time import localtime +from datetime import date, datetime, time, timedelta +from _mysql import string_literal + +Date = date +Time = time +TimeDelta = timedelta +Timestamp = datetime + +DateTimeDeltaType = timedelta +DateTimeType = datetime + +def DateFromTicks(ticks): + """Convert UNIX ticks into a date instance.""" + return date(*localtime(ticks)[:3]) + +def TimeFromTicks(ticks): + """Convert UNIX ticks into a time instance.""" + return time(*localtime(ticks)[3:6]) + +def TimestampFromTicks(ticks): + """Convert UNIX ticks into a datetime instance.""" + return datetime(*localtime(ticks)[:6]) + +format_TIME = format_DATE = str + +def format_TIMEDELTA(v): + seconds = int(v.seconds) % 60 + minutes = int(v.seconds / 60) % 60 + hours = int(v.seconds / 3600) % 24 + return '%d %d:%d:%d' % (v.days, hours, minutes, seconds) + +def format_TIMESTAMP(d): + return d.isoformat(" ") + + +def DateTime_or_None(s): + if ' ' in s: + sep = ' ' + elif 'T' in s: + sep = 'T' + else: + return Date_or_None(s) + + try: + d, t = s.split(sep, 1) + if '.' in t: + t, ms = t.split('.',1) + ms = ms.ljust(6, '0') + else: + ms = 0 + return datetime(*[ int(x) for x in d.split('-')+t.split(':')+[ms] ]) + except (SystemExit, KeyboardInterrupt): + raise + except: + return Date_or_None(s) + +def TimeDelta_or_None(s): + try: + h, m, s = s.split(':') + if '.' in s: + s, ms = s.split('.') + ms = ms.ljust(6, '0') + else: + ms = 0 + h, m, s, ms = int(h), int(m), int(s), int(ms) + td = timedelta(hours=abs(h), minutes=m, seconds=s, + microseconds=ms) + if h < 0: + return -td + else: + return td + except ValueError: + # unpacking or int/float conversion failed + return None + +def Time_or_None(s): + try: + h, m, s = s.split(':') + if '.' in s: + s, ms = s.split('.') + ms = ms.ljust(6, '0') + else: + ms = 0 + h, m, s, ms = int(h), int(m), int(s), int(ms) + return time(hour=h, minute=m, second=s, + microsecond=ms) + except ValueError: + return None + +def Date_or_None(s): + try: + return date(*[ int(x) for x in s.split('-',2)]) + except (SystemExit, KeyboardInterrupt): + raise + except: + return None + +def DateTime2literal(d, c): + """Format a DateTime object as an ISO timestamp.""" + return string_literal(format_TIMESTAMP(d),c) + +def DateTimeDelta2literal(d, c): + """Format a DateTimeDelta object as a time.""" + return string_literal(format_TIMEDELTA(d),c) + +def mysql_timestamp_converter(s): + """Convert a MySQL TIMESTAMP to a Timestamp object.""" + # MySQL>4.1 returns TIMESTAMP in the same format as DATETIME + if s[4] == '-': return DateTime_or_None(s) + s = s + "0"*(14-len(s)) # padding + parts = map(int, filter(None, (s[:4],s[4:6],s[6:8], + s[8:10],s[10:12],s[12:14]))) + try: + return Timestamp(*parts) + except (SystemExit, KeyboardInterrupt): + raise + except: + return None diff --git a/lib/mysql/build/lib.linux-x86_64-2.7/_mysql.so b/lib/mysql/build/lib.linux-x86_64-2.7/_mysql.so new file mode 100755 index 00000000..5dd437cc Binary files /dev/null and b/lib/mysql/build/lib.linux-x86_64-2.7/_mysql.so differ diff --git a/lib/mysql/build/lib.linux-x86_64-2.7/_mysql_exceptions.py b/lib/mysql/build/lib.linux-x86_64-2.7/_mysql_exceptions.py new file mode 100644 index 00000000..3241e740 --- /dev/null +++ b/lib/mysql/build/lib.linux-x86_64-2.7/_mysql_exceptions.py @@ -0,0 +1,87 @@ +"""_mysql_exceptions: Exception classes for _mysql and MySQLdb. + +These classes are dictated by the DB API v2.0: + + http://www.python.org/topics/database/DatabaseAPI-2.0.html +""" + +try: + from exceptions import Exception, StandardError, Warning +except ImportError: + # Python 3 + StandardError = Exception + + +class MySQLError(StandardError): + + """Exception related to operation with MySQL.""" + + +class Warning(Warning, MySQLError): + + """Exception raised for important warnings like data truncations + while inserting, etc.""" + +class Error(MySQLError): + + """Exception that is the base class of all other error exceptions + (not Warning).""" + + +class InterfaceError(Error): + + """Exception raised for errors that are related to the database + interface rather than the database itself.""" + + +class DatabaseError(Error): + + """Exception raised for errors that are related to the + database.""" + + +class DataError(DatabaseError): + + """Exception raised for errors that are due to problems with the + processed data like division by zero, numeric value out of range, + etc.""" + + +class OperationalError(DatabaseError): + + """Exception raised for errors that are related to the database's + operation and not necessarily under the control of the programmer, + e.g. an unexpected disconnect occurs, the data source name is not + found, a transaction could not be processed, a memory allocation + error occurred during processing, etc.""" + + +class IntegrityError(DatabaseError): + + """Exception raised when the relational integrity of the database + is affected, e.g. a foreign key check fails, duplicate key, + etc.""" + + +class InternalError(DatabaseError): + + """Exception raised when the database encounters an internal + error, e.g. the cursor is not valid anymore, the transaction is + out of sync, etc.""" + + +class ProgrammingError(DatabaseError): + + """Exception raised for programming errors, e.g. table not found + or already exists, syntax error in the SQL statement, wrong number + of parameters specified, etc.""" + + +class NotSupportedError(DatabaseError): + + """Exception raised in case a method or database API was used + which is not supported by the database, e.g. requesting a + .rollback() on a connection that does not support transaction or + has transactions turned off.""" + + diff --git a/lib/mysql/build/temp.linux-x86_64-2.7/_mysql.o b/lib/mysql/build/temp.linux-x86_64-2.7/_mysql.o new file mode 100644 index 00000000..1abce3a7 Binary files /dev/null and b/lib/mysql/build/temp.linux-x86_64-2.7/_mysql.o differ diff --git a/lib/mysql/dist/MySQL_python-1.2.5-py2.7-linux-x86_64.egg b/lib/mysql/dist/MySQL_python-1.2.5-py2.7-linux-x86_64.egg new file mode 100644 index 00000000..0383a985 Binary files /dev/null and b/lib/mysql/dist/MySQL_python-1.2.5-py2.7-linux-x86_64.egg differ diff --git a/lib/mysql/doc/FAQ.rst b/lib/mysql/doc/FAQ.rst new file mode 100644 index 00000000..b6a4ce97 --- /dev/null +++ b/lib/mysql/doc/FAQ.rst @@ -0,0 +1,143 @@ +==================================== + MySQLdb Frequently Asked Questions +==================================== + +.. contents:: +.. + + +Build Errors +------------ + + ld: fatal: library -lmysqlclient_r: not found + +mysqlclient_r is the thread-safe library. It's not available on +all platforms, or all installations, apparently. You'll need to +reconfigure site.cfg (in MySQLdb-1.2.1 and newer) to have +threadsafe = False. + + mysql.h: No such file or directory + +This almost always mean you don't have development packages +installed. On some systems, C headers for various things (like MySQL) +are distributed as a seperate package. You'll need to figure out +what that is and install it, but often the name ends with -devel. + +Another possibility: Some older versions of mysql_config behave oddly +and may throw quotes around some of the path names, which confused +MySQLdb-1.2.0. 1.2.1 works around these problems. If you see things +like -I'/usr/local/include/mysql' in your compile command, that's +probably the issue, but it shouldn't happen any more. + + +ImportError +----------- + + ImportError: No module named _mysql + +If you see this, it's likely you did some wrong when installing +MySQLdb; re-read (or read) README. _mysql is the low-level C module +that interfaces with the MySQL client library. + +Various versions of MySQLdb in the past have had build issues on +"weird" platforms; "weird" in this case means "not Linux", though +generally there aren't problems on Unix/POSIX platforms, including +BSDs and Mac OS X. Windows has been more problematic, in part because +there is no `mysql_config` available in the Windows installation of +MySQL. 1.2.1 solves most, if not all, of these problems, but you will +still have to edit a configuration file so that the setup knows where +to find MySQL and what libraries to include. + + + ImportError: libmysqlclient_r.so.14: cannot open shared object file: No such file or directory + +The number after .so may vary, but this means you have a version of +MySQLdb compiled against one version of MySQL, and are now trying to +run it against a different version. The shared library version tends +to change between major releases. + +Solution: Rebuilt MySQLdb, or get the matching version of MySQL. + +Another thing that can cause this: The MySQL libraries may not be on +your system path. + +Solutions: + +* set the LD_LIBRARY_PATH environment variable so that it includes + the path to the MySQL libraries. + +* set static=True in site.cfg for static linking + +* reconfigure your system so that the MySQL libraries are on the + default loader path. In Linux, you edit /etc/ld.so.conf and run + ldconfig. For Solaris, see `Linker and Libraries Guide + `_. + + + ImportError: ld.so.1: python: fatal: libmtmalloc.so.1: DF_1_NOOPEN tagged object may not be dlopen()'ed + +This is a weird one from Solaris. What does it mean? I have no idea. +However, things like this can happen if there is some sort of a compiler +or environment mismatch between Python and MySQL. For example, on some +commercial systems, you might have some code compiled with their own +compiler, and other things compiled with GCC. They don't always mesh +together. One way to encounter this is by getting binary packages from +different vendors. + +Solution: Rebuild Python or MySQL (or maybe both) from source. + + ImportError: dlopen(./_mysql.so, 2): Symbol not found: _sprintf$LDBLStub + Referenced from: ./_mysql.so + Expected in: dynamic lookup + +This is one from Mac OS X. It seems to have been a compiler mismatch, +but this time between two different versions of GCC. It seems nearly +every major release of GCC changes the ABI in some why, so linking +code compiled with GCC-3.3 and GCC-4.0, for example, can be +problematic. + + +My data disappeared! (or won't go away!) +---------------------------------------- + +Starting with 1.2.0, MySQLdb disables autocommit by default, as +required by the DB-API standard (`PEP-249`_). If you are using InnoDB +tables or some other type of transactional table type, you'll need +to do connection.commit() before closing the connection, or else +none of your changes will be written to the database. + +Conversely, you can also use connection.rollback() to throw away +any changes you've made since the last commit. + +Important note: Some SQL statements -- specifically DDL statements +like CREATE TABLE -- are non-transactional, so they can't be +rolled back, and they cause pending transactions to commit. + + +Other Errors +------------ + + OperationalError: (1251, 'Client does not support authentication protocol requested by server; consider upgrading MySQL client') + +This means your server and client libraries are not the same version. +More specifically, it probably means you have a 4.1 or newer server +and 4.0 or older client. You can either upgrade the client side, or +try some of the workarounds in `Password Hashing as of MySQL 4.1 +`_. + + +Other Resources +--------------- + +* Help forum. Please search before posting. + +* `Google `_ + +* READ README! + +* Read the User's Guide + +* Read `PEP-249`_ + +.. _`PEP-249`: http://www.python.org/peps/pep-0249.html + diff --git a/lib/mysql/doc/MySQLdb.constants.rst b/lib/mysql/doc/MySQLdb.constants.rst new file mode 100644 index 00000000..e28dee2b --- /dev/null +++ b/lib/mysql/doc/MySQLdb.constants.rst @@ -0,0 +1,59 @@ +constants Package +================= + +:mod:`constants` Package +------------------------ + +.. automodule:: MySQLdb.constants + :members: + :undoc-members: + :show-inheritance: + +:mod:`CLIENT` Module +-------------------- + +.. automodule:: MySQLdb.constants.CLIENT + :members: + :undoc-members: + :show-inheritance: + +:mod:`CR` Module +---------------- + +.. automodule:: MySQLdb.constants.CR + :members: + :undoc-members: + :show-inheritance: + +:mod:`ER` Module +---------------- + +.. automodule:: MySQLdb.constants.ER + :members: + :undoc-members: + :show-inheritance: + +:mod:`FIELD_TYPE` Module +------------------------ + +.. automodule:: MySQLdb.constants.FIELD_TYPE + :members: + :undoc-members: + :show-inheritance: + +:mod:`FLAG` Module +------------------ + +.. automodule:: MySQLdb.constants.FLAG + :members: + :undoc-members: + :show-inheritance: + +:mod:`REFRESH` Module +--------------------- + +.. automodule:: MySQLdb.constants.REFRESH + :members: + :undoc-members: + :show-inheritance: + diff --git a/lib/mysql/doc/MySQLdb.rst b/lib/mysql/doc/MySQLdb.rst new file mode 100644 index 00000000..26138ec1 --- /dev/null +++ b/lib/mysql/doc/MySQLdb.rst @@ -0,0 +1,50 @@ +MySQLdb Package +=============== + +:mod:`MySQLdb` Package +---------------------- + +.. automodule:: MySQLdb.__init__ + :members: + :undoc-members: + :show-inheritance: + +:mod:`connections` Module +------------------------- + +.. automodule:: MySQLdb.connections + :members: Connection + :undoc-members: + :show-inheritance: + +:mod:`converters` Module +------------------------ + +.. automodule:: MySQLdb.converters + :members: + :undoc-members: + :show-inheritance: + +:mod:`cursors` Module +--------------------- + +.. automodule:: MySQLdb.cursors + :members: Cursor + :undoc-members: + :show-inheritance: + +:mod:`times` Module +------------------- + +.. automodule:: MySQLdb.times + :members: + :undoc-members: + :show-inheritance: + +Subpackages +----------- + +.. toctree:: + + MySQLdb.constants + diff --git a/lib/mysql/doc/_build/_sources/FAQ.txt b/lib/mysql/doc/_build/_sources/FAQ.txt new file mode 100644 index 00000000..b6a4ce97 --- /dev/null +++ b/lib/mysql/doc/_build/_sources/FAQ.txt @@ -0,0 +1,143 @@ +==================================== + MySQLdb Frequently Asked Questions +==================================== + +.. contents:: +.. + + +Build Errors +------------ + + ld: fatal: library -lmysqlclient_r: not found + +mysqlclient_r is the thread-safe library. It's not available on +all platforms, or all installations, apparently. You'll need to +reconfigure site.cfg (in MySQLdb-1.2.1 and newer) to have +threadsafe = False. + + mysql.h: No such file or directory + +This almost always mean you don't have development packages +installed. On some systems, C headers for various things (like MySQL) +are distributed as a seperate package. You'll need to figure out +what that is and install it, but often the name ends with -devel. + +Another possibility: Some older versions of mysql_config behave oddly +and may throw quotes around some of the path names, which confused +MySQLdb-1.2.0. 1.2.1 works around these problems. If you see things +like -I'/usr/local/include/mysql' in your compile command, that's +probably the issue, but it shouldn't happen any more. + + +ImportError +----------- + + ImportError: No module named _mysql + +If you see this, it's likely you did some wrong when installing +MySQLdb; re-read (or read) README. _mysql is the low-level C module +that interfaces with the MySQL client library. + +Various versions of MySQLdb in the past have had build issues on +"weird" platforms; "weird" in this case means "not Linux", though +generally there aren't problems on Unix/POSIX platforms, including +BSDs and Mac OS X. Windows has been more problematic, in part because +there is no `mysql_config` available in the Windows installation of +MySQL. 1.2.1 solves most, if not all, of these problems, but you will +still have to edit a configuration file so that the setup knows where +to find MySQL and what libraries to include. + + + ImportError: libmysqlclient_r.so.14: cannot open shared object file: No such file or directory + +The number after .so may vary, but this means you have a version of +MySQLdb compiled against one version of MySQL, and are now trying to +run it against a different version. The shared library version tends +to change between major releases. + +Solution: Rebuilt MySQLdb, or get the matching version of MySQL. + +Another thing that can cause this: The MySQL libraries may not be on +your system path. + +Solutions: + +* set the LD_LIBRARY_PATH environment variable so that it includes + the path to the MySQL libraries. + +* set static=True in site.cfg for static linking + +* reconfigure your system so that the MySQL libraries are on the + default loader path. In Linux, you edit /etc/ld.so.conf and run + ldconfig. For Solaris, see `Linker and Libraries Guide + `_. + + + ImportError: ld.so.1: python: fatal: libmtmalloc.so.1: DF_1_NOOPEN tagged object may not be dlopen()'ed + +This is a weird one from Solaris. What does it mean? I have no idea. +However, things like this can happen if there is some sort of a compiler +or environment mismatch between Python and MySQL. For example, on some +commercial systems, you might have some code compiled with their own +compiler, and other things compiled with GCC. They don't always mesh +together. One way to encounter this is by getting binary packages from +different vendors. + +Solution: Rebuild Python or MySQL (or maybe both) from source. + + ImportError: dlopen(./_mysql.so, 2): Symbol not found: _sprintf$LDBLStub + Referenced from: ./_mysql.so + Expected in: dynamic lookup + +This is one from Mac OS X. It seems to have been a compiler mismatch, +but this time between two different versions of GCC. It seems nearly +every major release of GCC changes the ABI in some why, so linking +code compiled with GCC-3.3 and GCC-4.0, for example, can be +problematic. + + +My data disappeared! (or won't go away!) +---------------------------------------- + +Starting with 1.2.0, MySQLdb disables autocommit by default, as +required by the DB-API standard (`PEP-249`_). If you are using InnoDB +tables or some other type of transactional table type, you'll need +to do connection.commit() before closing the connection, or else +none of your changes will be written to the database. + +Conversely, you can also use connection.rollback() to throw away +any changes you've made since the last commit. + +Important note: Some SQL statements -- specifically DDL statements +like CREATE TABLE -- are non-transactional, so they can't be +rolled back, and they cause pending transactions to commit. + + +Other Errors +------------ + + OperationalError: (1251, 'Client does not support authentication protocol requested by server; consider upgrading MySQL client') + +This means your server and client libraries are not the same version. +More specifically, it probably means you have a 4.1 or newer server +and 4.0 or older client. You can either upgrade the client side, or +try some of the workarounds in `Password Hashing as of MySQL 4.1 +`_. + + +Other Resources +--------------- + +* Help forum. Please search before posting. + +* `Google `_ + +* READ README! + +* Read the User's Guide + +* Read `PEP-249`_ + +.. _`PEP-249`: http://www.python.org/peps/pep-0249.html + diff --git a/lib/mysql/doc/_build/_sources/MySQLdb.constants.txt b/lib/mysql/doc/_build/_sources/MySQLdb.constants.txt new file mode 100644 index 00000000..e28dee2b --- /dev/null +++ b/lib/mysql/doc/_build/_sources/MySQLdb.constants.txt @@ -0,0 +1,59 @@ +constants Package +================= + +:mod:`constants` Package +------------------------ + +.. automodule:: MySQLdb.constants + :members: + :undoc-members: + :show-inheritance: + +:mod:`CLIENT` Module +-------------------- + +.. automodule:: MySQLdb.constants.CLIENT + :members: + :undoc-members: + :show-inheritance: + +:mod:`CR` Module +---------------- + +.. automodule:: MySQLdb.constants.CR + :members: + :undoc-members: + :show-inheritance: + +:mod:`ER` Module +---------------- + +.. automodule:: MySQLdb.constants.ER + :members: + :undoc-members: + :show-inheritance: + +:mod:`FIELD_TYPE` Module +------------------------ + +.. automodule:: MySQLdb.constants.FIELD_TYPE + :members: + :undoc-members: + :show-inheritance: + +:mod:`FLAG` Module +------------------ + +.. automodule:: MySQLdb.constants.FLAG + :members: + :undoc-members: + :show-inheritance: + +:mod:`REFRESH` Module +--------------------- + +.. automodule:: MySQLdb.constants.REFRESH + :members: + :undoc-members: + :show-inheritance: + diff --git a/lib/mysql/doc/_build/_sources/MySQLdb.txt b/lib/mysql/doc/_build/_sources/MySQLdb.txt new file mode 100644 index 00000000..26138ec1 --- /dev/null +++ b/lib/mysql/doc/_build/_sources/MySQLdb.txt @@ -0,0 +1,50 @@ +MySQLdb Package +=============== + +:mod:`MySQLdb` Package +---------------------- + +.. automodule:: MySQLdb.__init__ + :members: + :undoc-members: + :show-inheritance: + +:mod:`connections` Module +------------------------- + +.. automodule:: MySQLdb.connections + :members: Connection + :undoc-members: + :show-inheritance: + +:mod:`converters` Module +------------------------ + +.. automodule:: MySQLdb.converters + :members: + :undoc-members: + :show-inheritance: + +:mod:`cursors` Module +--------------------- + +.. automodule:: MySQLdb.cursors + :members: Cursor + :undoc-members: + :show-inheritance: + +:mod:`times` Module +------------------- + +.. automodule:: MySQLdb.times + :members: + :undoc-members: + :show-inheritance: + +Subpackages +----------- + +.. toctree:: + + MySQLdb.constants + diff --git a/lib/mysql/doc/_build/_sources/_mysql.txt b/lib/mysql/doc/_build/_sources/_mysql.txt new file mode 100644 index 00000000..4a60591b --- /dev/null +++ b/lib/mysql/doc/_build/_sources/_mysql.txt @@ -0,0 +1,7 @@ +_mysql Module +============= + +.. automodule:: _mysql + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/lib/mysql/doc/_build/_sources/_mysql_exceptions.txt b/lib/mysql/doc/_build/_sources/_mysql_exceptions.txt new file mode 100644 index 00000000..9b65de35 --- /dev/null +++ b/lib/mysql/doc/_build/_sources/_mysql_exceptions.txt @@ -0,0 +1,7 @@ +_mysql_exceptions Module +======================== + +.. automodule:: _mysql_exceptions + :members: + :undoc-members: + :show-inheritance: diff --git a/lib/mysql/doc/_build/_sources/distribute_setup.txt b/lib/mysql/doc/_build/_sources/distribute_setup.txt new file mode 100644 index 00000000..d9808267 --- /dev/null +++ b/lib/mysql/doc/_build/_sources/distribute_setup.txt @@ -0,0 +1,7 @@ +distribute_setup Module +======================= + +.. automodule:: distribute_setup + :members: + :undoc-members: + :show-inheritance: diff --git a/lib/mysql/doc/_build/_sources/index.txt b/lib/mysql/doc/_build/_sources/index.txt new file mode 100644 index 00000000..a0b3fd57 --- /dev/null +++ b/lib/mysql/doc/_build/_sources/index.txt @@ -0,0 +1,24 @@ +.. MySQLdb documentation master file, created by + sphinx-quickstart on Sun Oct 07 19:36:17 2012. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to MySQLdb's documentation! +=================================== + +Contents: + +.. toctree:: + :maxdepth: 3 + + user_guide + MySQLdb + FAQ + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/lib/mysql/doc/_build/_sources/modules.txt b/lib/mysql/doc/_build/_sources/modules.txt new file mode 100644 index 00000000..7cf3faaa --- /dev/null +++ b/lib/mysql/doc/_build/_sources/modules.txt @@ -0,0 +1,7 @@ +MySQLdb +======= + +.. toctree:: + :maxdepth: 4 + + MySQLdb diff --git a/lib/mysql/doc/_build/_sources/setup.txt b/lib/mysql/doc/_build/_sources/setup.txt new file mode 100644 index 00000000..b6b6b3cf --- /dev/null +++ b/lib/mysql/doc/_build/_sources/setup.txt @@ -0,0 +1,7 @@ +setup Module +============ + +.. automodule:: setup + :members: + :undoc-members: + :show-inheritance: diff --git a/lib/mysql/doc/_build/_sources/setup_common.txt b/lib/mysql/doc/_build/_sources/setup_common.txt new file mode 100644 index 00000000..4ea20c77 --- /dev/null +++ b/lib/mysql/doc/_build/_sources/setup_common.txt @@ -0,0 +1,7 @@ +setup_common Module +=================== + +.. automodule:: setup_common + :members: + :undoc-members: + :show-inheritance: diff --git a/lib/mysql/doc/_build/_sources/setup_posix.txt b/lib/mysql/doc/_build/_sources/setup_posix.txt new file mode 100644 index 00000000..9100360a --- /dev/null +++ b/lib/mysql/doc/_build/_sources/setup_posix.txt @@ -0,0 +1,7 @@ +setup_posix Module +================== + +.. automodule:: setup_posix + :members: + :undoc-members: + :show-inheritance: diff --git a/lib/mysql/doc/_build/_sources/setup_windows.txt b/lib/mysql/doc/_build/_sources/setup_windows.txt new file mode 100644 index 00000000..447046a8 --- /dev/null +++ b/lib/mysql/doc/_build/_sources/setup_windows.txt @@ -0,0 +1,7 @@ +setup_windows Module +==================== + +.. automodule:: setup_windows + :members: + :undoc-members: + :show-inheritance: diff --git a/lib/mysql/doc/_build/_sources/user_guide.txt b/lib/mysql/doc/_build/_sources/user_guide.txt new file mode 100644 index 00000000..fbc86e5f --- /dev/null +++ b/lib/mysql/doc/_build/_sources/user_guide.txt @@ -0,0 +1,718 @@ +==================== +MySQLdb User's Guide +==================== + +.. contents:: +.. + +Introduction +------------ + +MySQLdb is an thread-compatible interface to the popular MySQL +database server that provides the Python database API. + +Installation +------------ + +The ``README`` file has complete installation instructions. + + +_mysql +------ + +If you want to write applications which are portable across databases, +use MySQLdb_, and avoid using this module directly. ``_mysql`` +provides an interface which mostly implements the MySQL C API. For +more information, see the `MySQL documentation`_. The documentation +for this module is intentionally weak because you probably should use +the higher-level MySQLdb module. If you really need it, use the +standard MySQL docs and transliterate as necessary. + +.. _`MySQL documentation`: http://dev.mysql.com/doc/ + + +MySQL C API translation +....................... + +The MySQL C API has been wrapped in an object-oriented way. The only +MySQL data structures which are implemented are the ``MYSQL`` +(database connection handle) and ``MYSQL_RES`` (result handle) +types. In general, any function which takes ``MYSQL *mysql`` as an +argument is now a method of the connection object, and any function +which takes ``MYSQL_RES *result`` as an argument is a method of the +result object. Functions requiring none of the MySQL data structures +are implemented as functions in the module. Functions requiring one of +the other MySQL data structures are generally not implemented. +Deprecated functions are not implemented. In all cases, the ``mysql_`` +prefix is dropped from the name. Most of the ``conn`` methods listed +are also available as MySQLdb Connection object methods. Their use is +non-portable. + +MySQL C API function mapping +............................ + +=================================== ================================== + C API ``_mysql`` +=================================== ================================== + ``mysql_affected_rows()`` ``conn.affected_rows()`` + ``mysql_autocommit()`` ``conn.autocommit()`` + ``mysql_character_set_name()`` ``conn.character_set_name()`` + ``mysql_close()`` ``conn.close()`` + ``mysql_commit()`` ``conn.commit()`` + ``mysql_connect()`` ``_mysql.connect()`` + ``mysql_data_seek()`` ``result.data_seek()`` + ``mysql_debug()`` ``_mysql.debug()`` + ``mysql_dump_debug_info`` ``conn.dump_debug_info()`` + ``mysql_escape_string()`` ``_mysql.escape_string()`` + ``mysql_fetch_row()`` ``result.fetch_row()`` + ``mysql_get_character_set_info()`` ``conn.get_character_set_info()`` + ``mysql_get_client_info()`` ``_mysql.get_client_info()`` + ``mysql_get_host_info()`` ``conn.get_host_info()`` + ``mysql_get_proto_info()`` ``conn.get_proto_info()`` + ``mysql_get_server_info()`` ``conn.get_server_info()`` + ``mysql_info()`` ``conn.info()`` + ``mysql_insert_id()`` ``conn.insert_id()`` + ``mysql_num_fields()`` ``result.num_fields()`` + ``mysql_num_rows()`` ``result.num_rows()`` + ``mysql_options()`` various options to ``_mysql.connect()`` + ``mysql_ping()`` ``conn.ping()`` + ``mysql_query()`` ``conn.query()`` + ``mysql_real_connect()`` ``_mysql.connect()`` + ``mysql_real_query()`` ``conn.query()`` + ``mysql_real_escape_string()`` ``conn.escape_string()`` + ``mysql_rollback()`` ``conn.rollback()`` + ``mysql_row_seek()`` ``result.row_seek()`` + ``mysql_row_tell()`` ``result.row_tell()`` + ``mysql_select_db()`` ``conn.select_db()`` + ``mysql_set_character_set()`` ``conn.set_character_set()`` + ``mysql_ssl_set()`` ``ssl`` option to ``_mysql.connect()`` + ``mysql_stat()`` ``conn.stat()`` + ``mysql_store_result()`` ``conn.store_result()`` + ``mysql_thread_id()`` ``conn.thread_id()`` + ``mysql_thread_safe_client()`` ``conn.thread_safe_client()`` + ``mysql_use_result()`` ``conn.use_result()`` + ``mysql_warning_count()`` ``conn.warning_count()`` + ``CLIENT_*`` ``MySQLdb.constants.CLIENT.*`` + ``CR_*`` ``MySQLdb.constants.CR.*`` + ``ER_*`` ``MySQLdb.constants.ER.*`` + ``FIELD_TYPE_*`` ``MySQLdb.constants.FIELD_TYPE.*`` + ``FLAG_*`` ``MySQLdb.constants.FLAG.*`` +=================================== ================================== + + +Some _mysql examples +.................... + +Okay, so you want to use ``_mysql`` anyway. Here are some examples. + +The simplest possible database connection is:: + + import _mysql + db=_mysql.connect() + +This creates a connection to the MySQL server running on the local +machine using the standard UNIX socket (or named pipe on Windows), +your login name (from the USER environment variable), no password, and +does not ``USE`` a database. Chances are you need to supply more +information.:: + + db=_mysql.connect("localhost","joebob","moonpie","thangs") + +This creates a connection to the MySQL server running on the local +machine via a UNIX socket (or named pipe), the user name "joebob", the +password "moonpie", and selects the initial database "thangs". + +We haven't even begun to touch upon all the parameters ``connect()`` +can take. For this reason, I prefer to use keyword parameters:: + + db=_mysql.connect(host="localhost",user="joebob", + passwd="moonpie",db="thangs") + +This does exactly what the last example did, but is arguably easier to +read. But since the default host is "localhost", and if your login +name really was "joebob", you could shorten it to this:: + + db=_mysql.connect(passwd="moonpie",db="thangs") + +UNIX sockets and named pipes don't work over a network, so if you +specify a host other than localhost, TCP will be used, and you can +specify an odd port if you need to (the default port is 3306):: + + db=_mysql.connect(host="outhouse",port=3307,passwd="moonpie",db="thangs") + +If you really had to, you could connect to the local host with TCP by +specifying the full host name, or 127.0.0.1. + +Generally speaking, putting passwords in your code is not such a good +idea:: + + db=_mysql.connect(host="outhouse",db="thangs",read_default_file="~/.my.cnf") + +This does what the previous example does, but gets the username and +password and other parameters from ~/.my.cnf (UNIX-like systems). Read +about `option files`_ for more details. + +.. _`option files`: http://dev.mysql.com/doc/mysql/en/Option_files.html + +So now you have an open connection as ``db`` and want to do a +query. Well, there are no cursors in MySQL, and no parameter +substitution, so you have to pass a complete query string to +``db.query()``:: + + db.query("""SELECT spam, eggs, sausage FROM breakfast + WHERE price < 5""") + +There's no return value from this, but exceptions can be raised. The +exceptions are defined in a separate module, ``_mysql_exceptions``, +but ``_mysql`` exports them. Read DB API specification PEP-249_ to +find out what they are, or you can use the catch-all ``MySQLError``. + +.. _PEP-249: http://www.python.org/peps/pep-0249.html + +At this point your query has been executed and you need to get the +results. You have two options:: + + r=db.store_result() + # ...or... + r=db.use_result() + +Both methods return a result object. What's the difference? +``store_result()`` returns the entire result set to the client +immediately. If your result set is really large, this could be a +problem. One way around this is to add a ``LIMIT`` clause to your +query, to limit the number of rows returned. The other is to use +``use_result()``, which keeps the result set in the server and sends +it row-by-row when you fetch. This does, however, tie up server +resources, and it ties up the connection: You cannot do any more +queries until you have fetched **all** the rows. Generally I +recommend using ``store_result()`` unless your result set is really +huge and you can't use ``LIMIT`` for some reason. + +Now, for actually getting real results:: + + >>> r.fetch_row() + (('3','2','0'),) + +This might look a little odd. The first thing you should know is, +``fetch_row()`` takes some additional parameters. The first one is, +how many rows (``maxrows``) should be returned. By default, it returns +one row. It may return fewer rows than you asked for, but never +more. If you set ``maxrows=0``, it returns all rows of the result +set. If you ever get an empty tuple back, you ran out of rows. + +The second parameter (``how``) tells it how the row should be +represented. By default, it is zero which means, return as a tuple. +``how=1`` means, return it as a dictionary, where the keys are the +column names, or ``table.column`` if there are two columns with the +same name (say, from a join). ``how=2`` means the same as ``how=1`` +except that the keys are *always* ``table.column``; this is for +compatibility with the old ``Mysqldb`` module. + +OK, so why did we get a 1-tuple with a tuple inside? Because we +implicitly asked for one row, since we didn't specify ``maxrows``. + +The other oddity is: Assuming these are numeric columns, why are they +returned as strings? Because MySQL returns all data as strings and +expects you to convert it yourself. This would be a real pain in the +ass, but in fact, ``_mysql`` can do this for you. (And ``MySQLdb`` +does do this for you.) To have automatic type conversion done, you +need to create a type converter dictionary, and pass this to +``connect()`` as the ``conv`` keyword parameter. + +The keys of ``conv`` should be MySQL column types, which in the +C API are ``FIELD_TYPE_*``. You can get these values like this:: + + from MySQLdb.constants import FIELD_TYPE + +By default, any column type that can't be found in ``conv`` is +returned as a string, which works for a lot of stuff. For our +purposes, we probably want this:: + + my_conv = { FIELD_TYPE.LONG: int } + +This means, if it's a ``FIELD_TYPE_LONG``, call the builtin ``int()`` +function on it. Note that ``FIELD_TYPE_LONG`` is an ``INTEGER`` +column, which corresponds to a C ``long``, which is also the type used +for a normal Python integer. But beware: If it's really an ``UNSIGNED +INTEGER`` column, this could cause overflows. For this reason, +``MySQLdb`` actually uses ``long()`` to do the conversion. But we'll +ignore this potential problem for now. + +Then if you use ``db=_mysql.connect(conv=my_conv...)``, the +results will come back ``((3, 2, 0),)``, which is what you would +expect. + +MySQLdb +------- + +MySQLdb is a thin Python wrapper around ``_mysql`` which makes it +compatible with the Python DB API interface (version 2). In reality, +a fair amount of the code which implements the API is in ``_mysql`` +for the sake of efficiency. + +The DB API specification PEP-249_ should be your primary guide for +using this module. Only deviations from the spec and other +database-dependent things will be documented here. + +Functions and attributes +........................ + +Only a few top-level functions and attributes are defined within +MySQLdb. + +connect(parameters...) + Constructor for creating a connection to the + database. Returns a Connection Object. Parameters are the + same as for the MySQL C API. In addition, there are a few + additional keywords that correspond to what you would pass + ``mysql_options()`` before connecting. Note that some + parameters must be specified as keyword arguments! The + default value for each parameter is NULL or zero, as + appropriate. Consult the MySQL documentation for more + details. The important parameters are: + + host + name of host to connect to. Default: use the local host + via a UNIX socket (where applicable) + + user + user to authenticate as. Default: current effective user. + + passwd + password to authenticate with. Default: no password. + + db + database to use. Default: no default database. + + port + TCP port of MySQL server. Default: standard port (3306). + + unix_socket + location of UNIX socket. Default: use default location or + TCP for remote hosts. + + conv + type conversion dictionary. Default: a copy of + ``MySQLdb.converters.conversions`` + + compress + Enable protocol compression. Default: no compression. + + connect_timeout + Abort if connect is not completed within + given number of seconds. Default: no timeout (?) + + named_pipe + Use a named pipe (Windows). Default: don't. + + init_command + Initial command to issue to server upon + connection. Default: Nothing. + + read_default_file + MySQL configuration file to read; see + the MySQL documentation for ``mysql_options()``. + + read_default_group + Default group to read; see the MySQL + documentation for ``mysql_options()``. + + cursorclass + cursor class that ``cursor()`` uses, unless + overridden. Default: ``MySQLdb.cursors.Cursor``. *This + must be a keyword parameter.* + + use_unicode + If True, CHAR and VARCHAR and TEXT columns are returned as + Unicode strings, using the configured character set. It is + best to set the default encoding in the server + configuration, or client configuration (read with + read_default_file). If you change the character set after + connecting (MySQL-4.1 and later), you'll need to put the + correct character set name in connection.charset. + + If False, text-like columns are returned as normal strings, + but you can always write Unicode strings. + + *This must be a keyword parameter.* + + charset + If present, the connection character set will be changed + to this character set, if they are not equal. Support for + changing the character set requires MySQL-4.1 and later + server; if the server is too old, UnsupportedError will be + raised. This option implies use_unicode=True, but you can + override this with use_unicode=False, though you probably + shouldn't. + + If not present, the default character set is used. + + *This must be a keyword parameter.* + + sql_mode + If present, the session SQL mode will be set to the given + string. For more information on sql_mode, see the MySQL + documentation. Only available for 4.1 and newer servers. + + If not present, the session SQL mode will be unchanged. + + *This must be a keyword parameter.* + + ssl + This parameter takes a dictionary or mapping, where the + keys are parameter names used by the mysql_ssl_set_ MySQL + C API call. If this is set, it initiates an SSL connection + to the server; if there is no SSL support in the client, + an exception is raised. *This must be a keyword + parameter.* + +.. _mysql_ssl_set: http://dev.mysql.com/doc/mysql/en/mysql_ssl_set.html + + +apilevel + String constant stating the supported DB API level. '2.0' + +threadsafety + Integer constant stating the level of thread safety the + interface supports. This is set to 1, which means: Threads may + share the module. + + The MySQL protocol can not handle multiple threads using the + same connection at once. Some earlier versions of MySQLdb + utilized locking to achieve a threadsafety of 2. While this is + not terribly hard to accomplish using the standard Cursor class + (which uses ``mysql_store_result()``), it is complicated by + SSCursor (which uses ``mysql_use_result()``; with the latter you + must ensure all the rows have been read before another query can + be executed. It is further complicated by the addition of + transactions, since transactions start when a cursor execute a + query, but end when ``COMMIT`` or ``ROLLBACK`` is executed by + the Connection object. Two threads simply cannot share a + connection while a transaction is in progress, in addition to + not being able to share it during query execution. This + excessively complicated the code to the point where it just + isn't worth it. + + The general upshot of this is: Don't share connections between + threads. It's really not worth your effort or mine, and in the + end, will probably hurt performance, since the MySQL server runs + a separate thread for each connection. You can certainly do + things like cache connections in a pool, and give those + connections to one thread at a time. If you let two threads use + a connection simultaneously, the MySQL client library will + probably upchuck and die. You have been warned. + + For threaded applications, try using a connection pool. + This can be done using the `Pool module`_. + + .. _`Pool module`: http://dustman.net/andy/python/Pool + +charset + The character set used by the connection. In MySQL-4.1 and newer, + it is possible (but not recommended) to change the connection's + character set with an SQL statement. If you do this, you'll also + need to change this attribute. Otherwise, you'll get encoding + errors. + +paramstyle + String constant stating the type of parameter marker formatting + expected by the interface. Set to 'format' = ANSI C printf + format codes, e.g. '...WHERE name=%s'. If a mapping object is + used for conn.execute(), then the interface actually uses + 'pyformat' = Python extended format codes, e.g. '...WHERE + name=%(name)s'. However, the API does not presently allow the + specification of more than one style in paramstyle. + + Note that any literal percent signs in the query string passed + to execute() must be escaped, i.e. %%. + + Parameter placeholders can **only** be used to insert column + values. They can **not** be used for other parts of SQL, such as + table names, statements, etc. + +conv + A dictionary or mapping which controls how types are converted + from MySQL to Python and vice versa. + + If the key is a MySQL type (from ``FIELD_TYPE.*``), then the value + can be either: + + * a callable object which takes a string argument (the MySQL + value),' returning a Python value + + * a sequence of 2-tuples, where the first value is a combination + of flags from ``MySQLdb.constants.FLAG``, and the second value + is a function as above. The sequence is tested until the flags + on the field match those of the first value. If both values + are None, then the default conversion is done. Presently this + is only used to distinquish TEXT and BLOB columns. + + If the key is a Python type or class, then the value is a + callable Python object (usually a function) taking two arguments + (value to convert, and the conversion dictionary) which converts + values of this type to a SQL literal string value. + + This is initialized with reasonable defaults for most + types. When creating a Connection object, you can pass your own + type converter dictionary as a keyword parameter. Otherwise, it + uses a copy of ``MySQLdb.converters.conversions``. Several + non-standard types are returned as strings, which is how MySQL + returns all columns. For more details, see the built-in module + documentation. + + +Connection Objects +.................. + +Connection objects are returned by the ``connect()`` function. + +commit() + If the database and the tables support transactions, this + commits the current transaction; otherwise this method + successfully does nothing. + +rollback() + If the database and tables support transactions, this rolls back + (cancels) the current transaction; otherwise a + ``NotSupportedError`` is raised. + +cursor([cursorclass]) + MySQL does not support cursors; however, cursors are easily + emulated. You can supply an alternative cursor class as an + optional parameter. If this is not present, it defaults to the + value given when creating the connection object, or the standard + ``Cursor`` class. Also see the additional supplied cursor + classes in the usage section. + +There are many more methods defined on the connection object which +are MySQL-specific. For more information on them, consult the internal +documentation using ``pydoc``. + + +Cursor Objects +.............. + +callproc(procname, args) + Calls stored procedure procname with the sequence of arguments + in args. Returns the original arguments. Stored procedure + support only works with MySQL-5.0 and newer. + + **Compatibility note:** PEP-249_ specifies that if there are + OUT or INOUT parameters, the modified values are to be + returned. This is not consistently possible with MySQL. Stored + procedure arguments must be passed as server variables, and + can only be returned with a SELECT statement. Since a stored + procedure may return zero or more result sets, it is impossible + for MySQLdb to determine if there are result sets to fetch + before the modified parmeters are accessible. + + The parameters are stored in the server as @_*procname*_*n*, + where *n* is the position of the parameter. I.e., if you + cursor.callproc('foo', (a, b, c)), the parameters will be + accessible by a SELECT statement as @_foo_0, @_foo_1, and + @_foo_2. + + **Compatibility note:** It appears that the mere act of + executing the CALL statement produces an empty result set, which + appears after any result sets which might be generated by the + stored procedure. Thus, you will always need to use nextset() to + advance result sets. + +close() + Closes the cursor. Future operations raise ``ProgrammingError``. + If you are using server-side cursors, it is very important to + close the cursor when you are done with it and before creating a + new one. + +info() + Returns some information about the last query. Normally + you don't need to check this. If there are any MySQL + warnings, it will cause a Warning to be issued through + the Python warning module. By default, Warning causes a + message to appear on the console. However, it is possible + to filter these out or cause Warning to be raised as exception. + See the MySQL docs for ``mysql_info()``, and the Python warning + module. (Non-standard) + +setinputsizes() + Does nothing, successfully. + +setoutputsizes() + Does nothing, successfully. + +nextset() + Advances the cursor to the next result set, discarding the remaining + rows in the current result set. If there are no additional result + sets, it returns None; otherwise it returns a true value. + + Note that MySQL doesn't support multiple result sets until 4.1. + + +Some examples +............. + +The ``connect()`` method works nearly the same as with `_mysql`_:: + + import MySQLdb + db=MySQLdb.connect(passwd="moonpie",db="thangs") + +To perform a query, you first need a cursor, and then you can execute +queries on it:: + + c=db.cursor() + max_price=5 + c.execute("""SELECT spam, eggs, sausage FROM breakfast + WHERE price < %s""", (max_price,)) + +In this example, ``max_price=5`` Why, then, use ``%s`` in the +string? Because MySQLdb will convert it to a SQL literal value, which +is the string '5'. When it's finished, the query will actually say, +"...WHERE price < 5". + +Why the tuple? Because the DB API requires you to pass in any +parameters as a sequence. Due to the design of the parser, (max_price) +is interpreted as using algebraic grouping and simply as max_price and +not a tuple. Adding a comma, i.e. (max_price,) forces it to make a +tuple. + +And now, the results:: + + >>> c.fetchone() + (3L, 2L, 0L) + +Quite unlike the ``_mysql`` example, this returns a single tuple, +which is the row, and the values are properly converted by default... +except... What's with the L's? + +As mentioned earlier, while MySQL's INTEGER column translates +perfectly into a Python integer, UNSIGNED INTEGER could overflow, so +these values are converted to Python long integers instead. + +If you wanted more rows, you could use ``c.fetchmany(n)`` or +``c.fetchall()``. These do exactly what you think they do. On +``c.fetchmany(n)``, the ``n`` is optional and defaults to +``c.arraysize``, which is normally 1. Both of these methods return a +sequence of rows, or an empty sequence if there are no more rows. If +you use a weird cursor class, the rows themselves might not be tuples. + +Note that in contrast to the above, ``c.fetchone()`` returns ``None`` +when there are no more rows to fetch. + +The only other method you are very likely to use is when you have to +do a multi-row insert:: + + c.executemany( + """INSERT INTO breakfast (name, spam, eggs, sausage, price) + VALUES (%s, %s, %s, %s, %s)""", + [ + ("Spam and Sausage Lover's Plate", 5, 1, 8, 7.95 ), + ("Not So Much Spam Plate", 3, 2, 0, 3.95 ), + ("Don't Wany ANY SPAM! Plate", 0, 4, 3, 5.95 ) + ] ) + +Here we are inserting three rows of five values. Notice that there is +a mix of types (strings, ints, floats) though we still only use +``%s``. And also note that we only included format strings for one +row. MySQLdb picks those out and duplicates them for each row. + +Using and extending +------------------- + +In general, it is probably wise to not directly interact with the DB +API except for small applicatons. Databases, even SQL databases, vary +widely in capabilities and may have non-standard features. The DB API +does a good job of providing a reasonably portable interface but some +methods are non-portable. Specifically, the parameters accepted by +``connect()`` are completely implementation-dependent. + +If you believe your application may need to run on several different +databases, the author recommends the following approach, based on +personal experience: Write a simplified API for your application which +implements the specific queries and operations your application needs +to perform. Implement this API as a base class which should be have +few database dependencies, and then derive a subclass from this which +implements the necessary dependencies. In this way, porting your +application to a new database should be a relatively simple matter of +creating a new subclass, assuming the new database is reasonably +standard. + +Because MySQLdb's Connection and Cursor objects are written in Python, +you can easily derive your own subclasses. There are several Cursor +classes in MySQLdb.cursors: + +BaseCursor + The base class for Cursor objects. This does not raise Warnings. + +CursorStoreResultMixIn + Causes the Cursor to use the ``mysql_store_result()`` function to + get the query result. The entire result set is stored on the + client side. + +CursorUseResultMixIn + Causes the cursor to use the ``mysql_use_result()`` function to + get the query result. The result set is stored on the server side + and is transferred row by row using fetch operations. + +CursorTupleRowsMixIn + Causes the cursor to return rows as a tuple of the column values. + +CursorDictRowsMixIn + + Causes the cursor to return rows as a dictionary, where the keys + are column names and the values are column values. Note that if + the column names are not unique, i.e., you are selecting from two + tables that share column names, some of them will be rewritten as + ``table.column``. This can be avoided by using the SQL ``AS`` + keyword. (This is yet-another reason not to use ``*`` in SQL + queries, particularly where ``JOIN`` is involved.) + +Cursor + The default cursor class. This class is composed of + ``CursorWarningMixIn``, ``CursorStoreResultMixIn``, + ``CursorTupleRowsMixIn,`` and ``BaseCursor``, i.e. it raises + ``Warning``, uses ``mysql_store_result()``, and returns rows as + tuples. + +DictCursor + Like ``Cursor`` except it returns rows as dictionaries. + +SSCursor + A "server-side" cursor. Like ``Cursor`` but uses + ``CursorUseResultMixIn``. Use only if you are dealing with + potentially large result sets. + +SSDictCursor + Like ``SSCursor`` except it returns rows as dictionaries. + + +Embedded Server +--------------- + +Instead of connecting to a stand-alone server over the network, +the embedded server support lets you run a full server right in +your Python code or application server. + +If you have built MySQLdb with embedded server support, there +are two additional functions you will need to make use of: + + server_init(args, groups) + Initialize embedded server. If this client is not linked against + the embedded server library, this function does nothing. + + args + sequence of command-line arguments + groups + sequence of groups to use in defaults files + + server_end() + Shut down embedded server. If not using an embedded server, this + does nothing. + +See the MySQL documentation for more information on the embedded +server. + + + +:Title: MySQLdb: a Python interface for MySQL +:Author: Andy Dustman +:Version: $Revision$ diff --git a/lib/mysql/doc/_mysql.rst b/lib/mysql/doc/_mysql.rst new file mode 100644 index 00000000..4a60591b --- /dev/null +++ b/lib/mysql/doc/_mysql.rst @@ -0,0 +1,7 @@ +_mysql Module +============= + +.. automodule:: _mysql + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/lib/mysql/doc/_mysql_exceptions.rst b/lib/mysql/doc/_mysql_exceptions.rst new file mode 100644 index 00000000..9b65de35 --- /dev/null +++ b/lib/mysql/doc/_mysql_exceptions.rst @@ -0,0 +1,7 @@ +_mysql_exceptions Module +======================== + +.. automodule:: _mysql_exceptions + :members: + :undoc-members: + :show-inheritance: diff --git a/lib/mysql/doc/conf.py b/lib/mysql/doc/conf.py new file mode 100644 index 00000000..ab36b07f --- /dev/null +++ b/lib/mysql/doc/conf.py @@ -0,0 +1,242 @@ +# -*- coding: utf-8 -*- +# +# MySQLdb documentation build configuration file, created by +# sphinx-quickstart on Sun Oct 07 19:36:17 2012. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ----------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['sphinx.ext.autodoc'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'MySQLdb' +copyright = u'2012, Andy Dustman' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '1.2' +# The full version, including alpha/beta/rc tags. +release = '1.2.4b4' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'MySQLdbdoc' + + +# -- Options for LaTeX output -------------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'MySQLdb.tex', u'MySQLdb Documentation', + u'Andy Dustman', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output -------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'mysqldb', u'MySQLdb Documentation', + [u'Andy Dustman'], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------------ + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('index', 'MySQLdb', u'MySQLdb Documentation', + u'Andy Dustman', 'MySQLdb', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' diff --git a/lib/mysql/doc/index.rst b/lib/mysql/doc/index.rst new file mode 100644 index 00000000..a0b3fd57 --- /dev/null +++ b/lib/mysql/doc/index.rst @@ -0,0 +1,24 @@ +.. MySQLdb documentation master file, created by + sphinx-quickstart on Sun Oct 07 19:36:17 2012. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to MySQLdb's documentation! +=================================== + +Contents: + +.. toctree:: + :maxdepth: 3 + + user_guide + MySQLdb + FAQ + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/lib/mysql/doc/modules.rst b/lib/mysql/doc/modules.rst new file mode 100644 index 00000000..7cf3faaa --- /dev/null +++ b/lib/mysql/doc/modules.rst @@ -0,0 +1,7 @@ +MySQLdb +======= + +.. toctree:: + :maxdepth: 4 + + MySQLdb diff --git a/lib/mysql/doc/user_guide.rst b/lib/mysql/doc/user_guide.rst new file mode 100644 index 00000000..fbc86e5f --- /dev/null +++ b/lib/mysql/doc/user_guide.rst @@ -0,0 +1,718 @@ +==================== +MySQLdb User's Guide +==================== + +.. contents:: +.. + +Introduction +------------ + +MySQLdb is an thread-compatible interface to the popular MySQL +database server that provides the Python database API. + +Installation +------------ + +The ``README`` file has complete installation instructions. + + +_mysql +------ + +If you want to write applications which are portable across databases, +use MySQLdb_, and avoid using this module directly. ``_mysql`` +provides an interface which mostly implements the MySQL C API. For +more information, see the `MySQL documentation`_. The documentation +for this module is intentionally weak because you probably should use +the higher-level MySQLdb module. If you really need it, use the +standard MySQL docs and transliterate as necessary. + +.. _`MySQL documentation`: http://dev.mysql.com/doc/ + + +MySQL C API translation +....................... + +The MySQL C API has been wrapped in an object-oriented way. The only +MySQL data structures which are implemented are the ``MYSQL`` +(database connection handle) and ``MYSQL_RES`` (result handle) +types. In general, any function which takes ``MYSQL *mysql`` as an +argument is now a method of the connection object, and any function +which takes ``MYSQL_RES *result`` as an argument is a method of the +result object. Functions requiring none of the MySQL data structures +are implemented as functions in the module. Functions requiring one of +the other MySQL data structures are generally not implemented. +Deprecated functions are not implemented. In all cases, the ``mysql_`` +prefix is dropped from the name. Most of the ``conn`` methods listed +are also available as MySQLdb Connection object methods. Their use is +non-portable. + +MySQL C API function mapping +............................ + +=================================== ================================== + C API ``_mysql`` +=================================== ================================== + ``mysql_affected_rows()`` ``conn.affected_rows()`` + ``mysql_autocommit()`` ``conn.autocommit()`` + ``mysql_character_set_name()`` ``conn.character_set_name()`` + ``mysql_close()`` ``conn.close()`` + ``mysql_commit()`` ``conn.commit()`` + ``mysql_connect()`` ``_mysql.connect()`` + ``mysql_data_seek()`` ``result.data_seek()`` + ``mysql_debug()`` ``_mysql.debug()`` + ``mysql_dump_debug_info`` ``conn.dump_debug_info()`` + ``mysql_escape_string()`` ``_mysql.escape_string()`` + ``mysql_fetch_row()`` ``result.fetch_row()`` + ``mysql_get_character_set_info()`` ``conn.get_character_set_info()`` + ``mysql_get_client_info()`` ``_mysql.get_client_info()`` + ``mysql_get_host_info()`` ``conn.get_host_info()`` + ``mysql_get_proto_info()`` ``conn.get_proto_info()`` + ``mysql_get_server_info()`` ``conn.get_server_info()`` + ``mysql_info()`` ``conn.info()`` + ``mysql_insert_id()`` ``conn.insert_id()`` + ``mysql_num_fields()`` ``result.num_fields()`` + ``mysql_num_rows()`` ``result.num_rows()`` + ``mysql_options()`` various options to ``_mysql.connect()`` + ``mysql_ping()`` ``conn.ping()`` + ``mysql_query()`` ``conn.query()`` + ``mysql_real_connect()`` ``_mysql.connect()`` + ``mysql_real_query()`` ``conn.query()`` + ``mysql_real_escape_string()`` ``conn.escape_string()`` + ``mysql_rollback()`` ``conn.rollback()`` + ``mysql_row_seek()`` ``result.row_seek()`` + ``mysql_row_tell()`` ``result.row_tell()`` + ``mysql_select_db()`` ``conn.select_db()`` + ``mysql_set_character_set()`` ``conn.set_character_set()`` + ``mysql_ssl_set()`` ``ssl`` option to ``_mysql.connect()`` + ``mysql_stat()`` ``conn.stat()`` + ``mysql_store_result()`` ``conn.store_result()`` + ``mysql_thread_id()`` ``conn.thread_id()`` + ``mysql_thread_safe_client()`` ``conn.thread_safe_client()`` + ``mysql_use_result()`` ``conn.use_result()`` + ``mysql_warning_count()`` ``conn.warning_count()`` + ``CLIENT_*`` ``MySQLdb.constants.CLIENT.*`` + ``CR_*`` ``MySQLdb.constants.CR.*`` + ``ER_*`` ``MySQLdb.constants.ER.*`` + ``FIELD_TYPE_*`` ``MySQLdb.constants.FIELD_TYPE.*`` + ``FLAG_*`` ``MySQLdb.constants.FLAG.*`` +=================================== ================================== + + +Some _mysql examples +.................... + +Okay, so you want to use ``_mysql`` anyway. Here are some examples. + +The simplest possible database connection is:: + + import _mysql + db=_mysql.connect() + +This creates a connection to the MySQL server running on the local +machine using the standard UNIX socket (or named pipe on Windows), +your login name (from the USER environment variable), no password, and +does not ``USE`` a database. Chances are you need to supply more +information.:: + + db=_mysql.connect("localhost","joebob","moonpie","thangs") + +This creates a connection to the MySQL server running on the local +machine via a UNIX socket (or named pipe), the user name "joebob", the +password "moonpie", and selects the initial database "thangs". + +We haven't even begun to touch upon all the parameters ``connect()`` +can take. For this reason, I prefer to use keyword parameters:: + + db=_mysql.connect(host="localhost",user="joebob", + passwd="moonpie",db="thangs") + +This does exactly what the last example did, but is arguably easier to +read. But since the default host is "localhost", and if your login +name really was "joebob", you could shorten it to this:: + + db=_mysql.connect(passwd="moonpie",db="thangs") + +UNIX sockets and named pipes don't work over a network, so if you +specify a host other than localhost, TCP will be used, and you can +specify an odd port if you need to (the default port is 3306):: + + db=_mysql.connect(host="outhouse",port=3307,passwd="moonpie",db="thangs") + +If you really had to, you could connect to the local host with TCP by +specifying the full host name, or 127.0.0.1. + +Generally speaking, putting passwords in your code is not such a good +idea:: + + db=_mysql.connect(host="outhouse",db="thangs",read_default_file="~/.my.cnf") + +This does what the previous example does, but gets the username and +password and other parameters from ~/.my.cnf (UNIX-like systems). Read +about `option files`_ for more details. + +.. _`option files`: http://dev.mysql.com/doc/mysql/en/Option_files.html + +So now you have an open connection as ``db`` and want to do a +query. Well, there are no cursors in MySQL, and no parameter +substitution, so you have to pass a complete query string to +``db.query()``:: + + db.query("""SELECT spam, eggs, sausage FROM breakfast + WHERE price < 5""") + +There's no return value from this, but exceptions can be raised. The +exceptions are defined in a separate module, ``_mysql_exceptions``, +but ``_mysql`` exports them. Read DB API specification PEP-249_ to +find out what they are, or you can use the catch-all ``MySQLError``. + +.. _PEP-249: http://www.python.org/peps/pep-0249.html + +At this point your query has been executed and you need to get the +results. You have two options:: + + r=db.store_result() + # ...or... + r=db.use_result() + +Both methods return a result object. What's the difference? +``store_result()`` returns the entire result set to the client +immediately. If your result set is really large, this could be a +problem. One way around this is to add a ``LIMIT`` clause to your +query, to limit the number of rows returned. The other is to use +``use_result()``, which keeps the result set in the server and sends +it row-by-row when you fetch. This does, however, tie up server +resources, and it ties up the connection: You cannot do any more +queries until you have fetched **all** the rows. Generally I +recommend using ``store_result()`` unless your result set is really +huge and you can't use ``LIMIT`` for some reason. + +Now, for actually getting real results:: + + >>> r.fetch_row() + (('3','2','0'),) + +This might look a little odd. The first thing you should know is, +``fetch_row()`` takes some additional parameters. The first one is, +how many rows (``maxrows``) should be returned. By default, it returns +one row. It may return fewer rows than you asked for, but never +more. If you set ``maxrows=0``, it returns all rows of the result +set. If you ever get an empty tuple back, you ran out of rows. + +The second parameter (``how``) tells it how the row should be +represented. By default, it is zero which means, return as a tuple. +``how=1`` means, return it as a dictionary, where the keys are the +column names, or ``table.column`` if there are two columns with the +same name (say, from a join). ``how=2`` means the same as ``how=1`` +except that the keys are *always* ``table.column``; this is for +compatibility with the old ``Mysqldb`` module. + +OK, so why did we get a 1-tuple with a tuple inside? Because we +implicitly asked for one row, since we didn't specify ``maxrows``. + +The other oddity is: Assuming these are numeric columns, why are they +returned as strings? Because MySQL returns all data as strings and +expects you to convert it yourself. This would be a real pain in the +ass, but in fact, ``_mysql`` can do this for you. (And ``MySQLdb`` +does do this for you.) To have automatic type conversion done, you +need to create a type converter dictionary, and pass this to +``connect()`` as the ``conv`` keyword parameter. + +The keys of ``conv`` should be MySQL column types, which in the +C API are ``FIELD_TYPE_*``. You can get these values like this:: + + from MySQLdb.constants import FIELD_TYPE + +By default, any column type that can't be found in ``conv`` is +returned as a string, which works for a lot of stuff. For our +purposes, we probably want this:: + + my_conv = { FIELD_TYPE.LONG: int } + +This means, if it's a ``FIELD_TYPE_LONG``, call the builtin ``int()`` +function on it. Note that ``FIELD_TYPE_LONG`` is an ``INTEGER`` +column, which corresponds to a C ``long``, which is also the type used +for a normal Python integer. But beware: If it's really an ``UNSIGNED +INTEGER`` column, this could cause overflows. For this reason, +``MySQLdb`` actually uses ``long()`` to do the conversion. But we'll +ignore this potential problem for now. + +Then if you use ``db=_mysql.connect(conv=my_conv...)``, the +results will come back ``((3, 2, 0),)``, which is what you would +expect. + +MySQLdb +------- + +MySQLdb is a thin Python wrapper around ``_mysql`` which makes it +compatible with the Python DB API interface (version 2). In reality, +a fair amount of the code which implements the API is in ``_mysql`` +for the sake of efficiency. + +The DB API specification PEP-249_ should be your primary guide for +using this module. Only deviations from the spec and other +database-dependent things will be documented here. + +Functions and attributes +........................ + +Only a few top-level functions and attributes are defined within +MySQLdb. + +connect(parameters...) + Constructor for creating a connection to the + database. Returns a Connection Object. Parameters are the + same as for the MySQL C API. In addition, there are a few + additional keywords that correspond to what you would pass + ``mysql_options()`` before connecting. Note that some + parameters must be specified as keyword arguments! The + default value for each parameter is NULL or zero, as + appropriate. Consult the MySQL documentation for more + details. The important parameters are: + + host + name of host to connect to. Default: use the local host + via a UNIX socket (where applicable) + + user + user to authenticate as. Default: current effective user. + + passwd + password to authenticate with. Default: no password. + + db + database to use. Default: no default database. + + port + TCP port of MySQL server. Default: standard port (3306). + + unix_socket + location of UNIX socket. Default: use default location or + TCP for remote hosts. + + conv + type conversion dictionary. Default: a copy of + ``MySQLdb.converters.conversions`` + + compress + Enable protocol compression. Default: no compression. + + connect_timeout + Abort if connect is not completed within + given number of seconds. Default: no timeout (?) + + named_pipe + Use a named pipe (Windows). Default: don't. + + init_command + Initial command to issue to server upon + connection. Default: Nothing. + + read_default_file + MySQL configuration file to read; see + the MySQL documentation for ``mysql_options()``. + + read_default_group + Default group to read; see the MySQL + documentation for ``mysql_options()``. + + cursorclass + cursor class that ``cursor()`` uses, unless + overridden. Default: ``MySQLdb.cursors.Cursor``. *This + must be a keyword parameter.* + + use_unicode + If True, CHAR and VARCHAR and TEXT columns are returned as + Unicode strings, using the configured character set. It is + best to set the default encoding in the server + configuration, or client configuration (read with + read_default_file). If you change the character set after + connecting (MySQL-4.1 and later), you'll need to put the + correct character set name in connection.charset. + + If False, text-like columns are returned as normal strings, + but you can always write Unicode strings. + + *This must be a keyword parameter.* + + charset + If present, the connection character set will be changed + to this character set, if they are not equal. Support for + changing the character set requires MySQL-4.1 and later + server; if the server is too old, UnsupportedError will be + raised. This option implies use_unicode=True, but you can + override this with use_unicode=False, though you probably + shouldn't. + + If not present, the default character set is used. + + *This must be a keyword parameter.* + + sql_mode + If present, the session SQL mode will be set to the given + string. For more information on sql_mode, see the MySQL + documentation. Only available for 4.1 and newer servers. + + If not present, the session SQL mode will be unchanged. + + *This must be a keyword parameter.* + + ssl + This parameter takes a dictionary or mapping, where the + keys are parameter names used by the mysql_ssl_set_ MySQL + C API call. If this is set, it initiates an SSL connection + to the server; if there is no SSL support in the client, + an exception is raised. *This must be a keyword + parameter.* + +.. _mysql_ssl_set: http://dev.mysql.com/doc/mysql/en/mysql_ssl_set.html + + +apilevel + String constant stating the supported DB API level. '2.0' + +threadsafety + Integer constant stating the level of thread safety the + interface supports. This is set to 1, which means: Threads may + share the module. + + The MySQL protocol can not handle multiple threads using the + same connection at once. Some earlier versions of MySQLdb + utilized locking to achieve a threadsafety of 2. While this is + not terribly hard to accomplish using the standard Cursor class + (which uses ``mysql_store_result()``), it is complicated by + SSCursor (which uses ``mysql_use_result()``; with the latter you + must ensure all the rows have been read before another query can + be executed. It is further complicated by the addition of + transactions, since transactions start when a cursor execute a + query, but end when ``COMMIT`` or ``ROLLBACK`` is executed by + the Connection object. Two threads simply cannot share a + connection while a transaction is in progress, in addition to + not being able to share it during query execution. This + excessively complicated the code to the point where it just + isn't worth it. + + The general upshot of this is: Don't share connections between + threads. It's really not worth your effort or mine, and in the + end, will probably hurt performance, since the MySQL server runs + a separate thread for each connection. You can certainly do + things like cache connections in a pool, and give those + connections to one thread at a time. If you let two threads use + a connection simultaneously, the MySQL client library will + probably upchuck and die. You have been warned. + + For threaded applications, try using a connection pool. + This can be done using the `Pool module`_. + + .. _`Pool module`: http://dustman.net/andy/python/Pool + +charset + The character set used by the connection. In MySQL-4.1 and newer, + it is possible (but not recommended) to change the connection's + character set with an SQL statement. If you do this, you'll also + need to change this attribute. Otherwise, you'll get encoding + errors. + +paramstyle + String constant stating the type of parameter marker formatting + expected by the interface. Set to 'format' = ANSI C printf + format codes, e.g. '...WHERE name=%s'. If a mapping object is + used for conn.execute(), then the interface actually uses + 'pyformat' = Python extended format codes, e.g. '...WHERE + name=%(name)s'. However, the API does not presently allow the + specification of more than one style in paramstyle. + + Note that any literal percent signs in the query string passed + to execute() must be escaped, i.e. %%. + + Parameter placeholders can **only** be used to insert column + values. They can **not** be used for other parts of SQL, such as + table names, statements, etc. + +conv + A dictionary or mapping which controls how types are converted + from MySQL to Python and vice versa. + + If the key is a MySQL type (from ``FIELD_TYPE.*``), then the value + can be either: + + * a callable object which takes a string argument (the MySQL + value),' returning a Python value + + * a sequence of 2-tuples, where the first value is a combination + of flags from ``MySQLdb.constants.FLAG``, and the second value + is a function as above. The sequence is tested until the flags + on the field match those of the first value. If both values + are None, then the default conversion is done. Presently this + is only used to distinquish TEXT and BLOB columns. + + If the key is a Python type or class, then the value is a + callable Python object (usually a function) taking two arguments + (value to convert, and the conversion dictionary) which converts + values of this type to a SQL literal string value. + + This is initialized with reasonable defaults for most + types. When creating a Connection object, you can pass your own + type converter dictionary as a keyword parameter. Otherwise, it + uses a copy of ``MySQLdb.converters.conversions``. Several + non-standard types are returned as strings, which is how MySQL + returns all columns. For more details, see the built-in module + documentation. + + +Connection Objects +.................. + +Connection objects are returned by the ``connect()`` function. + +commit() + If the database and the tables support transactions, this + commits the current transaction; otherwise this method + successfully does nothing. + +rollback() + If the database and tables support transactions, this rolls back + (cancels) the current transaction; otherwise a + ``NotSupportedError`` is raised. + +cursor([cursorclass]) + MySQL does not support cursors; however, cursors are easily + emulated. You can supply an alternative cursor class as an + optional parameter. If this is not present, it defaults to the + value given when creating the connection object, or the standard + ``Cursor`` class. Also see the additional supplied cursor + classes in the usage section. + +There are many more methods defined on the connection object which +are MySQL-specific. For more information on them, consult the internal +documentation using ``pydoc``. + + +Cursor Objects +.............. + +callproc(procname, args) + Calls stored procedure procname with the sequence of arguments + in args. Returns the original arguments. Stored procedure + support only works with MySQL-5.0 and newer. + + **Compatibility note:** PEP-249_ specifies that if there are + OUT or INOUT parameters, the modified values are to be + returned. This is not consistently possible with MySQL. Stored + procedure arguments must be passed as server variables, and + can only be returned with a SELECT statement. Since a stored + procedure may return zero or more result sets, it is impossible + for MySQLdb to determine if there are result sets to fetch + before the modified parmeters are accessible. + + The parameters are stored in the server as @_*procname*_*n*, + where *n* is the position of the parameter. I.e., if you + cursor.callproc('foo', (a, b, c)), the parameters will be + accessible by a SELECT statement as @_foo_0, @_foo_1, and + @_foo_2. + + **Compatibility note:** It appears that the mere act of + executing the CALL statement produces an empty result set, which + appears after any result sets which might be generated by the + stored procedure. Thus, you will always need to use nextset() to + advance result sets. + +close() + Closes the cursor. Future operations raise ``ProgrammingError``. + If you are using server-side cursors, it is very important to + close the cursor when you are done with it and before creating a + new one. + +info() + Returns some information about the last query. Normally + you don't need to check this. If there are any MySQL + warnings, it will cause a Warning to be issued through + the Python warning module. By default, Warning causes a + message to appear on the console. However, it is possible + to filter these out or cause Warning to be raised as exception. + See the MySQL docs for ``mysql_info()``, and the Python warning + module. (Non-standard) + +setinputsizes() + Does nothing, successfully. + +setoutputsizes() + Does nothing, successfully. + +nextset() + Advances the cursor to the next result set, discarding the remaining + rows in the current result set. If there are no additional result + sets, it returns None; otherwise it returns a true value. + + Note that MySQL doesn't support multiple result sets until 4.1. + + +Some examples +............. + +The ``connect()`` method works nearly the same as with `_mysql`_:: + + import MySQLdb + db=MySQLdb.connect(passwd="moonpie",db="thangs") + +To perform a query, you first need a cursor, and then you can execute +queries on it:: + + c=db.cursor() + max_price=5 + c.execute("""SELECT spam, eggs, sausage FROM breakfast + WHERE price < %s""", (max_price,)) + +In this example, ``max_price=5`` Why, then, use ``%s`` in the +string? Because MySQLdb will convert it to a SQL literal value, which +is the string '5'. When it's finished, the query will actually say, +"...WHERE price < 5". + +Why the tuple? Because the DB API requires you to pass in any +parameters as a sequence. Due to the design of the parser, (max_price) +is interpreted as using algebraic grouping and simply as max_price and +not a tuple. Adding a comma, i.e. (max_price,) forces it to make a +tuple. + +And now, the results:: + + >>> c.fetchone() + (3L, 2L, 0L) + +Quite unlike the ``_mysql`` example, this returns a single tuple, +which is the row, and the values are properly converted by default... +except... What's with the L's? + +As mentioned earlier, while MySQL's INTEGER column translates +perfectly into a Python integer, UNSIGNED INTEGER could overflow, so +these values are converted to Python long integers instead. + +If you wanted more rows, you could use ``c.fetchmany(n)`` or +``c.fetchall()``. These do exactly what you think they do. On +``c.fetchmany(n)``, the ``n`` is optional and defaults to +``c.arraysize``, which is normally 1. Both of these methods return a +sequence of rows, or an empty sequence if there are no more rows. If +you use a weird cursor class, the rows themselves might not be tuples. + +Note that in contrast to the above, ``c.fetchone()`` returns ``None`` +when there are no more rows to fetch. + +The only other method you are very likely to use is when you have to +do a multi-row insert:: + + c.executemany( + """INSERT INTO breakfast (name, spam, eggs, sausage, price) + VALUES (%s, %s, %s, %s, %s)""", + [ + ("Spam and Sausage Lover's Plate", 5, 1, 8, 7.95 ), + ("Not So Much Spam Plate", 3, 2, 0, 3.95 ), + ("Don't Wany ANY SPAM! Plate", 0, 4, 3, 5.95 ) + ] ) + +Here we are inserting three rows of five values. Notice that there is +a mix of types (strings, ints, floats) though we still only use +``%s``. And also note that we only included format strings for one +row. MySQLdb picks those out and duplicates them for each row. + +Using and extending +------------------- + +In general, it is probably wise to not directly interact with the DB +API except for small applicatons. Databases, even SQL databases, vary +widely in capabilities and may have non-standard features. The DB API +does a good job of providing a reasonably portable interface but some +methods are non-portable. Specifically, the parameters accepted by +``connect()`` are completely implementation-dependent. + +If you believe your application may need to run on several different +databases, the author recommends the following approach, based on +personal experience: Write a simplified API for your application which +implements the specific queries and operations your application needs +to perform. Implement this API as a base class which should be have +few database dependencies, and then derive a subclass from this which +implements the necessary dependencies. In this way, porting your +application to a new database should be a relatively simple matter of +creating a new subclass, assuming the new database is reasonably +standard. + +Because MySQLdb's Connection and Cursor objects are written in Python, +you can easily derive your own subclasses. There are several Cursor +classes in MySQLdb.cursors: + +BaseCursor + The base class for Cursor objects. This does not raise Warnings. + +CursorStoreResultMixIn + Causes the Cursor to use the ``mysql_store_result()`` function to + get the query result. The entire result set is stored on the + client side. + +CursorUseResultMixIn + Causes the cursor to use the ``mysql_use_result()`` function to + get the query result. The result set is stored on the server side + and is transferred row by row using fetch operations. + +CursorTupleRowsMixIn + Causes the cursor to return rows as a tuple of the column values. + +CursorDictRowsMixIn + + Causes the cursor to return rows as a dictionary, where the keys + are column names and the values are column values. Note that if + the column names are not unique, i.e., you are selecting from two + tables that share column names, some of them will be rewritten as + ``table.column``. This can be avoided by using the SQL ``AS`` + keyword. (This is yet-another reason not to use ``*`` in SQL + queries, particularly where ``JOIN`` is involved.) + +Cursor + The default cursor class. This class is composed of + ``CursorWarningMixIn``, ``CursorStoreResultMixIn``, + ``CursorTupleRowsMixIn,`` and ``BaseCursor``, i.e. it raises + ``Warning``, uses ``mysql_store_result()``, and returns rows as + tuples. + +DictCursor + Like ``Cursor`` except it returns rows as dictionaries. + +SSCursor + A "server-side" cursor. Like ``Cursor`` but uses + ``CursorUseResultMixIn``. Use only if you are dealing with + potentially large result sets. + +SSDictCursor + Like ``SSCursor`` except it returns rows as dictionaries. + + +Embedded Server +--------------- + +Instead of connecting to a stand-alone server over the network, +the embedded server support lets you run a full server right in +your Python code or application server. + +If you have built MySQLdb with embedded server support, there +are two additional functions you will need to make use of: + + server_init(args, groups) + Initialize embedded server. If this client is not linked against + the embedded server library, this function does nothing. + + args + sequence of command-line arguments + groups + sequence of groups to use in defaults files + + server_end() + Shut down embedded server. If not using an embedded server, this + does nothing. + +See the MySQL documentation for more information on the embedded +server. + + + +:Title: MySQLdb: a Python interface for MySQL +:Author: Andy Dustman +:Version: $Revision$ diff --git a/lib/mysql/metadata.cfg b/lib/mysql/metadata.cfg new file mode 100644 index 00000000..cece701f --- /dev/null +++ b/lib/mysql/metadata.cfg @@ -0,0 +1,58 @@ +[metadata] +version: 1.2.5 +version_info: (1,2,5,'final',1) +description: Python interface to MySQL +long_description: + ========================= + Python interface to MySQL + ========================= + \n + MySQLdb is an interface to the popular MySQL_ database server for + Python. The design goals are: + \n + - Compliance with Python database API version 2.0 [PEP-0249]_ + - Thread-safety + - Thread-friendliness (threads will not block each other) + \n + MySQL-3.23 through 5.5 and Python-2.4 through 2.7 are currently + supported. Python-3.0 will be supported in a future release. + PyPy is supported. + \n + MySQLdb is `Free Software`_. + \n + .. _MySQL: http://www.mysql.com/ + .. _`Free Software`: http://www.gnu.org/ + .. [PEP-0249] http://www.python.org/peps/pep-0249.html +author: Andy Dustman +author_email: farcepest@gmail.com +license: GPL +platforms: ALL +url: https://github.com/farcepest/MySQLdb1 +classifiers: + Development Status :: 5 - Production/Stable + Environment :: Other Environment + License :: OSI Approved :: GNU General Public License (GPL) + Operating System :: MacOS :: MacOS X + Operating System :: Microsoft :: Windows :: Windows NT/2000 + Operating System :: OS Independent + Operating System :: POSIX + Operating System :: POSIX :: Linux + Operating System :: Unix + Programming Language :: C + Programming Language :: Python + Topic :: Database + Topic :: Database :: Database Engines/Servers +py_modules: + _mysql_exceptions + MySQLdb.converters + MySQLdb.connections + MySQLdb.cursors + MySQLdb.release + MySQLdb.times + MySQLdb.constants.CR + MySQLdb.constants.FIELD_TYPE + MySQLdb.constants.ER + MySQLdb.constants.FLAG + MySQLdb.constants.REFRESH + MySQLdb.constants.CLIENT + diff --git a/lib/mysql/pymemcompat.h b/lib/mysql/pymemcompat.h new file mode 100644 index 00000000..e7c538c4 --- /dev/null +++ b/lib/mysql/pymemcompat.h @@ -0,0 +1,87 @@ + +/* The idea of this file is that you bundle it with your extension, + #include it, program to Python 2.3's memory API and have your + extension build with any version of Python from 1.5.2 through to + 2.3 (and hopefully beyond). */ + +#ifndef Py_PYMEMCOMPAT_H +#define Py_PYMEMCOMPAT_H + +#include "Python.h" + +/* There are three "families" of memory API: the "raw memory", "object + memory" and "object" families. (This is ignoring the matter of the + cycle collector, about which more is said below). + + Raw Memory: + + PyMem_Malloc, PyMem_Realloc, PyMem_Free + + Object Memory: + + PyObject_Malloc, PyObject_Realloc, PyObject_Free + + Object: + + PyObject_New, PyObject_NewVar, PyObject_Del + + The raw memory and object memory allocators both mimic the + malloc/realloc/free interface from ANSI C, but the object memory + allocator can (and, since 2.3, does by default) use a different + allocation strategy biased towards lots of lots of "small" + allocations. + + The object family is used for allocating Python objects, and the + initializers take care of some basic initialization (setting the + refcount to 1 and filling out the ob_type field) as well as having + a somewhat different interface. + + Do not mix the families! E.g. do not allocate memory with + PyMem_Malloc and free it with PyObject_Free. You may get away with + it quite a lot of the time, but there *are* scenarios where this + will break. You Have Been Warned. + + Also, in many versions of Python there are an insane amount of + memory interfaces to choose from. Use the ones described above. */ + +#if PY_VERSION_HEX < 0x01060000 +/* raw memory interface already present */ + +/* there is no object memory interface in 1.5.2 */ +#define PyObject_Malloc PyMem_Malloc +#define PyObject_Realloc PyMem_Realloc +#define PyObject_Free PyMem_Free + +/* the object interface is there, but the names have changed */ +#define PyObject_New PyObject_NEW +#define PyObject_NewVar PyObject_NEW_VAR +#define PyObject_Del PyMem_Free +#endif + +/* If your object is a container you probably want to support the + cycle collector, which was new in Python 2.0. + + Unfortunately, the interface to the collector that was present in + Python 2.0 and 2.1 proved to be tricky to use, and so changed in + 2.2 -- in a way that can't easily be papered over with macros. + + This file contains macros that let you program to the 2.2 GC API. + Your module will compile against any Python since version 1.5.2, + but the type will only participate in the GC in versions 2.2 and + up. Some work is still necessary on your part to only fill out the + tp_traverse and tp_clear fields when they exist and set tp_flags + appropriately. + + It is possible to support both the 2.0 and 2.2 GC APIs, but it's + not pretty and this comment block is too narrow to contain a + desciption of what's required... */ + +#if PY_VERSION_HEX < 0x020200B1 +#define PyObject_GC_New PyObject_New +#define PyObject_GC_NewVar PyObject_NewVar +#define PyObject_GC_Del PyObject_Del +#define PyObject_GC_Track(op) +#define PyObject_GC_UnTrack(op) +#endif + +#endif /* !Py_PYMEMCOMPAT_H */ diff --git a/lib/mysql/setup.cfg b/lib/mysql/setup.cfg new file mode 100644 index 00000000..1106a5ba --- /dev/null +++ b/lib/mysql/setup.cfg @@ -0,0 +1,18 @@ +[test] +test_suite = nose.collector + +[build_ext] + +[bdist_rpm] +doc_files = README MANIFEST doc/*.txt +vendor = MySQL-python SourceForge Project +packager = Andy Dustman +distribution-name = Red Stains Linux +requires = python +build-requires = python-devel mysql-devel zlib-devel openssl-devel + +[egg_info] +tag_build = +tag_date = 0 +tag_svn_revision = 0 + diff --git a/lib/mysql/setup.py b/lib/mysql/setup.py new file mode 100644 index 00000000..7e1c21b4 --- /dev/null +++ b/lib/mysql/setup.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python + +import os +import sys + +import distutils.errors +import setuptools + +if not hasattr(sys, "hexversion") or sys.hexversion < 0x02040000: + raise distutils.errors.DistutilsError("Python 2.4 or newer is required") + +if os.name == "posix": + from setup_posix import get_config +else: # assume windows + from setup_windows import get_config + +metadata, options = get_config() +metadata['ext_modules'] = [ + setuptools.Extension(sources=['_mysql.c'], **options)] +metadata['long_description'] = metadata['long_description'].replace(r'\n', '') +setuptools.setup(**metadata) diff --git a/lib/mysql/setup_common.py b/lib/mysql/setup_common.py new file mode 100644 index 00000000..03c39bb7 --- /dev/null +++ b/lib/mysql/setup_common.py @@ -0,0 +1,37 @@ +try: + # Python 2.x + from ConfigParser import SafeConfigParser +except ImportError: + # Python 3.x + from configparser import ConfigParser as SafeConfigParser + +def get_metadata_and_options(): + config = SafeConfigParser() + config.read(['metadata.cfg', 'site.cfg']) + + metadata = dict(config.items('metadata')) + options = dict(config.items('options')) + + metadata['py_modules'] = list(filter(None, metadata['py_modules'].split('\n'))) + metadata['classifiers'] = list(filter(None, metadata['classifiers'].split('\n'))) + + return metadata, options + +def enabled(options, option): + value = options[option] + s = value.lower() + if s in ('yes','true','1','y'): + return True + elif s in ('no', 'false', '0', 'n'): + return False + else: + raise ValueError("Unknown value %s for option %s" % (value, option)) + +def create_release_file(metadata): + rel = open("MySQLdb/release.py",'w') + rel.write(""" +__author__ = "%(author)s <%(author_email)s>" +version_info = %(version_info)s +__version__ = "%(version)s" +""" % metadata) + rel.close() diff --git a/lib/mysql/setup_common.pyc b/lib/mysql/setup_common.pyc new file mode 100644 index 00000000..79555bd4 Binary files /dev/null and b/lib/mysql/setup_common.pyc differ diff --git a/lib/mysql/setup_posix.py b/lib/mysql/setup_posix.py new file mode 100644 index 00000000..e6cb100f --- /dev/null +++ b/lib/mysql/setup_posix.py @@ -0,0 +1,103 @@ +import os, sys +from ConfigParser import SafeConfigParser + +# This dequote() business is required for some older versions +# of mysql_config + +def dequote(s): + if s[0] in "\"'" and s[0] == s[-1]: + s = s[1:-1] + return s + +def compiler_flag(f): + return "-%s" % f + +def mysql_config(what): + from os import popen + + f = popen("%s --%s" % (mysql_config.path, what)) + data = f.read().strip().split() + ret = f.close() + if ret: + if ret/256: + data = [] + if ret/256 > 1: + raise EnvironmentError("%s not found" % (mysql_config.path,)) + return data +mysql_config.path = "mysql_config" + +def get_config(): + from setup_common import get_metadata_and_options, enabled, create_release_file + + metadata, options = get_metadata_and_options() + + if 'mysql_config' in options: + mysql_config.path = options['mysql_config'] + + extra_objects = [] + static = enabled(options, 'static') + if enabled(options, 'embedded'): + libs = mysql_config("libmysqld-libs") + client = "mysqld" + elif enabled(options, 'threadsafe'): + libs = mysql_config("libs_r") + client = "mysqlclient_r" + if not libs: + libs = mysql_config("libs") + client = "mysqlclient" + else: + libs = mysql_config("libs") + client = "mysqlclient" + + library_dirs = [ dequote(i[2:]) for i in libs if i.startswith(compiler_flag("L")) ] + libraries = [ dequote(i[2:]) for i in libs if i.startswith(compiler_flag("l")) ] + + removable_compile_args = [ compiler_flag(f) for f in "ILl" ] + extra_compile_args = [ i.replace("%", "%%") for i in mysql_config("cflags") + if i[:2] not in removable_compile_args ] + + # Copy the arch flags for linking as well + extra_link_args = list() + for i in range(len(extra_compile_args)): + if extra_compile_args[i] == '-arch': + extra_link_args += ['-arch', extra_compile_args[i + 1]] + + include_dirs = [ dequote(i[2:]) + for i in mysql_config('include') + if i.startswith(compiler_flag('I')) ] + if not include_dirs: # fix for MySQL-3.23 + include_dirs = [ dequote(i[2:]) + for i in mysql_config('cflags') + if i.startswith(compiler_flag('I')) ] + + if static: + extra_objects.append(os.path.join(library_dirs[0],'lib%s.a' % client)) + if client in libraries: + libraries.remove(client) + + name = "MySQL-python" + if enabled(options, 'embedded'): + name = name + "-embedded" + metadata['name'] = name + + define_macros = [ + ('version_info', metadata['version_info']), + ('__version__', metadata['version']), + ] + create_release_file(metadata) + del metadata['version_info'] + ext_options = dict( + name = "_mysql", + library_dirs = library_dirs, + libraries = libraries, + extra_compile_args = extra_compile_args, + extra_link_args = extra_link_args, + include_dirs = include_dirs, + extra_objects = extra_objects, + define_macros = define_macros, + ) + return metadata, ext_options + +if __name__ == "__main__": + sys.stderr.write("""You shouldn't be running this directly; it is used by setup.py.""") + diff --git a/lib/mysql/setup_posix.pyc b/lib/mysql/setup_posix.pyc new file mode 100644 index 00000000..a9b913c7 Binary files /dev/null and b/lib/mysql/setup_posix.pyc differ diff --git a/lib/mysql/setup_windows.py b/lib/mysql/setup_windows.py new file mode 100644 index 00000000..ffe63971 --- /dev/null +++ b/lib/mysql/setup_windows.py @@ -0,0 +1,46 @@ +import os, sys + +def get_config(): + from setup_common import get_metadata_and_options, enabled, create_release_file + + metadata, options = get_metadata_and_options() + + connector = options["connector"] + + extra_objects = [] + + if enabled(options, 'embedded'): + client = "mysqld" + else: + client = "mysqlclient" + + library_dirs = [ os.path.join(connector, r'lib\opt') ] + libraries = [ 'kernel32', 'advapi32', 'wsock32', client ] + include_dirs = [ os.path.join(connector, r'include') ] + extra_compile_args = [ '/Zl' ] + + name = "MySQL-python" + if enabled(options, 'embedded'): + name = name + "-embedded" + metadata['name'] = name + + define_macros = [ + ('version_info', metadata['version_info']), + ('__version__', metadata['version']), + ] + create_release_file(metadata) + del metadata['version_info'] + ext_options = dict( + name = "_mysql", + library_dirs = library_dirs, + libraries = libraries, + extra_compile_args = extra_compile_args, + include_dirs = include_dirs, + extra_objects = extra_objects, + define_macros = define_macros, + ) + return metadata, ext_options + +if __name__ == "__main__": + sys.stderr.write("""You shouldn't be running this directly; it is used by setup.py.""") + diff --git a/lib/mysql/site.cfg b/lib/mysql/site.cfg new file mode 100644 index 00000000..369c87e4 --- /dev/null +++ b/lib/mysql/site.cfg @@ -0,0 +1,17 @@ +[options] +# embedded: link against the embedded server library +# threadsafe: use the threadsafe client +# static: link against a static library (probably required for embedded) + +embedded = False +threadsafe = True +static = False + +# The path to mysql_config. +# Only use this if mysql_config is not on your PATH, or you have some weird +# setup that requires it. +#mysql_config = /usr/local/bin/mysql_config + +# http://stackoverflow.com/questions/1972259/mysql-python-install-problem-using-virtualenv-windows-pip +# Windows connector libs for MySQL. You need a 32-bit connector for your 32-bit Python build. +connector = C:\Program Files (x86)\MySQL\MySQL Connector C 6.0.2 diff --git a/lib/mysql/tests/capabilities.py b/lib/mysql/tests/capabilities.py new file mode 100644 index 00000000..076361cb --- /dev/null +++ b/lib/mysql/tests/capabilities.py @@ -0,0 +1,281 @@ +#!/usr/bin/env python -O +""" Script to test database capabilities and the DB-API interface + for functionality and memory leaks. + + Adapted from a script by M-A Lemburg. + +""" +from time import time +import array +import unittest +from configdb import connection_factory + + +class DatabaseTest(unittest.TestCase): + + db_module = None + connect_args = () + connect_kwargs = dict() + create_table_extra = '' + rows = 10 + debug = False + + def setUp(self): + import gc + db = connection_factory(**self.connect_kwargs) + self.connection = db + self.cursor = db.cursor() + # TODO: this needs to be re-evaluated for Python 3 + self.BLOBText = ''.join([chr(i) for i in range(256)] * 100); + self.BLOBUText = u''.join([unichr(i) for i in range(16384)]) + self.BLOBBinary = self.db_module.Binary(''.join([chr(i) for i in range(256)] * 16)) + + leak_test = True + + def tearDown(self): + if self.leak_test: + import gc + del self.cursor + orphans = gc.collect() + self.failIf(orphans, "%d orphaned objects found after deleting cursor" % orphans) + + del self.connection + orphans = gc.collect() + self.failIf(orphans, "%d orphaned objects found after deleting connection" % orphans) + + def table_exists(self, name): + try: + self.cursor.execute('select * from %s where 1=0' % name) + except: + return False + else: + return True + + def quote_identifier(self, ident): + return '"%s"' % ident + + def new_table_name(self): + i = id(self.cursor) + while True: + name = self.quote_identifier('tb%08x' % i) + if not self.table_exists(name): + return name + i = i + 1 + + def create_table(self, columndefs): + + """ Create a table using a list of column definitions given in + columndefs. + + generator must be a function taking arguments (row_number, + col_number) returning a suitable data object for insertion + into the table. + + """ + self.table = self.new_table_name() + self.cursor.execute('CREATE TABLE %s (%s) %s' % + (self.table, + ',\n'.join(columndefs), + self.create_table_extra)) + + def check_data_integrity(self, columndefs, generator): + # insert + self.create_table(columndefs) + insert_statement = ('INSERT INTO %s VALUES (%s)' % + (self.table, + ','.join(['%s'] * len(columndefs)))) + data = [ [ generator(i,j) for j in range(len(columndefs)) ] + for i in range(self.rows) ] + self.cursor.executemany(insert_statement, data) + self.connection.commit() + # verify + self.cursor.execute('select * from %s' % self.table) + l = self.cursor.fetchall() + self.assertEquals(len(l), self.rows) + try: + for i in range(self.rows): + for j in range(len(columndefs)): + self.assertEquals(l[i][j], generator(i,j)) + finally: + if not self.debug: + self.cursor.execute('drop table %s' % (self.table)) + + def test_transactions(self): + columndefs = ( 'col1 INT', 'col2 VARCHAR(255)') + def generator(row, col): + if col == 0: return row + else: return ('%i' % (row%10))*255 + self.create_table(columndefs) + insert_statement = ('INSERT INTO %s VALUES (%s)' % + (self.table, + ','.join(['%s'] * len(columndefs)))) + data = [ [ generator(i,j) for j in range(len(columndefs)) ] + for i in range(self.rows) ] + self.cursor.executemany(insert_statement, data) + # verify + self.connection.commit() + self.cursor.execute('select * from %s' % self.table) + l = self.cursor.fetchall() + self.assertEquals(len(l), self.rows) + for i in range(self.rows): + for j in range(len(columndefs)): + self.assertEquals(l[i][j], generator(i,j)) + delete_statement = 'delete from %s where col1=%%s' % self.table + self.cursor.execute(delete_statement, (0,)) + self.cursor.execute('select col1 from %s where col1=%s' % \ + (self.table, 0)) + l = self.cursor.fetchall() + self.assertFalse(l, "DELETE didn't work") + self.connection.rollback() + self.cursor.execute('select col1 from %s where col1=%s' % \ + (self.table, 0)) + l = self.cursor.fetchall() + self.assertTrue(len(l) == 1, "ROLLBACK didn't work") + self.cursor.execute('drop table %s' % (self.table)) + + def test_truncation(self): + columndefs = ( 'col1 INT', 'col2 VARCHAR(255)') + def generator(row, col): + if col == 0: return row + else: return ('%i' % (row%10))*((255-self.rows/2)+row) + self.create_table(columndefs) + insert_statement = ('INSERT INTO %s VALUES (%s)' % + (self.table, + ','.join(['%s'] * len(columndefs)))) + + try: + self.cursor.execute(insert_statement, (0, '0'*256)) + except self.connection.DataError: + pass + else: + self.fail("Over-long column did not generate warnings/exception with single insert") + + self.connection.rollback() + + try: + for i in range(self.rows): + data = [] + for j in range(len(columndefs)): + data.append(generator(i,j)) + self.cursor.execute(insert_statement,tuple(data)) + except self.connection.DataError: + pass + else: + self.fail("Over-long columns did not generate warnings/exception with execute()") + + self.connection.rollback() + + try: + data = [ [ generator(i,j) for j in range(len(columndefs)) ] + for i in range(self.rows) ] + self.cursor.executemany(insert_statement, data) + except self.connection.DataError: + pass + else: + self.fail("Over-long columns did not generate warnings/exception with executemany()") + + self.connection.rollback() + self.cursor.execute('drop table %s' % (self.table)) + + def test_CHAR(self): + # Character data + def generator(row,col): + return ('%i' % ((row+col) % 10)) * 255 + self.check_data_integrity( + ('col1 char(255)','col2 char(255)'), + generator) + + def test_INT(self): + # Number data + def generator(row,col): + return row*row + self.check_data_integrity( + ('col1 INT',), + generator) + + def test_DECIMAL(self): + # DECIMAL + def generator(row,col): + from decimal import Decimal + return Decimal("%d.%02d" % (row, col)) + self.check_data_integrity( + ('col1 DECIMAL(5,2)',), + generator) + + def test_DATE(self): + ticks = time() + def generator(row,col): + return self.db_module.DateFromTicks(ticks+row*86400-col*1313) + self.check_data_integrity( + ('col1 DATE',), + generator) + + def test_TIME(self): + ticks = time() + def generator(row,col): + return self.db_module.TimeFromTicks(ticks+row*86400-col*1313) + self.check_data_integrity( + ('col1 TIME',), + generator) + + def test_DATETIME(self): + ticks = time() + def generator(row,col): + return self.db_module.TimestampFromTicks(ticks+row*86400-col*1313) + self.check_data_integrity( + ('col1 DATETIME',), + generator) + + def test_TIMESTAMP(self): + ticks = time() + def generator(row,col): + return self.db_module.TimestampFromTicks(ticks+row*86400-col*1313) + self.check_data_integrity( + ('col1 TIMESTAMP',), + generator) + + def test_fractional_TIMESTAMP(self): + ticks = time() + def generator(row,col): + return self.db_module.TimestampFromTicks(ticks+row*86400-col*1313+row*0.7*col/3.0) + self.check_data_integrity( + ('col1 TIMESTAMP',), + generator) + + def test_LONG(self): + def generator(row,col): + if col == 0: + return row + else: + return self.BLOBUText # 'BLOB Text ' * 1024 + self.check_data_integrity( + ('col1 INT','col2 LONG'), + generator) + + def test_TEXT(self): + def generator(row,col): + return self.BLOBUText # 'BLOB Text ' * 1024 + self.check_data_integrity( + ('col2 TEXT',), + generator) + + def test_LONG_BYTE(self): + def generator(row,col): + if col == 0: + return row + else: + return self.BLOBBinary # 'BLOB\000Binary ' * 1024 + self.check_data_integrity( + ('col1 INT','col2 LONG BYTE'), + generator) + + def test_BLOB(self): + def generator(row,col): + if col == 0: + return row + else: + return self.BLOBBinary # 'BLOB\000Binary ' * 1024 + self.check_data_integrity( + ('col1 INT','col2 BLOB'), + generator) + diff --git a/lib/mysql/tests/configdb.py b/lib/mysql/tests/configdb.py new file mode 100644 index 00000000..cd6d43da --- /dev/null +++ b/lib/mysql/tests/configdb.py @@ -0,0 +1,25 @@ +"""Configure database connection for tests.""" + +from os import environ, path + +tests_path = path.dirname(__file__) +conf_file = environ.get('TESTDB', 'default.cnf') +conf_path = path.join(tests_path, conf_file) +connect_kwargs = dict( + read_default_file = conf_path, + read_default_group = "MySQLdb-tests", +) + +def connection_kwargs(kwargs): + db_kwargs = connect_kwargs.copy() + db_kwargs.update(kwargs) + return db_kwargs + +def connection_factory(**kwargs): + import MySQLdb + db_kwargs = connection_kwargs(kwargs) + db = MySQLdb.connect(**db_kwargs) + return db + + + diff --git a/lib/mysql/tests/dbapi20.py b/lib/mysql/tests/dbapi20.py new file mode 100644 index 00000000..ad292ae7 --- /dev/null +++ b/lib/mysql/tests/dbapi20.py @@ -0,0 +1,853 @@ +#!/usr/bin/env python +''' Python DB API 2.0 driver compliance unit test suite. + + This software is Public Domain and may be used without restrictions. + + "Now we have booze and barflies entering the discussion, plus rumours of + DBAs on drugs... and I won't tell you what flashes through my mind each + time I read the subject line with 'Anal Compliance' in it. All around + this is turning out to be a thoroughly unwholesome unit test." + + -- Ian Bicking +''' + +__rcs_id__ = '$Id$' +__version__ = '$Revision$'[11:-2] +__author__ = 'Stuart Bishop ' + +import unittest +import time + +# $Log$ +# Revision 1.1.2.1 2006/02/25 03:44:32 adustman +# Generic DB-API unit test module +# +# Revision 1.10 2003/10/09 03:14:14 zenzen +# Add test for DB API 2.0 optional extension, where database exceptions +# are exposed as attributes on the Connection object. +# +# Revision 1.9 2003/08/13 01:16:36 zenzen +# Minor tweak from Stefan Fleiter +# +# Revision 1.8 2003/04/10 00:13:25 zenzen +# Changes, as per suggestions by M.-A. Lemburg +# - Add a table prefix, to ensure namespace collisions can always be avoided +# +# Revision 1.7 2003/02/26 23:33:37 zenzen +# Break out DDL into helper functions, as per request by David Rushby +# +# Revision 1.6 2003/02/21 03:04:33 zenzen +# Stuff from Henrik Ekelund: +# added test_None +# added test_nextset & hooks +# +# Revision 1.5 2003/02/17 22:08:43 zenzen +# Implement suggestions and code from Henrik Eklund - test that cursor.arraysize +# defaults to 1 & generic cursor.callproc test added +# +# Revision 1.4 2003/02/15 00:16:33 zenzen +# Changes, as per suggestions and bug reports by M.-A. Lemburg, +# Matthew T. Kromer, Federico Di Gregorio and Daniel Dittmar +# - Class renamed +# - Now a subclass of TestCase, to avoid requiring the driver stub +# to use multiple inheritance +# - Reversed the polarity of buggy test in test_description +# - Test exception heirarchy correctly +# - self.populate is now self._populate(), so if a driver stub +# overrides self.ddl1 this change propogates +# - VARCHAR columns now have a width, which will hopefully make the +# DDL even more portible (this will be reversed if it causes more problems) +# - cursor.rowcount being checked after various execute and fetchXXX methods +# - Check for fetchall and fetchmany returning empty lists after results +# are exhausted (already checking for empty lists if select retrieved +# nothing +# - Fix bugs in test_setoutputsize_basic and test_setinputsizes +# + +class DatabaseAPI20Test(unittest.TestCase): + ''' Test a database self.driver for DB API 2.0 compatibility. + This implementation tests Gadfly, but the TestCase + is structured so that other self.drivers can subclass this + test case to ensure compiliance with the DB-API. It is + expected that this TestCase may be expanded in the future + if ambiguities or edge conditions are discovered. + + The 'Optional Extensions' are not yet being tested. + + self.drivers should subclass this test, overriding setUp, tearDown, + self.driver, connect_args and connect_kw_args. Class specification + should be as follows: + + import dbapi20 + class mytest(dbapi20.DatabaseAPI20Test): + [...] + + Don't 'import DatabaseAPI20Test from dbapi20', or you will + confuse the unit tester - just 'import dbapi20'. + ''' + + # The self.driver module. This should be the module where the 'connect' + # method is to be found + driver = None + connect_args = () # List of arguments to pass to connect + connect_kw_args = {} # Keyword arguments for connect + table_prefix = 'dbapi20test_' # If you need to specify a prefix for tables + + ddl1 = 'create table %sbooze (name varchar(20))' % table_prefix + ddl2 = 'create table %sbarflys (name varchar(20))' % table_prefix + xddl1 = 'drop table %sbooze' % table_prefix + xddl2 = 'drop table %sbarflys' % table_prefix + + lowerfunc = 'lower' # Name of stored procedure to convert string->lowercase + + # Some drivers may need to override these helpers, for example adding + # a 'commit' after the execute. + def executeDDL1(self,cursor): + cursor.execute(self.ddl1) + + def executeDDL2(self,cursor): + cursor.execute(self.ddl2) + + def setUp(self): + ''' self.drivers should override this method to perform required setup + if any is necessary, such as creating the database. + ''' + pass + + def tearDown(self): + ''' self.drivers should override this method to perform required cleanup + if any is necessary, such as deleting the test database. + The default drops the tables that may be created. + ''' + con = self._connect() + try: + cur = con.cursor() + for ddl in (self.xddl1,self.xddl2): + try: + cur.execute(ddl) + con.commit() + except self.driver.Error: + # Assume table didn't exist. Other tests will check if + # execute is busted. + pass + finally: + con.close() + + def _connect(self): + try: + return self.driver.connect( + *self.connect_args,**self.connect_kw_args + ) + except AttributeError: + self.fail("No connect method found in self.driver module") + + def test_connect(self): + con = self._connect() + con.close() + + def test_apilevel(self): + try: + # Must exist + apilevel = self.driver.apilevel + # Must equal 2.0 + self.assertEqual(apilevel,'2.0') + except AttributeError: + self.fail("Driver doesn't define apilevel") + + def test_threadsafety(self): + try: + # Must exist + threadsafety = self.driver.threadsafety + # Must be a valid value + self.assertTrue(threadsafety in (0,1,2,3)) + except AttributeError: + self.fail("Driver doesn't define threadsafety") + + def test_paramstyle(self): + try: + # Must exist + paramstyle = self.driver.paramstyle + # Must be a valid value + self.assertTrue(paramstyle in ( + 'qmark','numeric','named','format','pyformat' + )) + except AttributeError: + self.fail("Driver doesn't define paramstyle") + + def test_Exceptions(self): + # Make sure required exceptions exist, and are in the + # defined heirarchy. + self.assertTrue(issubclass(self.driver.Warning,StandardError)) + self.assertTrue(issubclass(self.driver.Error,StandardError)) + self.assertTrue( + issubclass(self.driver.InterfaceError,self.driver.Error) + ) + self.assertTrue( + issubclass(self.driver.DatabaseError,self.driver.Error) + ) + self.assertTrue( + issubclass(self.driver.OperationalError,self.driver.Error) + ) + self.assertTrue( + issubclass(self.driver.IntegrityError,self.driver.Error) + ) + self.assertTrue( + issubclass(self.driver.InternalError,self.driver.Error) + ) + self.assertTrue( + issubclass(self.driver.ProgrammingError,self.driver.Error) + ) + self.assertTrue( + issubclass(self.driver.NotSupportedError,self.driver.Error) + ) + + def test_ExceptionsAsConnectionAttributes(self): + # OPTIONAL EXTENSION + # Test for the optional DB API 2.0 extension, where the exceptions + # are exposed as attributes on the Connection object + # I figure this optional extension will be implemented by any + # driver author who is using this test suite, so it is enabled + # by default. + con = self._connect() + drv = self.driver + self.assertTrue(con.Warning is drv.Warning) + self.assertTrue(con.Error is drv.Error) + self.assertTrue(con.InterfaceError is drv.InterfaceError) + self.assertTrue(con.DatabaseError is drv.DatabaseError) + self.assertTrue(con.OperationalError is drv.OperationalError) + self.assertTrue(con.IntegrityError is drv.IntegrityError) + self.assertTrue(con.InternalError is drv.InternalError) + self.assertTrue(con.ProgrammingError is drv.ProgrammingError) + self.assertTrue(con.NotSupportedError is drv.NotSupportedError) + + + def test_commit(self): + con = self._connect() + try: + # Commit must work, even if it doesn't do anything + con.commit() + finally: + con.close() + + def test_rollback(self): + con = self._connect() + # If rollback is defined, it should either work or throw + # the documented exception + if hasattr(con,'rollback'): + try: + con.rollback() + except self.driver.NotSupportedError: + pass + + def test_cursor(self): + con = self._connect() + try: + cur = con.cursor() + finally: + con.close() + + def test_cursor_isolation(self): + con = self._connect() + try: + # Make sure cursors created from the same connection have + # the documented transaction isolation level + cur1 = con.cursor() + cur2 = con.cursor() + self.executeDDL1(cur1) + cur1.execute("insert into %sbooze values ('Victoria Bitter')" % ( + self.table_prefix + )) + cur2.execute("select name from %sbooze" % self.table_prefix) + booze = cur2.fetchall() + self.assertEqual(len(booze),1) + self.assertEqual(len(booze[0]),1) + self.assertEqual(booze[0][0],'Victoria Bitter') + finally: + con.close() + + def test_description(self): + con = self._connect() + try: + cur = con.cursor() + self.executeDDL1(cur) + self.assertEqual(cur.description,None, + 'cursor.description should be none after executing a ' + 'statement that can return no rows (such as DDL)' + ) + cur.execute('select name from %sbooze' % self.table_prefix) + self.assertEqual(len(cur.description),1, + 'cursor.description describes too many columns' + ) + self.assertEqual(len(cur.description[0]),7, + 'cursor.description[x] tuples must have 7 elements' + ) + self.assertEqual(cur.description[0][0].lower(),'name', + 'cursor.description[x][0] must return column name' + ) + self.assertEqual(cur.description[0][1],self.driver.STRING, + 'cursor.description[x][1] must return column type. Got %r' + % cur.description[0][1] + ) + + # Make sure self.description gets reset + self.executeDDL2(cur) + self.assertEqual(cur.description,None, + 'cursor.description not being set to None when executing ' + 'no-result statements (eg. DDL)' + ) + finally: + con.close() + + def test_rowcount(self): + con = self._connect() + try: + cur = con.cursor() + self.executeDDL1(cur) + self.assertEqual(cur.rowcount,-1, + 'cursor.rowcount should be -1 after executing no-result ' + 'statements' + ) + cur.execute("insert into %sbooze values ('Victoria Bitter')" % ( + self.table_prefix + )) + self.assertTrue(cur.rowcount in (-1,1), + 'cursor.rowcount should == number or rows inserted, or ' + 'set to -1 after executing an insert statement' + ) + cur.execute("select name from %sbooze" % self.table_prefix) + self.assertTrue(cur.rowcount in (-1,1), + 'cursor.rowcount should == number of rows returned, or ' + 'set to -1 after executing a select statement' + ) + self.executeDDL2(cur) + self.assertEqual(cur.rowcount,-1, + 'cursor.rowcount not being reset to -1 after executing ' + 'no-result statements' + ) + finally: + con.close() + + lower_func = 'lower' + def test_callproc(self): + con = self._connect() + try: + cur = con.cursor() + if self.lower_func and hasattr(cur,'callproc'): + r = cur.callproc(self.lower_func,('FOO',)) + self.assertEqual(len(r),1) + self.assertEqual(r[0],'FOO') + r = cur.fetchall() + self.assertEqual(len(r),1,'callproc produced no result set') + self.assertEqual(len(r[0]),1, + 'callproc produced invalid result set' + ) + self.assertEqual(r[0][0],'foo', + 'callproc produced invalid results' + ) + finally: + con.close() + + def test_close(self): + con = self._connect() + try: + cur = con.cursor() + finally: + con.close() + + # cursor.execute should raise an Error if called after connection + # closed + self.assertRaises(self.driver.Error,self.executeDDL1,cur) + + # connection.commit should raise an Error if called after connection' + # closed.' + self.assertRaises(self.driver.Error,con.commit) + + # connection.close should raise an Error if called more than once + self.assertRaises(self.driver.Error,con.close) + + def test_execute(self): + con = self._connect() + try: + cur = con.cursor() + self._paraminsert(cur) + finally: + con.close() + + def _paraminsert(self,cur): + self.executeDDL1(cur) + cur.execute("insert into %sbooze values ('Victoria Bitter')" % ( + self.table_prefix + )) + self.assertTrue(cur.rowcount in (-1,1)) + + if self.driver.paramstyle == 'qmark': + cur.execute( + 'insert into %sbooze values (?)' % self.table_prefix, + ("Cooper's",) + ) + elif self.driver.paramstyle == 'numeric': + cur.execute( + 'insert into %sbooze values (:1)' % self.table_prefix, + ("Cooper's",) + ) + elif self.driver.paramstyle == 'named': + cur.execute( + 'insert into %sbooze values (:beer)' % self.table_prefix, + {'beer':"Cooper's"} + ) + elif self.driver.paramstyle == 'format': + cur.execute( + 'insert into %sbooze values (%%s)' % self.table_prefix, + ("Cooper's",) + ) + elif self.driver.paramstyle == 'pyformat': + cur.execute( + 'insert into %sbooze values (%%(beer)s)' % self.table_prefix, + {'beer':"Cooper's"} + ) + else: + self.fail('Invalid paramstyle') + self.assertTrue(cur.rowcount in (-1,1)) + + cur.execute('select name from %sbooze' % self.table_prefix) + res = cur.fetchall() + self.assertEqual(len(res),2,'cursor.fetchall returned too few rows') + beers = [res[0][0],res[1][0]] + beers.sort() + self.assertEqual(beers[0],"Cooper's", + 'cursor.fetchall retrieved incorrect data, or data inserted ' + 'incorrectly' + ) + self.assertEqual(beers[1],"Victoria Bitter", + 'cursor.fetchall retrieved incorrect data, or data inserted ' + 'incorrectly' + ) + + def test_executemany(self): + con = self._connect() + try: + cur = con.cursor() + self.executeDDL1(cur) + largs = [ ("Cooper's",) , ("Boag's",) ] + margs = [ {'beer': "Cooper's"}, {'beer': "Boag's"} ] + if self.driver.paramstyle == 'qmark': + cur.executemany( + 'insert into %sbooze values (?)' % self.table_prefix, + largs + ) + elif self.driver.paramstyle == 'numeric': + cur.executemany( + 'insert into %sbooze values (:1)' % self.table_prefix, + largs + ) + elif self.driver.paramstyle == 'named': + cur.executemany( + 'insert into %sbooze values (:beer)' % self.table_prefix, + margs + ) + elif self.driver.paramstyle == 'format': + cur.executemany( + 'insert into %sbooze values (%%s)' % self.table_prefix, + largs + ) + elif self.driver.paramstyle == 'pyformat': + cur.executemany( + 'insert into %sbooze values (%%(beer)s)' % ( + self.table_prefix + ), + margs + ) + else: + self.fail('Unknown paramstyle') + self.assertTrue(cur.rowcount in (-1,2), + 'insert using cursor.executemany set cursor.rowcount to ' + 'incorrect value %r' % cur.rowcount + ) + cur.execute('select name from %sbooze' % self.table_prefix) + res = cur.fetchall() + self.assertEqual(len(res),2, + 'cursor.fetchall retrieved incorrect number of rows' + ) + beers = [res[0][0],res[1][0]] + beers.sort() + self.assertEqual(beers[0],"Boag's",'incorrect data retrieved') + self.assertEqual(beers[1],"Cooper's",'incorrect data retrieved') + finally: + con.close() + + def test_fetchone(self): + con = self._connect() + try: + cur = con.cursor() + + # cursor.fetchone should raise an Error if called before + # executing a select-type query + self.assertRaises(self.driver.Error,cur.fetchone) + + # cursor.fetchone should raise an Error if called after + # executing a query that cannnot return rows + self.executeDDL1(cur) + self.assertRaises(self.driver.Error,cur.fetchone) + + cur.execute('select name from %sbooze' % self.table_prefix) + self.assertEqual(cur.fetchone(),None, + 'cursor.fetchone should return None if a query retrieves ' + 'no rows' + ) + self.assertTrue(cur.rowcount in (-1,0)) + + # cursor.fetchone should raise an Error if called after + # executing a query that cannnot return rows + cur.execute("insert into %sbooze values ('Victoria Bitter')" % ( + self.table_prefix + )) + self.assertRaises(self.driver.Error,cur.fetchone) + + cur.execute('select name from %sbooze' % self.table_prefix) + r = cur.fetchone() + self.assertEqual(len(r),1, + 'cursor.fetchone should have retrieved a single row' + ) + self.assertEqual(r[0],'Victoria Bitter', + 'cursor.fetchone retrieved incorrect data' + ) + self.assertEqual(cur.fetchone(),None, + 'cursor.fetchone should return None if no more rows available' + ) + self.assertTrue(cur.rowcount in (-1,1)) + finally: + con.close() + + samples = [ + 'Carlton Cold', + 'Carlton Draft', + 'Mountain Goat', + 'Redback', + 'Victoria Bitter', + 'XXXX' + ] + + def _populate(self): + ''' Return a list of sql commands to setup the DB for the fetch + tests. + ''' + populate = [ + "insert into %sbooze values ('%s')" % (self.table_prefix,s) + for s in self.samples + ] + return populate + + def test_fetchmany(self): + con = self._connect() + try: + cur = con.cursor() + + # cursor.fetchmany should raise an Error if called without + #issuing a query + self.assertRaises(self.driver.Error,cur.fetchmany,4) + + self.executeDDL1(cur) + for sql in self._populate(): + cur.execute(sql) + + cur.execute('select name from %sbooze' % self.table_prefix) + r = cur.fetchmany() + self.assertEqual(len(r),1, + 'cursor.fetchmany retrieved incorrect number of rows, ' + 'default of arraysize is one.' + ) + cur.arraysize=10 + r = cur.fetchmany(3) # Should get 3 rows + self.assertEqual(len(r),3, + 'cursor.fetchmany retrieved incorrect number of rows' + ) + r = cur.fetchmany(4) # Should get 2 more + self.assertEqual(len(r),2, + 'cursor.fetchmany retrieved incorrect number of rows' + ) + r = cur.fetchmany(4) # Should be an empty sequence + self.assertEqual(len(r),0, + 'cursor.fetchmany should return an empty sequence after ' + 'results are exhausted' + ) + self.assertTrue(cur.rowcount in (-1,6)) + + # Same as above, using cursor.arraysize + cur.arraysize=4 + cur.execute('select name from %sbooze' % self.table_prefix) + r = cur.fetchmany() # Should get 4 rows + self.assertEqual(len(r),4, + 'cursor.arraysize not being honoured by fetchmany' + ) + r = cur.fetchmany() # Should get 2 more + self.assertEqual(len(r),2) + r = cur.fetchmany() # Should be an empty sequence + self.assertEqual(len(r),0) + self.assertTrue(cur.rowcount in (-1,6)) + + cur.arraysize=6 + cur.execute('select name from %sbooze' % self.table_prefix) + rows = cur.fetchmany() # Should get all rows + self.assertTrue(cur.rowcount in (-1,6)) + self.assertEqual(len(rows),6) + self.assertEqual(len(rows),6) + rows = [r[0] for r in rows] + rows.sort() + + # Make sure we get the right data back out + for i in range(0,6): + self.assertEqual(rows[i],self.samples[i], + 'incorrect data retrieved by cursor.fetchmany' + ) + + rows = cur.fetchmany() # Should return an empty list + self.assertEqual(len(rows),0, + 'cursor.fetchmany should return an empty sequence if ' + 'called after the whole result set has been fetched' + ) + self.assertTrue(cur.rowcount in (-1,6)) + + self.executeDDL2(cur) + cur.execute('select name from %sbarflys' % self.table_prefix) + r = cur.fetchmany() # Should get empty sequence + self.assertEqual(len(r),0, + 'cursor.fetchmany should return an empty sequence if ' + 'query retrieved no rows' + ) + self.assertTrue(cur.rowcount in (-1,0)) + + finally: + con.close() + + def test_fetchall(self): + con = self._connect() + try: + cur = con.cursor() + # cursor.fetchall should raise an Error if called + # without executing a query that may return rows (such + # as a select) + self.assertRaises(self.driver.Error, cur.fetchall) + + self.executeDDL1(cur) + for sql in self._populate(): + cur.execute(sql) + + # cursor.fetchall should raise an Error if called + # after executing a a statement that cannot return rows + self.assertRaises(self.driver.Error,cur.fetchall) + + cur.execute('select name from %sbooze' % self.table_prefix) + rows = cur.fetchall() + self.assertTrue(cur.rowcount in (-1,len(self.samples))) + self.assertEqual(len(rows),len(self.samples), + 'cursor.fetchall did not retrieve all rows' + ) + rows = [r[0] for r in rows] + rows.sort() + for i in range(0,len(self.samples)): + self.assertEqual(rows[i],self.samples[i], + 'cursor.fetchall retrieved incorrect rows' + ) + rows = cur.fetchall() + self.assertEqual( + len(rows),0, + 'cursor.fetchall should return an empty list if called ' + 'after the whole result set has been fetched' + ) + self.assertTrue(cur.rowcount in (-1,len(self.samples))) + + self.executeDDL2(cur) + cur.execute('select name from %sbarflys' % self.table_prefix) + rows = cur.fetchall() + self.assertTrue(cur.rowcount in (-1,0)) + self.assertEqual(len(rows),0, + 'cursor.fetchall should return an empty list if ' + 'a select query returns no rows' + ) + + finally: + con.close() + + def test_mixedfetch(self): + con = self._connect() + try: + cur = con.cursor() + self.executeDDL1(cur) + for sql in self._populate(): + cur.execute(sql) + + cur.execute('select name from %sbooze' % self.table_prefix) + rows1 = cur.fetchone() + rows23 = cur.fetchmany(2) + rows4 = cur.fetchone() + rows56 = cur.fetchall() + self.assertTrue(cur.rowcount in (-1,6)) + self.assertEqual(len(rows23),2, + 'fetchmany returned incorrect number of rows' + ) + self.assertEqual(len(rows56),2, + 'fetchall returned incorrect number of rows' + ) + + rows = [rows1[0]] + rows.extend([rows23[0][0],rows23[1][0]]) + rows.append(rows4[0]) + rows.extend([rows56[0][0],rows56[1][0]]) + rows.sort() + for i in range(0,len(self.samples)): + self.assertEqual(rows[i],self.samples[i], + 'incorrect data retrieved or inserted' + ) + finally: + con.close() + + def help_nextset_setUp(self,cur): + ''' Should create a procedure called deleteme + that returns two result sets, first the + number of rows in booze then "name from booze" + ''' + raise NotImplementedError('Helper not implemented') + #sql=""" + # create procedure deleteme as + # begin + # select count(*) from booze + # select name from booze + # end + #""" + #cur.execute(sql) + + def help_nextset_tearDown(self,cur): + 'If cleaning up is needed after nextSetTest' + raise NotImplementedError('Helper not implemented') + #cur.execute("drop procedure deleteme") + + def test_nextset(self): + con = self._connect() + try: + cur = con.cursor() + if not hasattr(cur,'nextset'): + return + + try: + self.executeDDL1(cur) + sql=self._populate() + for sql in self._populate(): + cur.execute(sql) + + self.help_nextset_setUp(cur) + + cur.callproc('deleteme') + numberofrows=cur.fetchone() + assert numberofrows[0]== len(self.samples) + assert cur.nextset() + names=cur.fetchall() + assert len(names) == len(self.samples) + s=cur.nextset() + assert s == None,'No more return sets, should return None' + finally: + self.help_nextset_tearDown(cur) + + finally: + con.close() + + def test_nextset(self): + raise NotImplementedError('Drivers need to override this test') + + def test_arraysize(self): + # Not much here - rest of the tests for this are in test_fetchmany + con = self._connect() + try: + cur = con.cursor() + self.assertTrue(hasattr(cur,'arraysize'), + 'cursor.arraysize must be defined' + ) + finally: + con.close() + + def test_setinputsizes(self): + con = self._connect() + try: + cur = con.cursor() + cur.setinputsizes( (25,) ) + self._paraminsert(cur) # Make sure cursor still works + finally: + con.close() + + def test_setoutputsize_basic(self): + # Basic test is to make sure setoutputsize doesn't blow up + con = self._connect() + try: + cur = con.cursor() + cur.setoutputsize(1000) + cur.setoutputsize(2000,0) + self._paraminsert(cur) # Make sure the cursor still works + finally: + con.close() + + def test_setoutputsize(self): + # Real test for setoutputsize is driver dependant + raise NotImplementedError('Driver need to override this test') + + def test_None(self): + con = self._connect() + try: + cur = con.cursor() + self.executeDDL1(cur) + cur.execute('insert into %sbooze values (NULL)' % self.table_prefix) + cur.execute('select name from %sbooze' % self.table_prefix) + r = cur.fetchall() + self.assertEqual(len(r),1) + self.assertEqual(len(r[0]),1) + self.assertEqual(r[0][0],None,'NULL value not returned as None') + finally: + con.close() + + def test_Date(self): + d1 = self.driver.Date(2002,12,25) + d2 = self.driver.DateFromTicks(time.mktime((2002,12,25,0,0,0,0,0,0))) + # Can we assume this? API doesn't specify, but it seems implied + # self.assertEqual(str(d1),str(d2)) + + def test_Time(self): + t1 = self.driver.Time(13,45,30) + t2 = self.driver.TimeFromTicks(time.mktime((2001,1,1,13,45,30,0,0,0))) + # Can we assume this? API doesn't specify, but it seems implied + # self.assertEqual(str(t1),str(t2)) + + def test_Timestamp(self): + t1 = self.driver.Timestamp(2002,12,25,13,45,30) + t2 = self.driver.TimestampFromTicks( + time.mktime((2002,12,25,13,45,30,0,0,0)) + ) + # Can we assume this? API doesn't specify, but it seems implied + # self.assertEqual(str(t1),str(t2)) + + def test_Binary(self): + b = self.driver.Binary('Something') + b = self.driver.Binary('') + + def test_STRING(self): + self.assertTrue(hasattr(self.driver,'STRING'), + 'module.STRING must be defined' + ) + + def test_BINARY(self): + self.assertTrue(hasattr(self.driver,'BINARY'), + 'module.BINARY must be defined.' + ) + + def test_NUMBER(self): + self.assertTrue(hasattr(self.driver,'NUMBER'), + 'module.NUMBER must be defined.' + ) + + def test_DATETIME(self): + self.assertTrue(hasattr(self.driver,'DATETIME'), + 'module.DATETIME must be defined.' + ) + + def test_ROWID(self): + self.assertTrue(hasattr(self.driver,'ROWID'), + 'module.ROWID must be defined.' + ) + diff --git a/lib/mysql/tests/test_MySQLdb_capabilities.py b/lib/mysql/tests/test_MySQLdb_capabilities.py new file mode 100644 index 00000000..ead69822 --- /dev/null +++ b/lib/mysql/tests/test_MySQLdb_capabilities.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python +import capabilities +import unittest +import MySQLdb +import warnings + +warnings.filterwarnings('ignore') + +class test_MySQLdb(capabilities.DatabaseTest): + + db_module = MySQLdb + connect_args = () + connect_kwargs = dict(use_unicode=True, sql_mode="ANSI,STRICT_TRANS_TABLES,TRADITIONAL") + create_table_extra = "ENGINE=INNODB CHARACTER SET UTF8" + leak_test = False + + def quote_identifier(self, ident): + return "`%s`" % ident + + def test_TIME(self): + from datetime import timedelta + def generator(row,col): + return timedelta(0, row*8000) + self.check_data_integrity( + ('col1 TIME',), + generator) + + def test_TINYINT(self): + # Number data + def generator(row,col): + v = (row*row) % 256 + if v > 127: + v = v-256 + return v + self.check_data_integrity( + ('col1 TINYINT',), + generator) + + def test_stored_procedures(self): + db = self.connection + c = self.cursor + self.create_table(('pos INT', 'tree CHAR(20)')) + c.executemany("INSERT INTO %s (pos,tree) VALUES (%%s,%%s)" % self.table, + list(enumerate('ash birch cedar larch pine'.split()))) + db.commit() + + c.execute(""" + CREATE PROCEDURE test_sp(IN t VARCHAR(255)) + BEGIN + SELECT pos FROM %s WHERE tree = t; + END + """ % self.table) + db.commit() + + c.callproc('test_sp', ('larch',)) + rows = c.fetchall() + self.assertEquals(len(rows), 1) + self.assertEquals(rows[0][0], 3) + c.nextset() + + c.execute("DROP PROCEDURE test_sp") + c.execute('drop table %s' % (self.table)) + + def test_small_CHAR(self): + # Character data + def generator(row,col): + i = (row*col+62)%256 + if i == 62: return '' + if i == 63: return None + return chr(i) + self.check_data_integrity( + ('col1 char(1)','col2 char(1)'), + generator) + + def test_bug_2671682(self): + from MySQLdb.constants import ER + try: + self.cursor.execute("describe some_non_existent_table"); + except self.connection.ProgrammingError, msg: + self.assertEquals(msg[0], ER.NO_SUCH_TABLE) + + def test_bug_3514287(self): + c = self.cursor + try: + c.execute("""create table bug_3541287 ( + c1 CHAR(10), + t1 TIMESTAMP)""") + c.execute("insert into bug_3541287 (c1,t1) values (%s, NOW())", + ("blah",)) + finally: + c.execute("drop table if exists bug_3541287") + + def test_ping(self): + self.connection.ping() + + +if __name__ == '__main__': + if test_MySQLdb.leak_test: + import gc + gc.enable() + gc.set_debug(gc.DEBUG_LEAK) + unittest.main() diff --git a/lib/mysql/tests/test_MySQLdb_dbapi20.py b/lib/mysql/tests/test_MySQLdb_dbapi20.py new file mode 100644 index 00000000..2832e323 --- /dev/null +++ b/lib/mysql/tests/test_MySQLdb_dbapi20.py @@ -0,0 +1,204 @@ +#!/usr/bin/env python +import dbapi20 +import unittest +import MySQLdb +from configdb import connection_kwargs +import warnings +warnings.simplefilter("ignore") + +class test_MySQLdb(dbapi20.DatabaseAPI20Test): + driver = MySQLdb + connect_args = () + connect_kw_args = connection_kwargs(dict(sql_mode="ANSI,STRICT_TRANS_TABLES,TRADITIONAL")) + + def test_setoutputsize(self): pass + def test_setoutputsize_basic(self): pass + def test_nextset(self): pass + + """The tests on fetchone and fetchall and rowcount bogusly + test for an exception if the statement cannot return a + result set. MySQL always returns a result set; it's just that + some things return empty result sets.""" + + def test_fetchall(self): + con = self._connect() + try: + cur = con.cursor() + # cursor.fetchall should raise an Error if called + # without executing a query that may return rows (such + # as a select) + self.assertRaises(self.driver.Error, cur.fetchall) + + self.executeDDL1(cur) + for sql in self._populate(): + cur.execute(sql) + + # cursor.fetchall should raise an Error if called + # after executing a a statement that cannot return rows +## self.assertRaises(self.driver.Error,cur.fetchall) + + cur.execute('select name from %sbooze' % self.table_prefix) + rows = cur.fetchall() + self.assertTrue(cur.rowcount in (-1,len(self.samples))) + self.assertEqual(len(rows),len(self.samples), + 'cursor.fetchall did not retrieve all rows' + ) + rows = [r[0] for r in rows] + rows.sort() + for i in range(0,len(self.samples)): + self.assertEqual(rows[i],self.samples[i], + 'cursor.fetchall retrieved incorrect rows' + ) + rows = cur.fetchall() + self.assertEqual( + len(rows),0, + 'cursor.fetchall should return an empty list if called ' + 'after the whole result set has been fetched' + ) + self.assertTrue(cur.rowcount in (-1,len(self.samples))) + + self.executeDDL2(cur) + cur.execute('select name from %sbarflys' % self.table_prefix) + rows = cur.fetchall() + self.assertTrue(cur.rowcount in (-1,0)) + self.assertEqual(len(rows),0, + 'cursor.fetchall should return an empty list if ' + 'a select query returns no rows' + ) + + finally: + con.close() + + def test_fetchone(self): + con = self._connect() + try: + cur = con.cursor() + + # cursor.fetchone should raise an Error if called before + # executing a select-type query + self.assertRaises(self.driver.Error,cur.fetchone) + + # cursor.fetchone should raise an Error if called after + # executing a query that cannnot return rows + self.executeDDL1(cur) +## self.assertRaises(self.driver.Error,cur.fetchone) + + cur.execute('select name from %sbooze' % self.table_prefix) + self.assertEqual(cur.fetchone(),None, + 'cursor.fetchone should return None if a query retrieves ' + 'no rows' + ) + self.assertTrue(cur.rowcount in (-1,0)) + + # cursor.fetchone should raise an Error if called after + # executing a query that cannnot return rows + cur.execute("insert into %sbooze values ('Victoria Bitter')" % ( + self.table_prefix + )) +## self.assertRaises(self.driver.Error,cur.fetchone) + + cur.execute('select name from %sbooze' % self.table_prefix) + r = cur.fetchone() + self.assertEqual(len(r),1, + 'cursor.fetchone should have retrieved a single row' + ) + self.assertEqual(r[0],'Victoria Bitter', + 'cursor.fetchone retrieved incorrect data' + ) +## self.assertEqual(cur.fetchone(),None, +## 'cursor.fetchone should return None if no more rows available' +## ) + self.assertTrue(cur.rowcount in (-1,1)) + finally: + con.close() + + # Same complaint as for fetchall and fetchone + def test_rowcount(self): + con = self._connect() + try: + cur = con.cursor() + self.executeDDL1(cur) +## self.assertEqual(cur.rowcount,-1, +## 'cursor.rowcount should be -1 after executing no-result ' +## 'statements' +## ) + cur.execute("insert into %sbooze values ('Victoria Bitter')" % ( + self.table_prefix + )) +## self.assertTrue(cur.rowcount in (-1,1), +## 'cursor.rowcount should == number or rows inserted, or ' +## 'set to -1 after executing an insert statement' +## ) + cur.execute("select name from %sbooze" % self.table_prefix) + self.assertTrue(cur.rowcount in (-1,1), + 'cursor.rowcount should == number of rows returned, or ' + 'set to -1 after executing a select statement' + ) + self.executeDDL2(cur) +## self.assertEqual(cur.rowcount,-1, +## 'cursor.rowcount not being reset to -1 after executing ' +## 'no-result statements' +## ) + finally: + con.close() + + def test_callproc(self): + pass # performed in test_MySQL_capabilities + + def help_nextset_setUp(self,cur): + ''' Should create a procedure called deleteme + that returns two result sets, first the + number of rows in booze then "name from booze" + ''' + sql=""" + create procedure deleteme() + begin + select count(*) from %(tp)sbooze; + select name from %(tp)sbooze; + end + """ % dict(tp=self.table_prefix) + cur.execute(sql) + + def help_nextset_tearDown(self,cur): + 'If cleaning up is needed after nextSetTest' + cur.execute("drop procedure deleteme") + + def test_nextset(self): + from warnings import warn + con = self._connect() + try: + cur = con.cursor() + if not hasattr(cur,'nextset'): + return + + try: + self.executeDDL1(cur) + sql=self._populate() + for sql in self._populate(): + cur.execute(sql) + + self.help_nextset_setUp(cur) + + cur.callproc('deleteme') + numberofrows=cur.fetchone() + assert numberofrows[0]== len(self.samples) + assert cur.nextset() + names=cur.fetchall() + assert len(names) == len(self.samples) + s=cur.nextset() + if s: + empty = cur.fetchall() + self.assertEquals(len(empty), 0, + "non-empty result set after other result sets") + #warn("Incompatibility: MySQL returns an empty result set for the CALL itself", + # Warning) + #assert s == None,'No more return sets, should return None' + finally: + self.help_nextset_tearDown(cur) + + finally: + con.close() + + +if __name__ == '__main__': + unittest.main() diff --git a/lib/mysql/tests/test_MySQLdb_nonstandard.py b/lib/mysql/tests/test_MySQLdb_nonstandard.py new file mode 100644 index 00000000..a5c0e846 --- /dev/null +++ b/lib/mysql/tests/test_MySQLdb_nonstandard.py @@ -0,0 +1,87 @@ +import unittest + +import _mysql +import MySQLdb +from MySQLdb.constants import FIELD_TYPE +from configdb import connection_factory +import warnings +warnings.simplefilter("ignore") + +class TestDBAPISet(unittest.TestCase): + def test_set_equality(self): + self.assertTrue(MySQLdb.STRING == MySQLdb.STRING) + + def test_set_inequality(self): + self.assertTrue(MySQLdb.STRING != MySQLdb.NUMBER) + + def test_set_equality_membership(self): + self.assertTrue(FIELD_TYPE.VAR_STRING == MySQLdb.STRING) + + def test_set_inequality_membership(self): + self.assertTrue(FIELD_TYPE.DATE != MySQLdb.STRING) + + +class CoreModule(unittest.TestCase): + """Core _mysql module features.""" + + def test_NULL(self): + """Should have a NULL constant.""" + self.assertEqual(_mysql.NULL, 'NULL') + + def test_version(self): + """Version information sanity.""" + self.assertTrue(isinstance(_mysql.__version__, str)) + + self.assertTrue(isinstance(_mysql.version_info, tuple)) + self.assertEqual(len(_mysql.version_info), 5) + + def test_client_info(self): + self.assertTrue(isinstance(_mysql.get_client_info(), str)) + + def test_thread_safe(self): + self.assertTrue(isinstance(_mysql.thread_safe(), int)) + + +class CoreAPI(unittest.TestCase): + """Test _mysql interaction internals.""" + + def setUp(self): + self.conn = connection_factory(use_unicode=True) + + def tearDown(self): + self.conn.close() + + def test_thread_id(self): + tid = self.conn.thread_id() + self.assertTrue(isinstance(tid, int), + "thread_id didn't return an int.") + + self.assertRaises(TypeError, self.conn.thread_id, ('evil',), + "thread_id shouldn't accept arguments.") + + def test_affected_rows(self): + self.assertEquals(self.conn.affected_rows(), 0, + "Should return 0 before we do anything.") + + + #def test_debug(self): + ## FIXME Only actually tests if you lack SUPER + #self.assertRaises(MySQLdb.OperationalError, + #self.conn.dump_debug_info) + + def test_charset_name(self): + self.assertTrue(isinstance(self.conn.character_set_name(), str), + "Should return a string.") + + def test_host_info(self): + self.assertTrue(isinstance(self.conn.get_host_info(), str), + "Should return a string.") + + def test_proto_info(self): + self.assertTrue(isinstance(self.conn.get_proto_info(), int), + "Should return an int.") + + def test_server_info(self): + self.assertTrue(isinstance(self.conn.get_server_info(), str), + "Should return an str.") +