mirror of
https://github.com/PyMySQL/mysqlclient.git
synced 2025-08-15 19:31:54 +08:00
Version 1.1.7
This commit is contained in:
@ -1,691 +0,0 @@
|
|||||||
2004-09-19 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* _mysql.c, setup.py, MySQLdb/__init__.py, MySQLdb/connections.py:
|
|
||||||
* Removed some old-style Python stuff from setup.py
|
|
||||||
|
|
||||||
* Added a bit of documentation on ssl parameter to Connection
|
|
||||||
|
|
||||||
* Version 1.1.5
|
|
||||||
|
|
||||||
* MANIFEST.in: Include new ChangeLog
|
|
||||||
|
|
||||||
* setup.py: Restore missing common on include_dirs
|
|
||||||
|
|
||||||
2004-09-11 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* ChangeLog: *** empty log message ***
|
|
||||||
|
|
||||||
* _mysql.c, setup.py, MySQLdb/__init__.py, MySQLdb/connections.py:
|
|
||||||
Version 1.1.4
|
|
||||||
|
|
||||||
* setup.py: changed include and library path order
|
|
||||||
|
|
||||||
* MySQLdb/connections.py: fix super class reference in autocommit()
|
|
||||||
|
|
||||||
* Tested against MySQL-4.1.4a with InnoDB tables
|
|
||||||
|
|
||||||
* _mysql.c: Re-fix typo
|
|
||||||
|
|
||||||
* _mysql.c:
|
|
||||||
Fix _mysql_Execption() typo. Code is only compiled when MySQL-4.1
|
|
||||||
is in use, and I haven't done any actual testing against 4.1 yet.
|
|
||||||
Please report any bugs to the SourceForge tracker.
|
|
||||||
|
|
||||||
2004-09-11 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* _mysql.c, setup.py, MySQLdb/__init__.py, MySQLdb/connections.py:
|
|
||||||
Version 1.1.4
|
|
||||||
|
|
||||||
* setup.py: changed include and library path order
|
|
||||||
|
|
||||||
* MySQLdb/connections.py: fix super class reference in autocommit()
|
|
||||||
|
|
||||||
* Tested against MySQL-4.1.4a with InnoDB tables
|
|
||||||
|
|
||||||
* _mysql.c: Re-fix typo
|
|
||||||
|
|
||||||
* _mysql.c:
|
|
||||||
Fix _mysql_Execption() typo. Code is only compiled when MySQL-4.1
|
|
||||||
is in use, and I haven't done any actual testing against 4.1 yet.
|
|
||||||
Please report any bugs to the SourceForge tracker.
|
|
||||||
|
|
||||||
2004-09-08 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* _mysql.c, setup.py, MySQLdb/__init__.py: Version 1.1.3
|
|
||||||
|
|
||||||
* _mysql.c: restored missing mysql_errno() call (bug #1023466)
|
|
||||||
|
|
||||||
* _mysql.c: Only try to use SSL support if HAVE_OPENSSL is defined.
|
|
||||||
Raise NotSupportedError if ssl is requested but not available.
|
|
||||||
|
|
||||||
2004-09-06 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* ChangeLog, _mysql.c, setup.py, MySQLdb/__init__.py, MySQLdb/connections.py, MySQLdb/converters.py, MySQLdb/cursors.py, MySQLdb/times.py:
|
|
||||||
General cleanups.
|
|
||||||
|
|
||||||
* Turn autocommit off initially
|
|
||||||
|
|
||||||
* Add support for mysql_autocommit, _commit, and _rollback API functions
|
|
||||||
(new in MySQL-4.1)
|
|
||||||
|
|
||||||
* Remove Connection.begin(); use SQL BEGIN or START TRANSACTION instead
|
|
||||||
|
|
||||||
* pytimes (standard datetime module) is now the default implementation
|
|
||||||
|
|
||||||
* Detect and handle MySQL-4.1 and newer TIMESTAMP (looks like DATETIME)
|
|
||||||
|
|
||||||
* UnicodeType and ObjectType now always handled (required features)
|
|
||||||
|
|
||||||
* Ditch support for L at the end of long integer
|
|
||||||
|
|
||||||
* Remove z and crypt libs if building for Windows
|
|
||||||
|
|
||||||
* Version 1.1.2
|
|
||||||
|
|
||||||
* setup.py: Don't include z and crypt libs on Windows.
|
|
||||||
|
|
||||||
* _mysql.c: Conditionally define uint on all platforms.
|
|
||||||
|
|
||||||
* MySQLdb/cursors.py: Fix indentation error (again)
|
|
||||||
|
|
||||||
* _mysql.c: Fix bug #992756:
|
|
||||||
|
|
||||||
* Embedded server: List of groups was not NULL-terminated correctly.
|
|
||||||
|
|
||||||
* MySQLdb/cursors.py: Fix bug #989262:
|
|
||||||
|
|
||||||
* Changed errant tab to spaces in cursors.py
|
|
||||||
|
|
||||||
* _mysql.c, setup.py, MySQLdb/__init__.py: Fixes for bug #999588:
|
|
||||||
|
|
||||||
* Use os.environ.get() instead of os.getenv() in setup.py
|
|
||||||
|
|
||||||
* Use PySequence_Length() instead of PySequence_Check() in _mysql.c
|
|
||||||
|
|
||||||
Bump version to 1.0.1b1
|
|
||||||
|
|
||||||
2004-09-06 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* ChangeLog, _mysql.c, setup.py, MySQLdb/__init__.py, MySQLdb/connections.py, MySQLdb/converters.py, MySQLdb/cursors.py, MySQLdb/times.py:
|
|
||||||
General cleanups.
|
|
||||||
|
|
||||||
* Turn autocommit off initially
|
|
||||||
|
|
||||||
* Add support for mysql_autocommit, _commit, and _rollback API functions
|
|
||||||
(new in MySQL-4.1)
|
|
||||||
|
|
||||||
* Remove Connection.begin(); use SQL BEGIN or START TRANSACTION instead
|
|
||||||
|
|
||||||
* pytimes (standard datetime module) is now the default implementation
|
|
||||||
|
|
||||||
* Detect and handle MySQL-4.1 and newer TIMESTAMP (looks like DATETIME)
|
|
||||||
|
|
||||||
* UnicodeType and ObjectType now always handled (required features)
|
|
||||||
|
|
||||||
* Ditch support for L at the end of long integer
|
|
||||||
|
|
||||||
* Remove z and crypt libs if building for Windows
|
|
||||||
|
|
||||||
* Version 1.1.2
|
|
||||||
|
|
||||||
* setup.py: Don't include z and crypt libs on Windows.
|
|
||||||
|
|
||||||
* _mysql.c: Conditionally define uint on all platforms.
|
|
||||||
|
|
||||||
* MySQLdb/cursors.py: Fix indentation error (again)
|
|
||||||
|
|
||||||
* _mysql.c: Fix bug #992756:
|
|
||||||
|
|
||||||
* Embedded server: List of groups was not NULL-terminated correctly.
|
|
||||||
|
|
||||||
* MySQLdb/cursors.py: Fix bug #989262:
|
|
||||||
|
|
||||||
* Changed errant tab to spaces in cursors.py
|
|
||||||
|
|
||||||
* _mysql.c, setup.py, MySQLdb/__init__.py: Fixes for bug #999588:
|
|
||||||
|
|
||||||
* Use os.environ.get() instead of os.getenv() in setup.py
|
|
||||||
|
|
||||||
* Use PySequence_Length() instead of PySequence_Check() in _mysql.c
|
|
||||||
|
|
||||||
Bump version to 1.0.1b1
|
|
||||||
|
|
||||||
2004-06-07 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* MySQLdb/__init__.py, MySQLdb/connections.py, MySQLdb/cursors.py, README, _mysql.c, setup.py:
|
|
||||||
Bump version. Update README. Convert all classes to new-style.
|
|
||||||
|
|
||||||
2004-06-06 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* README, _mysql.c, setup.py, MySQLdb/__init__.py: 1.0.0 (D-Day)
|
|
||||||
|
|
||||||
2004-05-19 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* MySQLdb/__init__.py, MySQLdb/connections.py, MySQLdb/converters.py, MySQLdb/cursors.py, MySQLdb/mxdatetimes.py, MySQLdb/pytimes.py, MySQLdb/sets.py, MySQLdb/times.py, _mysql.c, _mysql_exceptions.py, setup.cfg, setup.py:
|
|
||||||
Initial conversion to modern Python.
|
|
||||||
|
|
||||||
* _mysql.c, setup.py, MySQLdb/__init__.py: Version bump (1.0.0c2)
|
|
||||||
|
|
||||||
2004-05-18 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* MySQLdb/pytimes.py: Fix bug #933911
|
|
||||||
|
|
||||||
* _mysql.c: Fix bug #955031
|
|
||||||
|
|
||||||
* setup.cfg: Fix bug #955032
|
|
||||||
|
|
||||||
2004-05-16 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* MySQLdb/__init__.py, _mysql.c, setup.py: Version Bump
|
|
||||||
|
|
||||||
2004-02-29 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* setup.py: Fix bug #897344
|
|
||||||
|
|
||||||
* MySQLdb/__init__.py: Fix bug #902024
|
|
||||||
|
|
||||||
2003-12-30 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* _mysql.c, setup.py, MySQLdb/__init__.py, MySQLdb/connections.py, MySQLdb/converters.py:
|
|
||||||
* Check for module initialization failure (extremely rare)
|
|
||||||
|
|
||||||
* The MySQL FIELD_TYPE converter can now be a sequence of 2-tuples.
|
|
||||||
Item 0 is a bit mask (using FLAG.*) which must be matched. This should
|
|
||||||
be an integer. Item 1 is the conversion function. If item 0 is not an
|
|
||||||
integer, then this function is considered the default converter for
|
|
||||||
this FIELD_TYPE. Note that these tuples are considered when the query
|
|
||||||
has been executed and the result is available, so it doesn't add a
|
|
||||||
per-row overhead.
|
|
||||||
|
|
||||||
* As a result of the above, BINARY BLOB fields are now returned as
|
|
||||||
character arrays using the array.array class. Non-BINARY BLOB fields
|
|
||||||
(i.e. TEXT) are returned as strings. If unicode is enabled, they are
|
|
||||||
returned as unicode strings.
|
|
||||||
|
|
||||||
* Bump version to 0.9.3b3.
|
|
||||||
|
|
||||||
2003-12-13 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* MySQLdb/converters.py:
|
|
||||||
https://sourceforge.net/tracker/?func=detail&aid=850174&group_id=22307&atid=374932
|
|
||||||
|
|
||||||
Use more precision for floats; str(<float>) doesn't return full precision.
|
|
||||||
|
|
||||||
2003-11-27 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* _mysql.c: Preliminary SSL support. Adds a ssl parameter to connect().
|
|
||||||
ssl should be a mapping. These are the recognized keys:
|
|
||||||
|
|
||||||
ca*, cert*, capath, key*, cipher
|
|
||||||
|
|
||||||
Items marked with * are required. All values must be strings.
|
|
||||||
They are described here:
|
|
||||||
|
|
||||||
http://www.mysql.com/doc/en/SSL_options.html
|
|
||||||
|
|
||||||
You're probably better off putting these variables into an
|
|
||||||
option file and using read_option_file instead.
|
|
||||||
|
|
||||||
SSL is supported in MySQL-4.0 and newer. Even if you don't
|
|
||||||
specify all the required parameters, the connection will probably
|
|
||||||
succeed, although without SSL.
|
|
||||||
|
|
||||||
This is not yet tested in any significant way.
|
|
||||||
|
|
||||||
2003-11-23 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* _mysql.c, setup.py, MySQLdb/__init__.py: Version bump
|
|
||||||
|
|
||||||
* MySQLdb/converters.py, MySQLdb/mxdatetimes.py, MySQLdb/pytimes.py, MySQLdb/stringtimes.py, MySQLdb/times.py:
|
|
||||||
Time-handling updates. New load order is:
|
|
||||||
|
|
||||||
mxdatetime (wrapper around mx.DateTime)
|
|
||||||
pytimes (wrapper around Python-2.3+ datetime)
|
|
||||||
stringtimes (minimal string implementation)
|
|
||||||
|
|
||||||
The logic is, if you're running Python-2.3 and are have mx.Datetime,
|
|
||||||
you probably want to use that instead of datetime.
|
|
||||||
|
|
||||||
2003-11-22 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* MySQLdb/pytimes.py: Bug #816721
|
|
||||||
|
|
||||||
* _mysql.c: Bug #811636 fix (?)
|
|
||||||
|
|
||||||
2003-09-07 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* MySQLdb/cursors.py: info() might return None or empty string
|
|
||||||
|
|
||||||
* MySQLdb/connections.py:
|
|
||||||
Don't treat FIELD_TYPE.CHAR as a character type, it's really
|
|
||||||
a TINYINT (FIELD_TYPE.TINY).
|
|
||||||
|
|
||||||
* MySQLdb/connections.py, _mysql.c: Bug#778822
|
|
||||||
|
|
||||||
* setup.py: Fix version number correctly
|
|
||||||
|
|
||||||
* setup.py, MySQLdb/__init__.py, _mysql.c: Version bump
|
|
||||||
|
|
||||||
2003-07-11 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* setup.py: Include new time handling modules
|
|
||||||
|
|
||||||
* MySQLdb/mxdatetimes.py, MySQLdb/stringtimes.py:
|
|
||||||
Split out old Date/Time handling classes into separate modules
|
|
||||||
|
|
||||||
* MySQLdb/pytimes.py: Finish up TimeDelta_or_None
|
|
||||||
|
|
||||||
2003-07-10 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* CHANGELOG, MySQLdb/times.py:
|
|
||||||
Add support for Python 2.3 datetime classes.
|
|
||||||
|
|
||||||
2003-07-08 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* CHANGELOG, MySQLdb/__init__.py, setup.py: Bump version numbers.
|
|
||||||
|
|
||||||
* _mysql.c: Bump version and remove some unneccesary casts that seem to
|
|
||||||
break things when using Python 2.3.
|
|
||||||
|
|
||||||
2003-07-07 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* MySQLdb/converters.py: Fix bug 605849 (I hope).
|
|
||||||
|
|
||||||
* _mysql.c: Fix member access problems
|
|
||||||
|
|
||||||
2003-04-21 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* _mysql.c: Eliminate use of deprecated PyArg_NoArgs()
|
|
||||||
|
|
||||||
* _mysql.c: Dumb typo
|
|
||||||
|
|
||||||
2003-04-19 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* README, setup.py: Build and documentation updates
|
|
||||||
|
|
||||||
2002-08-22 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* MySQLdb/__init__.py, CHANGELOG, _mysql.c, setup.py:
|
|
||||||
Embedded server support
|
|
||||||
|
|
||||||
* _mysql.c: Clean up compiler warnings about
|
|
||||||
assignment discards qualifiers from pointer target type
|
|
||||||
|
|
||||||
2002-08-02 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* _mysql.c: Windows (blech) compatibility changes. (Gerhard H<>ring)
|
|
||||||
|
|
||||||
2002-08-01 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* CHANGELOG: CHANGELOG
|
|
||||||
|
|
||||||
* _mysql.c: Not supporting GC for python < 2.2
|
|
||||||
|
|
||||||
* MANIFEST.in, pymemcompat.h: Memory API updates
|
|
||||||
|
|
||||||
* MySQLdb/connections.py: Ignore exception from close() in __del__
|
|
||||||
|
|
||||||
* _mysql.c: GC for Python 2.2+
|
|
||||||
|
|
||||||
2002-07-21 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* MySQLdb/__init__.py, CHANGELOG, _mysql.c, setup.py: 0.9.2 (finally)
|
|
||||||
|
|
||||||
2002-07-16 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* MySQLdb/cursors.py:
|
|
||||||
Revert execute behavior: Do not use % operator when there are no args
|
|
||||||
|
|
||||||
2002-07-10 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* README: Rewrite
|
|
||||||
|
|
||||||
* setup.cfg: Packaging cleanups
|
|
||||||
|
|
||||||
* MySQLdb/__init__.py, MySQLdb/cursors.py, CHANGELOG, _mysql.c, setup.py:
|
|
||||||
Version 0.9.2c3, see CHANGELOG
|
|
||||||
|
|
||||||
2002-07-03 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* MySQLdb/converters.py:
|
|
||||||
Revert returning BLOBs as arrays, since MySQL doesn't distinquish
|
|
||||||
between TEXT and BLOB types. (Skip Montanaro)
|
|
||||||
|
|
||||||
* MySQLdb/connections.py:
|
|
||||||
Passing both conv and unicode to connect was broken (Skip Montanaro)
|
|
||||||
|
|
||||||
2002-07-02 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* setup.py: FreeBSD/OpenBSD update
|
|
||||||
|
|
||||||
2002-07-01 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* MySQLdb/cursors.py: Fix dumb (but working) iterator implementation
|
|
||||||
|
|
||||||
* doc/MySQLdb.sgml: Doc updates
|
|
||||||
|
|
||||||
2002-06-26 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* _mysql.c:
|
|
||||||
Add _mysql.thread_safe() (boolean, true if linked with thread-safe lib)
|
|
||||||
|
|
||||||
2002-06-24 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* MySQLdb/__init__.py, _mysql.c, setup.py: Smack my version up
|
|
||||||
|
|
||||||
2002-06-23 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* MySQLdb/connections.py, MySQLdb/cursors.py, CHANGELOG:
|
|
||||||
Some errorhandler cleanups
|
|
||||||
|
|
||||||
2002-06-20 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* CHANGELOG: *** empty log message ***
|
|
||||||
|
|
||||||
* MySQLdb/connections.py: Make the new unicode option actually work
|
|
||||||
|
|
||||||
* MySQLdb/cursors.py: Add nextset() dummy stub
|
|
||||||
|
|
||||||
* MySQLdb/converters.py: BLOBs as array support
|
|
||||||
|
|
||||||
* MySQLdb/connections.py:
|
|
||||||
More Python 2.2 and doc updates. Return blobs as array.
|
|
||||||
The unicode option to connect() causes (VAR)CHAR columns
|
|
||||||
to be returned as unicode stings.
|
|
||||||
|
|
||||||
* _mysql.c: Lots of Python 2.2 updates, especially documentation
|
|
||||||
|
|
||||||
2002-06-18 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* MySQLdb/__init__.py, MySQLdb/connections.py, MySQLdb/converters.py, _mysql.c, MANIFEST.in:
|
|
||||||
Mostly documentation updates, and some code cleanups
|
|
||||||
|
|
||||||
2002-06-15 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* MySQLdb/cursors.py:
|
|
||||||
Make executemany iterate over queries that don't use multiple VALUES
|
|
||||||
|
|
||||||
2002-04-28 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* CHANGELOG, _mysql.c, setup.py:
|
|
||||||
packaging changes, pre-emptive version bump
|
|
||||||
|
|
||||||
* setup.py: Bump version
|
|
||||||
|
|
||||||
* MySQLdb/cursors.py:
|
|
||||||
Errorhandler was broken in cursor
|
|
||||||
CVSr ----------------------------------------------------------------------
|
|
||||||
|
|
||||||
* CHANGELOG: changelog
|
|
||||||
|
|
||||||
* MySQLdb/__init__.py: Version bump
|
|
||||||
|
|
||||||
* _mysql.c: Macro cleanups
|
|
||||||
|
|
||||||
2002-04-27 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* _mysql.c: Fix memory leak in _mysql_escape_dict. (Danny Yoo)
|
|
||||||
|
|
||||||
SSCursor.fetchall() (_mysql_ResultObject_fetch_row) didn't properly
|
|
||||||
increase the size of the result tuple if the result set was more than
|
|
||||||
1000 rows. (Danny Yoo)
|
|
||||||
|
|
||||||
2002-03-19 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* _mysql.c: More (de)allocation cleanups, based on suggestions from
|
|
||||||
python-dev and Skip Montanaro
|
|
||||||
|
|
||||||
* _mysql.c: Use modern allocation with modern Python
|
|
||||||
|
|
||||||
2002-03-14 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* MySQLdb/connections.py: Elminate debugging statement.
|
|
||||||
|
|
||||||
* MySQLdb/__init__.py, MySQLdb/connections.py, MySQLdb/cursors.py, _mysql.c, setup.py:
|
|
||||||
Bump version. Minor Alpha Linux update. Clear errorhandler on close.
|
|
||||||
|
|
||||||
2002-03-01 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* _mysql.c: Fix a memory leak if the connect fails
|
|
||||||
|
|
||||||
2002-01-29 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* MySQLdb/cursors.py: Stricter regex for finding INSERT values
|
|
||||||
([ #505295 ] Wrong regexp in executemany() function.)
|
|
||||||
|
|
||||||
2002-01-25 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* CHANGELOG: changes
|
|
||||||
|
|
||||||
* MySQLdb/__init__.py: Verision bump.
|
|
||||||
|
|
||||||
* _mysql.c:
|
|
||||||
Use modern memory deallocation on modern versions of Python.
|
|
||||||
|
|
||||||
* setup.py:
|
|
||||||
Rework platform config a bit, default to thread-safe client.
|
|
||||||
|
|
||||||
2001-12-29 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* MySQLdb/cursors.py: Fix fetchmany().
|
|
||||||
|
|
||||||
2001-12-24 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* setup.py: Fix version.
|
|
||||||
|
|
||||||
* MySQLdb/connections.py, MySQLdb/cursors.py, doc/.cvsignore, .cvsignore, CHANGELOG, setup.py:
|
|
||||||
Version 0.9.2a1. Unicode + DB-API extensions.
|
|
||||||
|
|
||||||
2001-12-23 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* _mysql.c, MySQLdb/__init__.py: 0.9.2 alpha 1
|
|
||||||
|
|
||||||
* MySQLdb/converters.py: Unicode support.
|
|
||||||
|
|
||||||
2001-12-22 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* _mysql.c: str() can fail in some cases, particularly unicode.
|
|
||||||
Watch for it to prevent core dumps.
|
|
||||||
|
|
||||||
2001-12-03 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* MySQLdb/cursors.py:
|
|
||||||
Fix cursor.rownumber for CursorStoreResultMixIn.fetchmany()
|
|
||||||
and implement cursor.rownumber for CursorUseResultMixIn.fetchXXX().
|
|
||||||
|
|
||||||
2001-11-28 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* setup.py: Catch more *bsd platforms. (Suggested by Ragnar Beer)
|
|
||||||
|
|
||||||
2001-11-07 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* setup.py: Simplify the various configurations.
|
|
||||||
|
|
||||||
Solaris might be fixed for gcc and broken for standard compiler.
|
|
||||||
|
|
||||||
2001-10-31 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* README: Some additional Zope notes.
|
|
||||||
|
|
||||||
* CHANGELOG: Mac OS X updates
|
|
||||||
|
|
||||||
* setup.py: Link with -flat_namespace on Mac OS X/darwin. (Dan Grassi)
|
|
||||||
|
|
||||||
2001-10-25 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* MySQLdb/cursors.py:
|
|
||||||
Do some renaming suggested by recent DB-SIG discussions.
|
|
||||||
|
|
||||||
This should not break anything unless you are using private members.
|
|
||||||
|
|
||||||
2001-10-23 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* CHANGELOG, setup.py: netbsd config
|
|
||||||
|
|
||||||
2001-10-17 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* CHANGELOG, MySQLdb/__init__.py, README, _mysql.c, setup.py:
|
|
||||||
0.9.0 updates
|
|
||||||
|
|
||||||
2001-10-13 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* MySQLdb/__init__.py: import Set
|
|
||||||
|
|
||||||
2001-09-29 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* setup.py: Catch more Linux platforms in the config.
|
|
||||||
|
|
||||||
2001-09-21 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* setup.py: Solaris config (Bent NAgstrup Terp)
|
|
||||||
|
|
||||||
2001-09-20 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* README: Good to update this at least once a year.
|
|
||||||
|
|
||||||
* CHANGELOG, MySQLdb/__init__.py, _mysql.c, setup.py:
|
|
||||||
Update to 0.9.1c2.
|
|
||||||
|
|
||||||
2001-09-13 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* _mysql.c: Fix exception handling in connect() (broken by 0.9.1.c1)
|
|
||||||
|
|
||||||
2001-09-12 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* MANIFEST.in: Added CHANGELOG. (John Bowe)
|
|
||||||
|
|
||||||
2001-09-07 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* setup.py:
|
|
||||||
OSX config (Paul DuBois); tab/space cleanups; more package info
|
|
||||||
|
|
||||||
* PKG-INFO: Generated by distutils.
|
|
||||||
|
|
||||||
* CHANGELOG: More stuff I forgot about.
|
|
||||||
|
|
||||||
* _mysql.c: Use two arg _PyTuple_Resize() for Python 2.2 and newer.
|
|
||||||
|
|
||||||
* setup.py: Version 0.9.1c1
|
|
||||||
|
|
||||||
* MySQLdb/converters.py: Return DECIMAL/NUMERIC as floating point.
|
|
||||||
|
|
||||||
2001-09-06 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* CHANGELOG: Added a CHANGELOG, for people who like that sort of thing.
|
|
||||||
|
|
||||||
* _mysql.c:
|
|
||||||
Kill bastardly refcount bug that occurs starting with Python 2.0.1.
|
|
||||||
PyArgs_ParseTupleAndKeywords() returns borrowed references for O format
|
|
||||||
starting in 2.0.1, prior to that it returns new references, so it's
|
|
||||||
necessary to test the Python version to determine whether or not we
|
|
||||||
should Py_INCREF() it. If we always Py_INCREF() it, this produces a
|
|
||||||
memory leak in versions prior to 2.0.1.
|
|
||||||
|
|
||||||
* MySQLdb/__init__.py, _mysql.c, setup.py:
|
|
||||||
Change version number, back out memory changes.
|
|
||||||
|
|
||||||
* _mysql.c:
|
|
||||||
Memory allocation cleanups. Add missing newline in docstring.
|
|
||||||
|
|
||||||
2001-07-29 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* _mysql.c: ER_PARSE_ERROR -> ProgrammingError;
|
|
||||||
#ifdef around some recent error types
|
|
||||||
|
|
||||||
2001-07-12 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* _mysql.c: Fix leak on converter dictionary. (Ted Wright)
|
|
||||||
|
|
||||||
2001-07-11 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* MANIFEST.in, MySQLdb/__init__.py, MySQLdb/connections.py, MySQLdb/cursors.py, PKG-INFO, _mysql.c, doc/MySQLdb.sgml, setup.py:
|
|
||||||
Minor fixes for 1.0.0.
|
|
||||||
|
|
||||||
2001-06-20 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* doc/MySQLdb.sgml: Clarify use of host parameter to connect().
|
|
||||||
|
|
||||||
* doc/MySQLdb-FAQ.sgml, doc/MySQLdb.sgml:
|
|
||||||
Some corrections courtesy of Paul DuBois.
|
|
||||||
|
|
||||||
2001-06-04 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* MySQLdb/__init__.py, _mysql.c, setup.py: Update version number.
|
|
||||||
|
|
||||||
2001-05-28 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* .cvsignore, MySQLdb/.cvsignore, MySQLdb/constants/.cvsignore, doc/.cvsignore:
|
|
||||||
Ignore stuff.
|
|
||||||
|
|
||||||
2001-05-25 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* MySQLdb/connections.py, _mysql.c, doc/MySQLdb.sgml, setup.py:
|
|
||||||
Rip out _mysql.field_*() methods, as MySQL recommends using SQL
|
|
||||||
instead. See C API docs.
|
|
||||||
|
|
||||||
2001-05-24 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* PKG-INFO: Update version.
|
|
||||||
|
|
||||||
* MySQLdb/__init__.py, _mysql.c:
|
|
||||||
Clean up some import statements, bump versions to 0.9.0c2.
|
|
||||||
|
|
||||||
2001-05-23 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* MySQLdb/times.py: Fix the case where there is no mx.DateTime.
|
|
||||||
|
|
||||||
* MySQLdb/connections.py: Remove a debug string.
|
|
||||||
|
|
||||||
* MANIFEST.in, MySQLdb/__init__.py, MySQLdb/connections.py, _mysql.c, _mysql_version.h, doc/MySQLdb.sgml, setup.cfg, setup.py:
|
|
||||||
0.9.0c1 minor edit.
|
|
||||||
|
|
||||||
2001-05-14 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* _mysql.c: PyObject_Length() == -1 on error. Thanks, Jon Ribbens.
|
|
||||||
|
|
||||||
2001-05-12 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* MySQLdb/__init__.py, MySQLdb/converters.py, MySQLdb/data.py, MySQLdb/sets.py, MySQLdb/times.py, _mysql_version.h, setup.py:
|
|
||||||
Smash data into two separate modules: sets and times. I never liked
|
|
||||||
that name anyway.
|
|
||||||
|
|
||||||
Set has been extended somewhat. The comparision operators really only
|
|
||||||
work properly with Python 2.1, due to the limitations of __cmp__.
|
|
||||||
Set also uses the binary operators (&, |, ^), since these make somewhat
|
|
||||||
more sense than the arithmetic ones, though there is no good analog for
|
|
||||||
- (if only there were a nand operator...)
|
|
||||||
|
|
||||||
Bump the version to 0.9.0b3. This is not the actual 0.9.0b3 release yet,
|
|
||||||
however. I want to do some more insanity checking. But almost ready for
|
|
||||||
some candidate releases.
|
|
||||||
|
|
||||||
2001-05-11 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* MySQLdb/__init__.py, MySQLdb/connections.py, MySQLdb/converters.py, MySQLdb/cursors.py, MySQLdb/data.py, doc/MySQLdb.sgml, _mysql_version.h, setup.py:
|
|
||||||
More major code heaving.
|
|
||||||
|
|
||||||
All the threading stuff is ripped out and burned.
|
|
||||||
Too much code for not enough benefit. Still thread-safe,
|
|
||||||
just don't share connections.
|
|
||||||
|
|
||||||
Made a nice Set class for SET columns.
|
|
||||||
|
|
||||||
Updated the docs.
|
|
||||||
|
|
||||||
2001-05-10 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* doc/MySQLdb-FAQ.sgml, doc/MySQLdb.sgml: Revamped docs.
|
|
||||||
|
|
||||||
2001-05-09 adustman <adustman@tweek.neosouth.net>
|
|
||||||
|
|
||||||
* MySQLdb/__init__.py, MySQLdb/connections.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, MySQLdb/converters.py, MySQLdb/cursors.py, PKG-INFO, _mysql_exceptions.py, _mysql_version.h:
|
|
||||||
Initial import of 0.9.0 series (pre-1.0.0).
|
|
||||||
|
|
||||||
* MySQLdb/__init__.py, MySQLdb/connections.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, MySQLdb/converters.py, MySQLdb/cursors.py, PKG-INFO, _mysql_exceptions.py, _mysql_version.h:
|
|
||||||
New file.
|
|
||||||
|
|
||||||
* CompatMysqldb.py, MANIFEST.in, README, _mysql.c, setup.py:
|
|
||||||
Initial import of 0.9.0 series (pre-1.0.0).
|
|
||||||
|
|
||||||
* CompatMysqldb.py, MANIFEST.in, README, _mysql.c, setup.py: New file.
|
|
||||||
|
|
@ -1,318 +0,0 @@
|
|||||||
"""
|
|
||||||
Original author: James Henstridge <james@daa.com.au>
|
|
||||||
Adapted by: Andy Dustman <andy@dustman.net>
|
|
||||||
|
|
||||||
This is the original Mysqldb.py module which came with MySQLmodule-1.4,
|
|
||||||
only it has been adapted to use _mysql instead MySQL. It is intended
|
|
||||||
for backwards compatibility purposes only. But as a bonus, transactions
|
|
||||||
will work if your database server and table types support them. It is
|
|
||||||
called CompatMysqldb instead of Mysqldb so as not to interfere with an
|
|
||||||
existing Mysqldb, or MySQLdb on case-insensitive brain-dead operating
|
|
||||||
systems.
|
|
||||||
|
|
||||||
Under no circumstances should you bug James Henstridge about this!!!
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
This is a class that implements an interface to mySQL databases, conforming
|
|
||||||
to the API published by the Python db-sig at
|
|
||||||
http://www.python.org/sigs/db-sig/DatabaseAPI.html
|
|
||||||
|
|
||||||
It is really just a wrapper for an older python interface to mySQL databases
|
|
||||||
called mySQL, which I modified to facilitate use of a cursor. That module was
|
|
||||||
Joseph Skinner's port of the mSQL module by David Gibson, which was a modified
|
|
||||||
version of Anthony Baxter's msql module.
|
|
||||||
|
|
||||||
As an example, to add some extra (unprivelledged) users to your database system,
|
|
||||||
and delete them again:
|
|
||||||
|
|
||||||
>>> import Mysqldb
|
|
||||||
>>> conn = Mysqldb.mysqldb('mysql@localhost root rootpasswd')
|
|
||||||
>>> curs = conn.cursor()
|
|
||||||
>>> curs.execute("insert into user (host, user) values ('%s', '%s')",
|
|
||||||
... [('localhost', 'linus'), ('somewhere.com.au', 'james')])
|
|
||||||
2
|
|
||||||
>>> curs.execute("select * from user")
|
|
||||||
>>> curs.fetchall()
|
|
||||||
-- record listing --
|
|
||||||
>>> curs.execute("delete from user where host = 'somewhere.com.au' or user = 'linus'")
|
|
||||||
2
|
|
||||||
>>> curs.close()
|
|
||||||
>>> conn.close()
|
|
||||||
|
|
||||||
The argument to mysqldb.mysqldb is of the form 'db@host user pass',
|
|
||||||
'db@host user', 'db@host', 'db', 'db user pass' or 'db user'.
|
|
||||||
|
|
||||||
As always, the source is a good manual :-)
|
|
||||||
|
|
||||||
James Henstridge <james@daa.com.au>
|
|
||||||
"""
|
|
||||||
|
|
||||||
import _mysql
|
|
||||||
MySQL = _mysql
|
|
||||||
from string import upper, split, join
|
|
||||||
|
|
||||||
error = 'mysqldb.error'
|
|
||||||
|
|
||||||
from MySQLdb.constants import FIELD_TYPE
|
|
||||||
_type_conv = { FIELD_TYPE.TINY: int,
|
|
||||||
FIELD_TYPE.SHORT: int,
|
|
||||||
FIELD_TYPE.LONG: long,
|
|
||||||
FIELD_TYPE.FLOAT: float,
|
|
||||||
FIELD_TYPE.DOUBLE: float,
|
|
||||||
FIELD_TYPE.LONGLONG: long,
|
|
||||||
FIELD_TYPE.INT24: int,
|
|
||||||
FIELD_TYPE.YEAR: int }
|
|
||||||
|
|
||||||
def isDDL(q):
|
|
||||||
return upper(split(q)[0]) in ('CREATE', 'ALTER', 'GRANT', 'REVOKE',
|
|
||||||
'DROP', 'SET')
|
|
||||||
def isDML(q):
|
|
||||||
return upper(split(q)[0]) in ('DELETE', 'INSERT', 'UPDATE', 'LOAD')
|
|
||||||
def isDQL(q):
|
|
||||||
return upper(split(q)[0]) in ('SELECT', 'SHOW', 'DESC', 'DESCRIBE')
|
|
||||||
|
|
||||||
class DBAPITypeObject:
|
|
||||||
|
|
||||||
def __init__(self,*values):
|
|
||||||
self.values = values
|
|
||||||
|
|
||||||
def __cmp__(self,other):
|
|
||||||
if other in self.values:
|
|
||||||
return 0
|
|
||||||
if other < self.values:
|
|
||||||
return 1
|
|
||||||
else:
|
|
||||||
return -1
|
|
||||||
|
|
||||||
_Set = DBAPITypeObject
|
|
||||||
|
|
||||||
STRING = _Set(FIELD_TYPE.CHAR, FIELD_TYPE.ENUM, FIELD_TYPE.INTERVAL,
|
|
||||||
FIELD_TYPE.SET, FIELD_TYPE.STRING, FIELD_TYPE.VAR_STRING)
|
|
||||||
BINARY = _Set(FIELD_TYPE.BLOB, FIELD_TYPE.LONG_BLOB, FIELD_TYPE.MEDIUM_BLOB,
|
|
||||||
FIELD_TYPE.TINY_BLOB)
|
|
||||||
NUMBER = _Set(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 = _Set(FIELD_TYPE.DATE, FIELD_TYPE.NEWDATE)
|
|
||||||
TIME = _Set(FIELD_TYPE.TIME)
|
|
||||||
TIMESTAMP = _Set(FIELD_TYPE.TIMESTAMP, FIELD_TYPE.DATETIME)
|
|
||||||
ROWID = _Set()
|
|
||||||
|
|
||||||
class Connection:
|
|
||||||
"""This is the connection object for the mySQL database interface."""
|
|
||||||
def __init__(self, host, user, passwd, db):
|
|
||||||
from MySQLdb.constants import CLIENT
|
|
||||||
kwargs = {}
|
|
||||||
kwargs['conv'] = _type_conv
|
|
||||||
if host: kwargs['host'] = host
|
|
||||||
if user: kwargs['user'] = user
|
|
||||||
if passwd: kwargs['passwd'] = passwd
|
|
||||||
if db: kwargs['db'] = db
|
|
||||||
try:
|
|
||||||
self.__conn = apply(MySQL.connect, (), kwargs)
|
|
||||||
except MySQL.Error, msg:
|
|
||||||
raise error, msg
|
|
||||||
self.__curs = Cursor(self.__conn)
|
|
||||||
self.__transactional = self.__conn.server_capabilities & CLIENT.TRANSACTIONS
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
self.close()
|
|
||||||
|
|
||||||
def __getattr__(self, key):
|
|
||||||
return getattr(self.__curs, key)
|
|
||||||
|
|
||||||
def __setattr__(self, key, val):
|
|
||||||
if key in ('arraysize', 'description', 'insert_id'):
|
|
||||||
setattr(self.__curs, key, val)
|
|
||||||
else:
|
|
||||||
self.__dict__[key] = val
|
|
||||||
|
|
||||||
def close(self):
|
|
||||||
self.__conn = None
|
|
||||||
|
|
||||||
def cursor(self):
|
|
||||||
if self.__conn == None: raise error, "Connection is closed."
|
|
||||||
return Cursor(self.__conn)
|
|
||||||
|
|
||||||
def commit(self):
|
|
||||||
"""Commit the current transaction."""
|
|
||||||
if self.__transactional:
|
|
||||||
self.__conn.query("COMMIT")
|
|
||||||
|
|
||||||
def rollback(self):
|
|
||||||
"""Rollback the current transaction."""
|
|
||||||
if self.__transactional:
|
|
||||||
self.__conn.query("ROLLBACK")
|
|
||||||
else: raise error, "Not supported by server"
|
|
||||||
|
|
||||||
def callproc(self, params=None): pass
|
|
||||||
|
|
||||||
# These functions are just here so that every action that is
|
|
||||||
# covered by mySQL is covered by mysqldb. They are not standard
|
|
||||||
# DB API. The list* methods are not included, since they can be
|
|
||||||
# done with the SQL SHOW command.
|
|
||||||
def create(self, dbname):
|
|
||||||
"""This is not a standard part of Python DB API."""
|
|
||||||
self.__conn.query("CREATE DATABASE %s" % dbname)
|
|
||||||
self.__conn.store_result()
|
|
||||||
return None
|
|
||||||
def drop(self, dbname):
|
|
||||||
"""This is not a standard part of Python DB API."""
|
|
||||||
self.__conn.query("DROP DATABASE %s" % dbname)
|
|
||||||
self.__conn.store_result()
|
|
||||||
return None
|
|
||||||
def reload(self):
|
|
||||||
"""This is not a standard part of Python DB API."""
|
|
||||||
self.__conn.query("RELOAD TABLES")
|
|
||||||
self.__conn.store_result()
|
|
||||||
return None
|
|
||||||
def shutdown(self):
|
|
||||||
"""This is not a standard part of Python DB API."""
|
|
||||||
return self.__conn.shutdown()
|
|
||||||
|
|
||||||
|
|
||||||
class Cursor:
|
|
||||||
"""A cursor object for use with connecting to mySQL databases."""
|
|
||||||
def __init__(self, conn):
|
|
||||||
self.__conn = conn
|
|
||||||
self.__res = None
|
|
||||||
self.arraysize = 1
|
|
||||||
self.__dict__['description'] = None
|
|
||||||
self.__open = 1
|
|
||||||
self.insert_id = 0
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
self.close()
|
|
||||||
|
|
||||||
def __setattr__(self, key, val):
|
|
||||||
if key == 'description':
|
|
||||||
raise error, "description is a read-only attribute."
|
|
||||||
else:
|
|
||||||
self.__dict__[key] = val
|
|
||||||
|
|
||||||
def __delattr__(self, key):
|
|
||||||
if key in ('description', 'arraysize', 'insert_id'):
|
|
||||||
raise error, "%s can't be deleted." % (key,)
|
|
||||||
else:
|
|
||||||
del self.__dict__[key]
|
|
||||||
|
|
||||||
def close(self):
|
|
||||||
self.__conn = None
|
|
||||||
self.__res = None
|
|
||||||
self.__open = 0
|
|
||||||
|
|
||||||
def execute(self, op, params=None):
|
|
||||||
if not self.__open: raise error, "Cursor has been closed."
|
|
||||||
if params:
|
|
||||||
if type(params[0]) not in (type(()), type([])):
|
|
||||||
params = [params]
|
|
||||||
if isDDL(op):
|
|
||||||
self.__dict__['description'] = None
|
|
||||||
try:
|
|
||||||
for x in params:
|
|
||||||
self.__res = \
|
|
||||||
self.__conn.query(op % x)
|
|
||||||
self.insert_id = self.__res.insert_id()
|
|
||||||
except MySQL.Error, msg:
|
|
||||||
raise error, msg
|
|
||||||
return 1
|
|
||||||
if isDML(op):
|
|
||||||
self.__dict__['description'] = None
|
|
||||||
af = 0
|
|
||||||
try:
|
|
||||||
for x in params:
|
|
||||||
self.__res = \
|
|
||||||
self.__conn.query(op % x)
|
|
||||||
af =af+self.__res.affectedrows()
|
|
||||||
self.insert_id = self.__res.insert_id()
|
|
||||||
except MySQL.Error, msg:
|
|
||||||
raise error, msg
|
|
||||||
return af
|
|
||||||
if isDQL(op):
|
|
||||||
try:
|
|
||||||
self.__res = self.__conn.query(
|
|
||||||
op % params[-1])
|
|
||||||
self.insert_id = self.__res.insert_id()
|
|
||||||
except MySQL.Error, msg:
|
|
||||||
raise error, msg
|
|
||||||
self.__dict__['description'] = self.__res.describe()
|
|
||||||
return None
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
self.__conn.query(op)
|
|
||||||
self.__res = self.__conn.store_result()
|
|
||||||
self.insert_id = self.__conn.insert_id()
|
|
||||||
except MySQL.Error, msg:
|
|
||||||
raise error, msg
|
|
||||||
self.__dict__['description'] = None
|
|
||||||
if isDDL(op):
|
|
||||||
return 1
|
|
||||||
elif self.__conn.affected_rows() != -1:
|
|
||||||
return self.__conn.affected_rows()
|
|
||||||
else:
|
|
||||||
self.__dict__['description'] = self.__res.describe()
|
|
||||||
return None
|
|
||||||
def fetchone(self):
|
|
||||||
if not self.__res: raise error, "no query made yet."
|
|
||||||
try:
|
|
||||||
return self.__res.fetch_row(1)[0]
|
|
||||||
except MySQL.Error, msg:
|
|
||||||
raise error, msg
|
|
||||||
|
|
||||||
def fetchmany(self, size=None):
|
|
||||||
if not self.__res: raise error, "no query made yet."
|
|
||||||
try:
|
|
||||||
return self.__res.fetch_row(size or self.arraysize)
|
|
||||||
except MySQL.Error, msg:
|
|
||||||
raise error, msg
|
|
||||||
|
|
||||||
def fetchall(self):
|
|
||||||
if not self.__res: raise error, "no query made yet."
|
|
||||||
try:
|
|
||||||
return self.__res.fetch_row(0)
|
|
||||||
except MySQL.Error, msg:
|
|
||||||
raise error, msg
|
|
||||||
|
|
||||||
def fetchoneDict(self):
|
|
||||||
"""This is not a standard part of Python DB API."""
|
|
||||||
if not self.__res: raise error, "no query made yet."
|
|
||||||
try:
|
|
||||||
return self.__res.fetch_row(1, 2)[0]
|
|
||||||
except MySQL.Error, msg:
|
|
||||||
raise error, msg
|
|
||||||
|
|
||||||
def fetchmanyDict(self, size=None):
|
|
||||||
"""This is not a standard part of Python DB API."""
|
|
||||||
if not self.__res: raise error, "no query made yet."
|
|
||||||
try:
|
|
||||||
return self.__res.fetch_row(size or self.arraysize, 2)
|
|
||||||
except MySQL.Error, msg:
|
|
||||||
raise error, msg
|
|
||||||
|
|
||||||
def fetchallDict(self):
|
|
||||||
"""This is not a standard part of Python DB API."""
|
|
||||||
if not self.__res: raise error, "no query made yet."
|
|
||||||
try:
|
|
||||||
return self.__res.fetch_row(0,2)
|
|
||||||
except MySQL.Error, msg:
|
|
||||||
raise error, msg
|
|
||||||
|
|
||||||
def setinputsizes(self, sizes): pass
|
|
||||||
def setoutputsize(self, size, col=None): pass
|
|
||||||
|
|
||||||
|
|
||||||
def mysqldb(connect_string):
|
|
||||||
"""Makes a connection to the MySQL server. The Argument should be of
|
|
||||||
the form 'db@host user pass' or 'db@host user' or 'db@host' or 'db'
|
|
||||||
or 'db user pass' or 'db user', where db is the database name, host
|
|
||||||
is the server's host name, user is your user name, and pass is your
|
|
||||||
password."""
|
|
||||||
val = split(connect_string)
|
|
||||||
if len(val) == 0: raise error, "no database specified"
|
|
||||||
while len(val) < 3: val.append('')
|
|
||||||
dh = split(val[0], '@')
|
|
||||||
if len(dh) == 0: raise error, "no database specified"
|
|
||||||
while len(dh) < 2: dh.append('')
|
|
||||||
return Connection(dh[1], val[1], val[2], dh[0])
|
|
||||||
|
|
@ -18,7 +18,7 @@ __revision__ = """$Revision$"""[11:-2]
|
|||||||
version_info = (
|
version_info = (
|
||||||
1,
|
1,
|
||||||
1,
|
1,
|
||||||
6,
|
7,
|
||||||
"final",
|
"final",
|
||||||
1)
|
1)
|
||||||
if version_info[3] == "final": __version__ = "%d.%d.%d" % version_info[:3]
|
if version_info[3] == "final": __version__ = "%d.%d.%d" % version_info[:3]
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#define version_info "(1,1,6,'final',1)"
|
#define version_info "(1,1,7,'final',1)"
|
||||||
#define __version__ "1.1.6"
|
#define __version__ "1.1.7"
|
||||||
/*
|
/*
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
622
MySQLdb/doc/MySQLdb.txt
Normal file
622
MySQLdb/doc/MySQLdb.txt
Normal file
@ -0,0 +1,622 @@
|
|||||||
|
====================
|
||||||
|
MySQLdb User's Guide
|
||||||
|
====================
|
||||||
|
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/en/index.html
|
||||||
|
|
||||||
|
|
||||||
|
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_close()`` ``conn.close()``
|
||||||
|
``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_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()`` ``_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_row_seek()`` ``result.row_seek()``
|
||||||
|
``mysql_row_tell()`` ``result.row_tell()``
|
||||||
|
``mysql_select_db()`` ``conn.select_db()``
|
||||||
|
``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()``
|
||||||
|
``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.*
|
||||||
|
|
||||||
|
unicode
|
||||||
|
If set, CHAR and VARCHAR columns are returned as Unicode
|
||||||
|
strings, using the specified character set. None means to
|
||||||
|
use a default encoding. *This must be a keyword
|
||||||
|
parameter.*
|
||||||
|
|
||||||
|
unicode_errors
|
||||||
|
If set, this is used as the errors parameter to the
|
||||||
|
``unicode()`` function. Default: "strict". *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
|
||||||
|
|
||||||
|
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()
|
||||||
|
Not implemented.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
insert_id()
|
||||||
|
Returns the last ``AUTO_INCREMENT`` field value inserted
|
||||||
|
into the database. (Non-standard)
|
||||||
|
|
||||||
|
info()
|
||||||
|
Returns some information about the last query. Normally
|
||||||
|
you don't need to check this. With the default cursor, any MySQL
|
||||||
|
warnings cause ``Warning`` to be raised. If you are using a
|
||||||
|
cursor class without warnings, then you might want to use
|
||||||
|
this. See the MySQL docs for ``mysql_info()``. (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;
|
||||||
|
there is currently no support for this in MySQLdb.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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 100. 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.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
:Title: MySQLdb: a Python interface for MySQL
|
||||||
|
:Author: Andy Dustman
|
||||||
|
:Version: $Revision$
|
@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
"""Setup script for the MySQLdb module distribution."""
|
"""Setup script for the MySQLdb module distribution."""
|
||||||
|
|
||||||
import os, sys
|
import os
|
||||||
|
import sys
|
||||||
from distutils.core import setup
|
from distutils.core import setup
|
||||||
from distutils.extension import Extension
|
from distutils.extension import Extension
|
||||||
|
|
||||||
@ -18,7 +19,7 @@ embedded_server = (mysqlclient == 'mysqld')
|
|||||||
name = "MySQL-%s" % os.path.basename(sys.executable)
|
name = "MySQL-%s" % os.path.basename(sys.executable)
|
||||||
if embedded_server:
|
if embedded_server:
|
||||||
name = name + "-embedded"
|
name = name + "-embedded"
|
||||||
version = "1.1.6"
|
version = "1.1.7"
|
||||||
|
|
||||||
# include files and library locations should cover most platforms
|
# include files and library locations should cover most platforms
|
||||||
include_dirs = [
|
include_dirs = [
|
||||||
@ -87,7 +88,11 @@ elif os.name == "posix": # UNIX-ish platforms not covered above
|
|||||||
else:
|
else:
|
||||||
raise "UnknownPlatform", "sys.platform=%s, os.name=%s" % \
|
raise "UnknownPlatform", "sys.platform=%s, os.name=%s" % \
|
||||||
(sys.platform, os.name)
|
(sys.platform, os.name)
|
||||||
|
|
||||||
|
# avoid frightening noobs with warnings about missing directories
|
||||||
|
include_dirs = [ d for d in include_dirs if os.path.isdir(d) ]
|
||||||
|
library_dirs = [ d for d in library_dirs if os.path.isdir(d) ]
|
||||||
|
|
||||||
long_description = \
|
long_description = \
|
||||||
"""Python interface to MySQL
|
"""Python interface to MySQL
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user