This commit was manufactured by cvs2svn to create tag 'r_1_1_7'.

This commit is contained in:
(no author)
2004-10-31 03:49:19 +00:00
parent 28d85501da
commit 2c8d9ba82d
68 changed files with 0 additions and 7271 deletions

View File

@ -1,13 +0,0 @@
# The "checkoutlist" file is used to support additional version controlled
# administrative files in $CVSROOT/CVSROOT, such as template files.
#
# The first entry on a line is a filename which will be checked out from
# the corresponding RCS file in the $CVSROOT/CVSROOT directory.
# The remainder of the line is an error message to use if the file cannot
# be checked out.
#
# File format:
#
# [<whitespace>]<filename><whitespace><error message><end-of-line>
#
# comment lines begin with '#'

View File

@ -1,15 +0,0 @@
# The "commitinfo" file is used to control pre-commit checks.
# The filter on the right is invoked with the repository and a list
# of files to check. A non-zero exit of the filter program will
# cause the commit to be aborted.
#
# The first entry on a line is a regular expression which is tested
# against the directory that the change is being committed to, relative
# to the $CVSROOT. For the first match that is found, then the remainder
# of the line is the name of the filter to run.
#
# If the repository name does not match any of the regular expressions in this
# file, the "DEFAULT" line is used, if it is specified.
#
# If the name "ALL" appears as a regular expression it is always used
# in addition to the first matching regex or "DEFAULT".

View File

@ -1,11 +0,0 @@
# Set this to "no" if pserver shouldn't check system users/passwords
#SystemAuth=no
# Set `PreservePermissions' to `yes' to save file status information
# in the repository.
#PreservePermissions=no
# Set `TopLevelAdmin' to `yes' to create a CVS directory at the top
# level of the new working directory when using the `cvs checkout'
# command.
#TopLevelAdmin=no

View File

@ -1,23 +0,0 @@
# This file affects handling of files based on their names.
#
# The -t/-f options allow one to treat directories of files
# as a single file, or to transform a file in other ways on
# its way in and out of CVS.
#
# The -m option specifies whether CVS attempts to merge files.
#
# The -k option specifies keyword expansion (e.g. -kb for binary).
#
# Format of wrapper file ($CVSROOT/CVSROOT/cvswrappers or .cvswrappers)
#
# wildcard [option value][option value]...
#
# where option is one of
# -f from cvs filter value: path to filter
# -t to cvs filter value: path to filter
# -m update methodology value: MERGE or COPY
# -k expansion mode value: b, o, kkv, &c
#
# and value is a single-quote delimited value.
# For example:
#*.gif -k 'b'

View File

@ -1,21 +0,0 @@
# The "editinfo" file is used to allow verification of logging
# information. It works best when a template (as specified in the
# rcsinfo file) is provided for the logging procedure. Given a
# template with locations for, a bug-id number, a list of people who
# reviewed the code before it can be checked in, and an external
# process to catalog the differences that were code reviewed, the
# following test can be applied to the code:
#
# Making sure that the entered bug-id number is correct.
# Validating that the code that was reviewed is indeed the code being
# checked in (using the bug-id number or a seperate review
# number to identify this particular code set.).
#
# If any of the above test failed, then the commit would be aborted.
#
# Actions such as mailing a copy of the report to each reviewer are
# better handled by an entry in the loginfo file.
#
# One thing that should be noted is the the ALL keyword is not
# supported. There can be only one entry that matches a given
# repository.

View File

@ -1,26 +0,0 @@
# The "loginfo" file controls where "cvs commit" log information
# is sent. The first entry on a line is a regular expression which must match
# the directory that the change is being made to, relative to the
# $CVSROOT. If a match is found, then the remainder of the line is a filter
# program that should expect log information on its standard input.
#
# If the repository name does not match any of the regular expressions in this
# file, the "DEFAULT" line is used, if it is specified.
#
# If the name ALL appears as a regular expression it is always used
# in addition to the first matching regex or DEFAULT.
#
# You may specify a format string as part of the
# filter. The string is composed of a `%' followed
# by a single format character, or followed by a set of format
# characters surrounded by `{' and `}' as separators. The format
# characters are:
#
# s = file name
# V = old version number (pre-checkin)
# v = new version number (post-checkin)
#
# For example:
#DEFAULT (echo ""; id; echo %s; date; cat) >> $CVSROOT/CVSROOT/commitlog
# or
#DEFAULT (echo ""; id; echo %{sVv}; date; cat) >> $CVSROOT/CVSROOT/commitlog

View File

@ -1,26 +0,0 @@
# Three different line formats are valid:
# key -a aliases...
# key [options] directory
# key [options] directory files...
#
# Where "options" are composed of:
# -i prog Run "prog" on "cvs commit" from top-level of module.
# -o prog Run "prog" on "cvs checkout" of module.
# -e prog Run "prog" on "cvs export" of module.
# -t prog Run "prog" on "cvs rtag" of module.
# -u prog Run "prog" on "cvs update" of module.
# -d dir Place module in directory "dir" instead of module name.
# -l Top-level directory only -- do not recurse.
#
# NOTE: If you change any of the "Run" options above, you'll have to
# release and re-checkout any working directories of these modules.
#
# And "directory" is a path to a directory relative to $CVSROOT.
#
# The "-a" option specifies an alias. An alias is interpreted as if
# everything on the right of the "-a" had been typed on the command line.
#
# You can encode a module within a module by using the special '&'
# character to interpose another module into the current module. This
# can be useful for creating a module that consists of many directories
# spread out over the entire source repository.

View File

@ -1,12 +0,0 @@
# The "notify" file controls where notifications from watches set by
# "cvs watch add" or "cvs edit" are sent. The first entry on a line is
# a regular expression which is tested against the directory that the
# change is being made to, relative to the $CVSROOT. If it matches,
# then the remainder of the line is a filter program that should contain
# one occurrence of %s for the user to notify, and information on its
# standard input.
#
# "ALL" or "DEFAULT" can be used in place of the regular expression.
#
# For example:
#ALL mail %s -s "CVS notification"

View File

@ -1,13 +0,0 @@
# The "rcsinfo" file is used to control templates with which the editor
# is invoked on commit and import.
#
# The first entry on a line is a regular expression which is tested
# against the directory that the change is being made to, relative to the
# $CVSROOT. For the first match that is found, then the remainder of the
# line is the name of the file that contains the template.
#
# If the repository name does not match any of the regular expressions in this
# file, the "DEFAULT" line is used, if it is specified.
#
# If the name "ALL" appears as a regular expression it is always used
# in addition to the first matching regex or "DEFAULT".

View File

@ -1,20 +0,0 @@
# The "taginfo" file is used to control pre-tag checks.
# The filter on the right is invoked with the following arguments:
#
# $1 -- tagname
# $2 -- operation "add" for tag, "mov" for tag -F, and "del" for tag -d
# $3 -- repository
# $4-> file revision [file revision ...]
#
# A non-zero exit of the filter program will cause the tag to be aborted.
#
# The first entry on a line is a regular expression which is tested
# against the directory that the change is being committed to, relative
# to the $CVSROOT. For the first match that is found, then the remainder
# of the line is the name of the filter to run.
#
# If the repository name does not match any of the regular expressions in this
# file, the "DEFAULT" line is used, if it is specified.
#
# If the name "ALL" appears as a regular expression it is always used
# in addition to the first matching regex or "DEFAULT".

View File

@ -1,21 +0,0 @@
# The "verifymsg" file is used to allow verification of logging
# information. It works best when a template (as specified in the
# rcsinfo file) is provided for the logging procedure. Given a
# template with locations for, a bug-id number, a list of people who
# reviewed the code before it can be checked in, and an external
# process to catalog the differences that were code reviewed, the
# following test can be applied to the code:
#
# Making sure that the entered bug-id number is correct.
# Validating that the code that was reviewed is indeed the code being
# checked in (using the bug-id number or a seperate review
# number to identify this particular code set.).
#
# If any of the above test failed, then the commit would be aborted.
#
# Actions such as mailing a copy of the report to each reviewer are
# better handled by an entry in the loginfo file.
#
# One thing that should be noted is the the ALL keyword is not
# supported. There can be only one entry that matches a given
# repository.

View File

@ -1,135 +0,0 @@
<!doctype linuxdoc system>
<article>
<title>MySQLdb FAQ
<author>Andy Dustman
<date>$Id$
<sect>Compiling <tt/_mysql.so/
<P>Here are some common errors that happen during the build.
This section covers UNIX/Linux problems only, as I don't do Windows.
<tt/.so/ is a dynamically loading library on Linux and most other UNIX
variants; a few use extensions other than <tt/.so/. Windows probably
uses <tt/.dll/.
<sect1>ImportError: libmysqlclient.so.6: cannot open shared object file:
No such file or directory
<P>
You have dynamic MySQL libraries, and by default, your compiler links
<tt/_mysql.so/ against these, but these are not on your loader path
when you start Python.
You have two basic options:
<p>
<enum>
<item>
Modify setup.py so that it links against the static library; see the comments.
<item>
If your linker supports a run-time loader path switch, you can set this
in setup.py as well.
<item>
Change your system environment so that the MySQL libraries are on
your loader path. With Linux, you can modify <tt>/etc/ld.so.conf</tt> (see
<tt/man ldconfig/ for more details) or you can add to or create the
<tt/LD_LIBRARY_PATH/ environment variable before starting Python, i.e.
<p><code>
LD_LIBRARY_PATH=/path/to/mysql/libs python ... # Bourne-ish shell
</code>
</enum>
<sect1>ImportError: ./_mysql.so: undefined symbol: PyLong_FromUnsignedLongLong
<p>
<tt/PyLong_FromUnsignedLongLong()/ first appears in Python 1.5.2, so you are
linking against an earlier version. You may also have more than one version
installed. Get Python 1.5.2 or newer from your vendor or python.org.
<sect1>ImportError: ./_mysql.so: undefined symbol: uncompress
<P>
It seems that MySQL-3.23 client libraries require libz for gzip
compression. setup.py should add this automatically.
<sect1>./_mysql.c:33: mysql.h: No such file or directory
<P>The include path (-I) to your MySQL include files is wrong; modify
setup.py. OR: You don't have the MySQL development stuff loaded. If you
are using the Red Hat RPMs, you need the <tt/MySQL-devel/ RPM to compile
<tt/_mysql.so/. However, if you link against the static MySQL
libraries (see above), you can install <tt/_mysql.so/ on a system
that does not have the MySQL client libraries (<tt/libmysqlclient/).
<sect1>I'm using Windows...
<P>Say no more.
<P>I don't use Windows. setup.py is supposed to work for building.
There may also be a link to some user-contributed binaries on the web site.
</sect1>
<sect>
Trouble with ZMySQLDA
<sect1>I installed MySQLdb but ZMySQLDA can't find it.
<p>Probably you installed a binary version of Zope which comes with
its own Python interpreter. You will have to compile MySQLdb against
that particular Python installation. Find out where it's python binary
lives and use that to run setup.py.
</sect1>
<sect1>I'm getting these stupid L's on my INTEGER columns.
<p>Yup, they have to be converted to long integers to avoid overflows
on UNSIGNED INT columns. Solutions: Use a <tt/fmt=%d/ attribute on your
<tt/dtml-var/ elements; Wait for Zope 2.4 which comes with Python 2.1
which doesn't add the L.
</sect1>
<sect1>I get SQL syntax errors on a LIMIT clause, and I didn't put in
a LIMIT clause!
<p>Z SQL Methods have a <tt/max_rows/ parameter. If this is set to a
non-zero value, ZMySQLDA adds a LIMIT clause to SELECT statements to
enforce this. This is a big performance gain, particularly if the
result set could be big. If it is interfering with something, set
<tt/max_rows/ to zero, and it won't add a LIMIT clause. In particular,
you will probably have to do this when inserting rows with
AUTO_INCREMENT columns, because typically you use SELECT thereafter to
get LAST_INSERT_ID(), and LIMIT can mess this up.
<sect>Using MySQLdb
<p>
MySQLdb is a
<htmlurl url="http://www.python.org/topics/database/DatabaseAPI-2.0.html"
name="Python Database API Specification 2.0"> database module, so you
should be familiar with the spec. Deviations from the spec are documented in the
<htmlurl url="http://dustman.net/andy/python/MySQLdb/doc/MySQLdb.html"
name="MySQLdb documentation">.
<sect1>cursor.rollback() always fails!
<p>MySQLdb now supports transactions if the server supports
transaction-safe tables (TSTs) and you are using them. If your server
doesn't support them, rollbacks will always fail, as they should,
because it can't do what you asked. Even if your server does support
them, rollbacks will fail if you modified any non-TST tables.
<p>OTOH, <tt/cursor.commit()/, which attempts to commit the
transaction to the database, <em/always/ succeeds, because MySQL
essentially is always in auto-commit mode (unless you told it
otherwise).
<sect1>How do I use some of the special MySQL features?
<P>First answer: Don't, if you can avoid it. Your program will not be
portable to other databases.
<P>Second answer: Nearly all the special API calls are implemented on
the _mysql connection object, and the MySQLdb connection object can
also invoke them. See the built-in module docs to find out what ones
are implemented, and the MySQL C API docs to see what they do.
<sect1>I still wanna use _mysql directly.
<p>Well, it <tt/may/ be appropriate in some cirumstances. ZMySQLDA
does this, because Zope's ZRDB module is an API in itself, and too
many layers of APIs tend to make a mess of things. Besides, it was
actually pretty easy to do it that way and it probably improves the
performance a bit.
<enum>
<item>
Read the MySQL docs, particularly the C API, for an overview.
<item>
Read the MySQLdb docs. This shows how the C API is transliterated
into Python. Plus some examples are in there.
<item>
Read the MySQLdb sources, particularly MySQLdb/cursors.py. That one
file contains most of the gory details, particularly in the
execute and _query methods.
</enum>
</article>

View File

@ -1,749 +0,0 @@
<!DOCTYPE linuxdoc system>
<article>
<title>MySQLdb: a Python interface for MySQL
<author>Andy Dustman
<date>$Id$
<abstract>MySQLdb is an thread-compatible interface to the popular
MySQL database server that provides the Python database API.
<sect>Introduction
<P>This module should be <ref id="MySQLmodule" name="mostly
compatible"> with an older interface written by Joe Skinner and
others. However, the older version is a) not thread-friendly (database
operations could cause all other threads to block), b) written for
MySQL 3.21 (does not compile against newer versions without patches),
c) apparently not actively maintained. MySQLdb is a completely new
module, distributed free of charge under the GNU Public License.
<p>
<sect1>Platforms
<p>
<sect2>Linux/UNIX
<p>
This module is developed on RedHat Linux (currently 7.1) for Intel. It
should build without much trouble on most platforms by using the
<tt/setup.py/ script. Supposedly it builds on MacOS X. Be aware that
you need the Distutils package which comes with Python 2.0. If you
don't have it (i.e. you have Python 1.5.2), you can find it over at
<htmlurl url="http://www.python.org/" name="www.python.org">.
<sect2>Windows (3.11, 95, 98, NT, 2000, CE, BSOD, XYZ, etc.)
<p>
Windows is <em/not/ a supported platform. However, the <tt/setup.py/
script reportedly gets the job done. There is probably a link on the
web page for getting a precompiled Windows installer from someone or
other. Be aware that this is a user-contributed package; the author
cannot help you with compiling and running under Windows.
<sect1>Python
<p>
MySQLdb requires Python 1.5.2 or newer. Earlier versions will not
work, because support for C <tt/long long/ is required by MySQL. If
you have an earlier version of Python, upgrade to 1.5.2 or beyond.
Current development is done with Python 2.2.1, but Python 1.5.2 will be
supported for the forseeable future.
<sect1>MySQL
<p>
<sect2>MySQL-3.22
<p>
Only versions 3.22.32 and up are guaranteed to work. Some older
versions may work; if you have an older version you should seriously
consider upgrading to get the bug fixes and particularly the security
updates.
MySQL-3.22 seems to have a problem trying to insert <tt/TIME/ values
with fractional seconds. Values like 12:56:13.00 are returned as
344:13:00, apparently interpreting the original input as 12 days, 56
hours, 13 minutes, 0 seconds. (12 days and 56 hours is 344 hours.) To
avoid this problem, use the <tt/DateTimeDelta/ type.
<sect2>MySQL-3.23
<p>
MySQL-3.23 is now stable (3.23.51 as of this writing). MySQLdb
supports transactions if the <em/server/ supports them. Even then,
this does not guarantee that transactions will work. For that, you
must use a transaction-safe table (TST). Current TSTs are BDB and
InnoDB. Note that MySQL
generally operates in <tt/AUTOCOMMIT/ mode by default, and MySQLdb
assumes that <tt/AUTOCOMMIT/ is on by default. To change this, use the
<tt/SET AUTOCOMMIT=0/ SQL statement.
<sect2>MySQL-4.0
<p>
MySQL-4.0 is supported, though still alpha.
<sect1>DateTime
<p>If you have the <htmlurl
url="http://www.lemburg.com/files/python/mxDateTime.html"
name="mx.DateTime"> package installed (recommended), MySQLdb will use
it for date-related objects. Otherwise, these will be returned to
Python as strings. You can also modify the type conversion
dictionary to return these as other object classes, if you prefer.
<sect1>MySQLmodule<label id="MySQLmodule">
<p>
MySQLmodule, the older MySQL interface by Joe Skinner and others, is
also a split C/Python interface. <tt/MySQL/, the C portion, has an
interface similar to perl's DBI internally. In addition, there is
Python portion, <tt/Mysqldb/, which provides a DB API v1.0 interface,
written by James Henstridge. MySQLdb-0.2.2 and up include
<tt/CompatMysqldb/, which is an adaptation of <tt/Mysqldb/ to
<tt/_mysql/. It should be considered experimental.
In contrast, MySQLdb's C portion, <tt><ref id="_mysql"></tt>, is
designed to mimic the MySQL C API in an object-oriented way; you
should not expect to move from <tt/MySQL/ to <tt/_mysql/ without a
fair amount of work. <tt><ref id="MySQLdb"></tt> provides a DB API
v2.0 interface, which has some changes from the v1.0 interface. Things
to watch out for in particular:
<table>
<tabular ca="foo">
Operation | Mysqldb | MySQLdb
@ Connecting | <tt>db = Mysqldb.Mysqldb("db@host user pass")</tt>
| <tt>db = MySQLdb.connect(db='db', host='host', user='user', passwd='pass')</tt>
@ Implicit cursor | <tt>db.execute(SQL)</tt> |
implicit cursors dropped from DB API v2.0; always use <tt>c = db.cursor()</tt>
@ Fetch row as dictionary | <tt>c.fetchDict()</tt>,
keys are "<em/table.column/" |
not standard; alternate cursor class <tt>DictCursor</tt>
provides a dictionary interface,
keys are "<em/column/" or "<em/table.column/" if there are two columns
with the same name; use SQL <tt/AS/ to rename fields.
@ Transactions | <tt>db.commit()</tt> and <tt>db.rollback()</tt>
both exist and silently do nothing <ref id="rollback" name="(danger!)">
| <tt>db.commit()</tt> and <tt>db.rollback()</tt> work if the MySQL
server can perform transactions; otherwise <tt>db.rollback()</tt>
always fails
<caption>Mysqldb to MySQLdb changes</tabular></table>
<sect1>Zope and ZMySQLDA
<p>I wrote a <htmlurl url="http://dustman.net/andy/python/ZMySQLDA"
name="ZMySQLDA"> for use with MySQLdb. It's adapted from ZOracleDA
from Digital Creations, makers of Zope.
<sect1>Documentation
<p>The web page documentation may be slightly ahead of the latest
release and may reflect features of the next release. <sect1>FAQs
<p>A FAQ is available at <htmlurl
url="http://dustman.net/andy/python/MySQLdb/faq/MySQLdb-FAQ.html">.
<sect>_mysql module<label id="_mysql">
<P>
If you want to write applications which are portable across databases,
avoid using this module directly. <tt>_mysql</tt> 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 <ref id="MySQLdb"> module. If you really need it, use the
standard MySQL docs and transliterate as necessary.
<sect1>MySQL C API translation
<p>
The MySQL C API has been wrapped in an object-oriented way. The only
MySQL data structures which are implemented are the <tt>MYSQL</tt>
(database connection handle) and <tt>MYSQL_RES</tt> (result handle)
types. In general, any function which takes <tt>MYSQL *mysql</tt> as
an argument is now a method of the connection object, and any function
which takes <tt>MYSQL_RES *result</tt> 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 <tt>mysql_</tt> prefix is dropped from the name. Most of the
<tt>conn</tt> methods listed are also available as MySQLdb Connection
object methods. Their use is non-portable.
<p>
Starting with MySQLdb-0.9.2, the connection and result objects are
subclassable types if you have at least Python-2.2.
<table>
<tabular ca="MySQL C API function mapping">
C API | <tt>_mysql</tt>
@ <tt>mysql_affected_rows()</tt> | <tt>conn.affected_rows()</tt>
@ <tt>mysql_close()</tt> | <tt>conn.close()</tt>
@ <tt>mysql_connect()</tt> | <tt>_mysql.connect()</tt>
@ <tt>mysql_data_seek()</tt> | <tt>result.data_seek()</tt>
@ <tt>mysql_debug()</tt> | <tt>_mysql.debug()</tt>
@ <tt>mysql_dump_debug_info</tt> | <tt>conn.dump_debug_info()</tt>
@ <tt>mysql_escape_string()</tt> | <tt>_mysql.escape_string()</tt>
@ <tt>mysql_fetch_row()</tt> | <tt>result.fetch_row()</tt>
@ <tt>mysql_get_client_info()</tt> | <tt>_mysql.get_client_info()</tt>
@ <tt>mysql_get_host_info()</tt> | <tt>conn.get_host_info()</tt>
@ <tt>mysql_get_proto_info()</tt> | <tt>conn.get_proto_info()</tt>
@ <tt>mysql_get_server_info()</tt> | <tt>conn.get_server_info()</tt>
@ <tt>mysql_info()</tt> | <tt>conn.info()</tt>
@ <tt>mysql_insert_id()</tt> | <tt>conn.insert_id()</tt>
@ <tt>mysql_num_fields()</tt> | <tt>result.num_fields()</tt>
@ <tt>mysql_num_rows()</tt> | <tt>result.num_rows()</tt>
@ <tt>mysql_options()</tt> | <tt>_mysql.connect()</tt>
@ <tt>mysql_ping()</tt> | <tt>conn.ping()</tt>
@ <tt>mysql_query()</tt> | <tt>conn.query()</tt>
@ <tt>mysql_real_connect()</tt> | <tt>_mysql.connect()</tt>
@ <tt>mysql_real_query()</tt> | <tt>conn.query()</tt>
@ <tt>mysql_real_escape_string()</tt> | <tt>conn.escape_string()</tt>
@ <tt>mysql_row_seek()</tt> | <tt>result.row_seek()</tt>
@ <tt>mysql_row_tell()</tt> | <tt>result.row_tell()</tt>
@ <tt>mysql_select_db()</tt> | <tt>conn.select_db()</tt>
@ <tt>mysql_stat()</tt> | <tt>conn.stat()</tt>
@ <tt>mysql_store_result()</tt> | <tt>conn.store_result()</tt>
@ <tt>mysql_thread_id()</tt> | <tt>conn.thread_id()</tt>
@ <tt>mysql_thread_safe_client()</tt> | <tt>conn.thread_safe_client()</tt>
@ <tt>mysql_use_result()</tt> | <tt>conn.use_result()</tt>
@ <tt>CLIENT_*</tt> | <tt>MySQLdb.constants.CLIENT.*</tt>
@ <tt>CR_*</tt> | <tt>MySQLdb.constants.CR.*</tt>
@ <tt>ER_*</tt> | <tt>MySQLdb.constants.ER.*</tt>
@ <tt>FIELD_TYPE_*</tt> | <tt>MySQLdb.constants.FIELD_TYPE.*</tt>
@ <tt>FLAG_*</tt> | <tt>MySQLdb.constants.FLAG.*</tt>
<caption>MySQL C API function mapping
</tabular>
</table>
<sect1>Some _mysql examples
<P>Okay, so you want to use <tt/_mysql/ anyway. Here are some examples.
<p>The simplest possible database connection is:
<code>
import _mysql
db=_mysql.connect()
</code>
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 <tt/USE/ a database.
Maybe this will work for you, if you have set up a configuration file,
i.e. (<tt>~/.my.cnf</tt>). Chances are you need to supply more
information.
<code>
db=_mysql.connect("localhost","joebob","moonpie","thangs")
</code>
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".
<P>We haven't even begun to touch upon all the parameters <tt/connect()/
can take.
For this reason, I prefer to use keyword parameters:
<code>
db=_mysql.connect(host="localhost",user="joebob",
passwd="moonpie",db="thangs")
</code>
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:
<code>
db=_mysql.connect(passwd="moonpie",db="thangs")
</code>
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):
<code>
db=_mysql.connect(host="outhouse",port=3307,passwd="moonpie",db="thangs")
</code>
<p>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.
<p>
There are some other parameters you can use, and most of them aren't
needed, except for one, which we'll get to momentarily. For the rest,
read the built-in documentation. Python 2.1's <tt/pydoc/ module is
great for this.
<P>So now you have an open connection as <tt/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
<tt/db.query()/:
<code>
db.query("""SELECT spam, eggs, sausage FROM breakfast
WHERE price < 5""")
</code>
There's no return value from this, but exceptions can be raised. The
exceptions are defined in a separate module, <tt/_mysql_exceptions/,
but <tt/_mysql/ exports them. Read the <htmlurl
url="http://www.python.org/peps/pep-0249.html"
name="DB API specification"> to find out what they are, or you can use
the catch-all <tt/MySQLError/.
<P>At this point your query has been executed and you need to get the
results. You have two options:
<code>
r=db.store_result()
# ...or...
r=db.use_result()
</code>
Both methods return a result object. What's the difference?
<tt/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 <tt/LIMIT/ clause to your
query, to limit the number of rows returned. The other is to use
<tt/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 <em/all/ the rows. Generally I
recommend using <tt/store_result()/ unless your result set is really
huge and you can't use <tt/LIMIT/ for some reason.
<P>Now, for actually getting real results:
<CODE>
>>> r.fetch_row()
(('3','2','0'),)
</CODE>
This might look a little odd. The first thing you should know is,
<tt/fetch_row()/ takes some additional parameters. The first one is,
how many rows (<tt/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 <tt/maxrows=0/, it returns all rows of the
result set. If you ever get an empty tuple back, you ran out of rows.
<p>The second parameter (<tt/how/) tells it how the row should be
represented. By default, it is zero which means, return as a tuple.
<tt/how=1/ means, return it as a dictionary, where the keys are the
column names, or <tt/table.column/ if there are two columns with the
same name (say, from a join). <tt/how=2/ means the same as <tt/how=1/
except that the keys are <em/always/ <tt/table.column/; this is for
compatibility with the old <tt/Mysqldb/ module.
<P>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 <tt/maxrows/.
<P>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, <tt/_mysql/ can do this for you. (And
<tt/MySQLdb/ does do this for you.) To have automatic type conversion
done, you need to create a type converter dictionary, and pass this
to <tt/connect()/ as the <tt/conv/ keyword parameter.
<p>The keys of <tt/conv/ should be MySQL column types, which in the
C API are <tt/FIELD_TYPE_*/. You can get these values like this:
<code>
from MySQLdb.constants import FIELD_TYPE
</code>
By default, any column type that can't be found in <tt/conv/ is
returned as a string, which works for a lot of stuff. For our
purposes, we probably want this:
<code>
my_conv = { FIELD_TYPE.LONG: int }
</code>
This means, if it's a <tt/FIELD_TYPE_LONG/, call the builtin
<tt/int()/ function on it. Note that <tt/FIELD_TYPE_LONG/ is an
<tt/INTEGER/ column, which corresponds to a C <tt/long/, which is also
the type used for a normal Python integer. But beware: If it's really
an <tt/UNSIGNED INTEGER/ column, this could cause overflows. For this
reason, <tt/MySQLdb/ actually uses <tt/long()/ to do the
conversion. But we'll ignore this potential problem for now.
<P>Then if you use <tt/db=_mysql.connect(conv=my_conv...)/, the
results will come back <tt/((3, 2, 0),)/, which is what you would
expect.
<sect>MySQLdb -- DB API interface<label id="MySQLdb">
<p>
MySQLdb is a thin Python wrapper around <tt><ref id="_mysql"></tt>
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 <tt>_mysql</tt> for the sake of efficiency.
<p>
The <htmlurl
url="http://www.python.org/topics/database/DatabaseAPI-2.0.html"
name="DB API specification"> should be your primary guide for using
this module. Only deviations from the spec and other
database-dependent things will be documented here.
<sect1>Functions and attributes
<P>Only a few top-level functions and attributes are defined within
MySQLdb.
<descrip>
<tag><label id="connect()">connect(parameters...)</tag> 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 <tt/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:
<descrip>
<tag>host</tag>
name of host to connect to. Default: use the local host
via a UNIX socket (where applicable)
<tag>user</tag>
user to authenticate as. Default: current effective user.
<tag>passwd</tag>
password to authenticate with. Default: no password.
<tag>db</tag>
database to use. Default: no default database.
<tag>port</tag>
TCP port of MySQL server. Default: standard port (3306).
<tag>unix_socket</tag>
location of UNIX socket. Default: use default location or
TCP for remote hosts.
<tag>conv</tag> type conversion dictionary.
Default: a copy of <tt/MySQLdb.converters.conversions/
<tag>compress</tag> Enable protocol compression. Default: no compression.
<tag>connect_timeout</tag> Abort if connect is not completed within
given number of seconds. Default: no timeout (?)
<tag>named_pipe</tag> Use a named pipe (Windows). Default: don't.
<tag>init_command</tag> Initial command to issue to server upon
connection. Default: Nothing.
<tag>read_default_file</tag> MySQL configuration file to read; see
the MySQL documentation for <tt/mysql_options()/.
<tag>read_default_group</tag> Default group to read; see the MySQL
documentation for <tt/mysql_options()/.
<tag>cursorclass</tag> cursor class that <tt/cursor()/ uses,
unless overridden. Default: <tt/MySQLdb.cursors.Cursor/.
<em/This must be a keyword parameter./
<tag>unicode</tag> If set, CHAR and VARCHAR columns are returned
as Unicode strings, using the specified character set.
None means to use a default encoding.
</descrip>
<tag>apilevel</tag>
String constant stating the supported DB API level. '2.0'
<tag>threadsafety</tag> Integer constant stating the level of thread
safety the interface supports. As of MySQLdb version 0.9.0, this
is set to 1, which means: Threads may share the module.
<p>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
<tt/mysql_store_result()/), it is complicated by SSCursor (which
uses <tt/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
<tt/COMMIT/ or <tt/ROLLBACK/ is executed by the Connection object.
Two threads 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. <p>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.
<p>For threaded applications, try using a connection pool.
This can be done using the
<htmlurl url="http://dustman.net/andy/python/Pool" name="Pool module">.
<tag>paramstyle</tag> 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.
Compatibility note: The older MySQLmodule uses a similar
parameter scheme, but requires that quotes be placed around
format strings which will contain strings, dates, and similar
character data. This is not necessary for MySQLdb. It is
recommended that %s (and not '%s') be used for all parameters,
regardless of type. The interface performs all necessary
quoting.
Note that any literal percent signs in the query string passed
to execute() must be escaped, i.e. %%.
<tag><label id="conversions">conv</tag> A dictionary mapping MySQL types
(from <TT>FIELD_TYPE.*</TT>) to callable Python objects (usually
functions) which convert from a string to the desired type; and
mapping Python types to callable Python objects which convert
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 <tt>MySQLdb.converters.conversions</tt>. The dictionary
includes some of the factory functions from the
<tt>DateTime</tt> module, if it is available. Several
non-standard types are returned as strings,
which is how MySQL returns all columns. For more details, see
the built-in module documentation.
<P>As of MySQL-3.23, MySQL supports different character sets in the
server, and a new quoting function, <tt/mysql_real_escape_string()/.
This requires the string quoting function to be a method bound to
the connection object. MySQLdb handles this for you automatically.
However, if you feel the need to do something goofy with your strings,
you will have to modify the dictionary after opening the connection.
In practice, you should never have to worry about this. This also
applies to Unicode strings, if enabled.
</descrip>
<sect1>Connection Objects
<P>Connection objects are returned by the <tt>connect()</tt> function.
<descrip>
<tag>commit()</tag> If the database and the tables support
transactions, this commits the current transaction; otherwise
this method successfully does nothing.
<tag><label id="rollback">rollback()</tag> If the database and tables
support transactions, this rolls back (cancels) the current
transaction; otherwise a <tt>NotSupportedError</tt> is raised.
Compatibility note: The older <ref id="MySQLmodule"> defines this method,
which sucessfully does nothing. This is dangerous behavior, as a
successful rollback indicates that the current transaction was
backed out, which is not true, and fails to notify the
programmer that the database now needs to be cleaned up by other
means.
<tag>cursor([cursorclass])</tag> 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 <tt/Cursor/ class. Also see
the additional supplied cursor classes in the <ref id="usage">
section.
<tag>begin()</tag> Explicitly start a transaction. Normally you do
not need to use this: Executing a query implicitly starts a new
transaction if one is not in progress. If AUTOCOMMIT is on, you
can use <tt/begin()/ to temporarily turn it off. AUTOCOMMIT will
resume after the next <tt/commit()/ or <tt/rollback/.
</descrip>
<p>There are many more methods defined on the connection object which
are MySQL-specific. For more information on them, consult the internal
documentation using <tt/pydoc/.
<sect1>Cursor Objects
<p>
<descrip>
<tag>callproc()</tag>
Not implemented.
<tag>close()</tag>
Closes the cursor. Future operations raise <tt/ProgrammingError/.
If you are using <ref id="SSCursor" name="server-side cursors">,
it is very important to close the cursor when you are done with
it and before creating a new one.
<tag/insert_id()/
Returns the last <tt/AUTO_INCREMENT/ field value inserted
into the database. (Non-standard)
<tag/info()/ Returns some information about the last query. Normally
you don't need to check this. With the default cursor, any MySQL
warnings cause <tt/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 <tt/mysql_info()/. (Non-standard)
<tag>setinputsizes()</tag>
Does nothing, successfully.
<tag>setoutputsizes()</tag>
Does nothing, successfully.
<tag>nextset()</tag>
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 presently doesn't support multiple result sets.
</descrip>
<sect1>Some examples
<p>The <tt/connect()/ method works nearly the same as with <tt/_mysql/:
<code>
import MySQLdb
db=MySQLdb.connect(passwd="moonpie",db="thangs")
</code>
To perform a query, you first need a cursor, and then you can execute
queries on it.
<code>
c=db.cursor()
max_price=5
c.execute("""SELECT spam, eggs, sausage FROM breakfast
WHERE price < %s""", (max_price,))
</code>
In this example, <tt/max_price=5/ Why, then, use <tt/%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".
<p>Why the tuple? Because the DB API requires you to pass in any
parameters as a sequence.
<p>And now, the results:
<CODE>
>>> c.fetchone()
(3L, 2L, 0L)
</CODE>
Quite unlike the <tt/_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?
<P>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. Prior to
Python 1.6, long integers retained the L when converted to strings
with <tt/str()/. In 1.6 and later, <tt/str()/ does not include the L.
Of course, the L always prints when using <tt/repr()/, which is what
has happened here.
<P>When you are finished with a transaction, you should execute either
<tt/db.commit()/ or <tt/db.rollback()/. If your server and tables
don't support transactions, <tt/commit()/ will still work, but
<tt/rollback()/ will raise an exception. Note carefully that these are
methods of the <em/connection/ and not methods of the <em/cursor/,
even though <tt/c.execute(...)/ is what started the transaction.
<P>If you wanted more rows, you could use <tt/c.fetchmany(n)/ or
<tt/c.fetchall()/. These do exactly what you think they do. On
<tt/c.fetchmany(n)/, the <tt/n/ is optional and defaults to
<tt/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.
<P>Note that in contrast to the above, <tt/c.fetchone()/ returns <tt/None/
when there are no more rows to fetch.
<P>The only other method you are very likely to use is when you have to
do a multi-row insert:
<CODE>
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 )
] )
</CODE>
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
<tt/%s/. And also note that we only included format strings for one
row. MySQLdb picks those out and duplicates them for each row.
<footnote>Baked beans are off!</footnote>
<sect>Using and extending<label id="usage">
<P>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 <tt><ref id="connect()"></tt> 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.
For an example of this, see the author's
<htmlurl url="http://dustman.net/andy/python"
name="SQLDict module">, which allows standard queries to be
defined and accessed using an object which looks like a
dictionary, and reads/writes user-defined objects.
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:
<p>
<descrip>
<tag>BaseCursor</tag> The base class for Cursor objects.
This does not raise Warnings.
<tag>CursorWarningMixIn</tag> Causes the Warning exception to be raised
on queries which produce warnings.
<tag>CursorStoreResultMixIn</tag> Causes the Cursor to use the
<tt>mysql_store_result()</tt> function to get the query result. The
entire result set is stored on the client side.
<tag><label id="SSCursor">CursorUseResultMixIn</tag> Causes the cursor to use the
<tt>mysql_use_result()</tt> function to get the query result. The
result set is stored on the server side and is transferred row by row
using fetch operations.
<tag>CursorTupleRowsMixIn</tag> Causes the cursor to return rows
as a tuple of the column values.
<tag>CursorDictRowsMixIn</tag> 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 <em/table.column/.
This can be avoided by using
the SQL <tt>AS</TT> keyword. (This is yet-another reason not to use
<tt/*/ in SQL queries, particularly where <tt/JOIN/ is involved.
<tag>Cursor</tag> The default cursor class. This class is composed
of <tt>CursorWarningMixIn, CursorStoreResultMixIn, CursorTupleRowsMixIn,</tt>
and <tt>BaseCursor</tt>, i.e. it raises <tt>Warning</tt>, uses
<tt>mysql_store_result()</tt>, and returns rows as tuples.
<tag>DictCursor</tag> Like <tt/Cursor/ except it returns rows as
dictionaries.
<tag>SSCursor</tag> A "server-side" cursor. Like <tt/Cursor/ but uses
<tt/CursorUseResultMixIn/.
Use only if you are dealing with potentially large result sets.
<tag/SSDictCursor/ Like <tt/SSCursor/ except it returns rows as
dictionaries.
<tag/XXXCursorNW/ Cursors with the "NW" suffix do not raise Warnings.
</descrip>
<p>For an example of how to use these classes,
read the code. If you need something more exotic than this,
you will have to roll your own.
</article>

View File

@ -1,66 +0,0 @@
Z MySQL DA Releases
2.0.9
Allow the connection string to work without a specified database.
Wrap queries with a lock to prevent multiple threads from using
the connection simultaneously (this may or may not be happening).
If transactional, then there is an additional transaction lock,
acquired at the beginning of the transaction and released when
either finished or aborted.
A named lock can be specified by inserting *LOCKNAME at the start
of the connection string. This is probably best used only if you
must use non-transactional tables.
Some stuff will be logged as an error when bad things happen
during the transaction manager hooks.
2.0.8
More information about columns is available from the table
browser. This is primarily to support SQL Blender.
DECIMAL and NUMERIC columns now returned as floating-point numbers
(was string). This has also been fixed in MySQLdb-0.9.1, but the
fix is included here just in case you don't upgrade. Upgrading is
a good idea anyway, because some memory-related bugs are fixed,
particularly if using Zope 2.4 and Python 2.1.
2.0.7
Transaction support tweaked some more. A plus (+) or minus (-)
at the beginning of the connection string will force transactions
on or off respectively. By default, transactions are enabled if
the server supports them. Beware: If you are using non-TST tables
on a server that supports transactions, you should probably force
transactions off.
2.0.6
This version finally should have all the transaction support
working correctly. If your MySQL server supports transactions,
i.e. it has at least one transaction-safe table (TST) handler,
transactions are enabled automatically. If transactions are
enabled, rollbacks (aborts) fail if any non-TST tables were
modified.
2.0.5
Transactions don't really work right in this and prior versions.
2.0.4
INT columns, whether UNSIGNED or not, are returned as Python
long integers to avoid overflows. Python-1.5.2 adds an 'L' to
the end of long integers when printing. Later versions do not.
As a workaround, use affected columns with a format string,
i.e. '<dtml-var x fmt="%d">'.
2.0.0
This is the first version of the database adapter using MySQLdb
for Zope. This database adapter is based on the Z DCOracle DA
version 2.2.0.

View File

@ -1,161 +0,0 @@
##############################################################################
#
# Zope Public License (ZPL) Version 1.0
# -------------------------------------
#
# Copyright (c) Digital Creations. All rights reserved.
#
# This license has been certified as Open Source(tm).
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions in source code must retain the above copyright
# notice, this list of conditions, and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions, and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# 3. Digital Creations requests that attribution be given to Zope
# in any manner possible. Zope includes a "Powered by Zope"
# button that is installed by default. While it is not a license
# violation to remove this button, it is requested that the
# attribution remain. A significant investment has been put
# into Zope, and this effort will continue if the Zope community
# continues to grow. This is one way to assure that growth.
#
# 4. All advertising materials and documentation mentioning
# features derived from or use of this software must display
# the following acknowledgement:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# In the event that the product being advertised includes an
# intact Zope distribution (with copyright and license included)
# then this clause is waived.
#
# 5. Names associated with Zope or Digital Creations must not be used to
# endorse or promote products derived from this software without
# prior written permission from Digital Creations.
#
# 6. Modified redistributions of any form whatsoever must retain
# the following acknowledgment:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# Intact (re-)distributions of any official Zope release do not
# require an external acknowledgement.
#
# 7. Modifications are encouraged but must be packaged separately as
# patches to official Zope releases. Distributions that do not
# clearly separate the patches from the original work must be clearly
# labeled as unofficial distributions. Modifications which do not
# carry the name Zope may be packaged in any form, as long as they
# conform to all of the clauses above.
#
#
# Disclaimer
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
#
# This software consists of contributions made by Digital Creations and
# many individuals on behalf of Digital Creations. Specific
# attributions are listed in the accompanying credits file.
#
##############################################################################
database_type='MySQL'
__doc__='''%s Database Connection
$Id$''' % database_type
__version__='$Revision$'[11:-2]
import os
from db import DB
import Shared.DC.ZRDB.Connection, sys, DABase
from App.Dialogs import MessageDialog
from Globals import HTMLFile
from ImageFile import ImageFile
from ExtensionClass import Base
from DateTime import DateTime
manage_addZMySQLConnectionForm=HTMLFile('connectionAdd',globals())
def manage_addZMySQLConnection(self, id, title,
connection_string,
check=None, REQUEST=None):
"""Add a DB connection to a folder"""
self._setObject(id, Connection(id, title, connection_string, check))
if REQUEST is not None: return self.manage_main(self,REQUEST)
class Connection(DABase.Connection):
" "
database_type=database_type
id='%s_database_connection' % database_type
meta_type=title='Z %s Database Connection' % database_type
icon='misc_/Z%sDA/conn' % database_type
manage_properties=HTMLFile('connectionEdit', globals())
def factory(self): return DB
def connect(self,s):
try: self._v_database_connection.close()
except: pass
self._v_connected=''
DB=self.factory()
## No try. DO.
self._v_database_connection=DB(s)
self._v_connected=DateTime()
return self
def sql_quote__(self, v, escapes={}):
return self._v_database_connection.string_literal(v)
classes=('DA.Connection',)
meta_types=(
{'name':'Z %s Database Connection' % database_type,
'action':'manage_addZ%sConnectionForm' % database_type,
},
)
folder_methods={
'manage_addZMySQLConnection':
manage_addZMySQLConnection,
'manage_addZMySQLConnectionForm':
manage_addZMySQLConnectionForm,
}
__ac_permissions__=(
('Add Z MySQL Database Connections',
('manage_addZMySQLConnectionForm',
'manage_addZMySQLConnection')),
)
misc_={'conn': ImageFile(
os.path.join('Shared','DC','ZRDB','www','DBAdapterFolder_icon.gif'))}
for icon in ('table', 'view', 'stable', 'what',
'field', 'text','bin','int','float',
'date','time','datetime'):
misc_[icon]=ImageFile(os.path.join('icons','%s.gif') % icon, globals())

View File

@ -1,250 +0,0 @@
##############################################################################
#
# Zope Public License (ZPL) Version 1.0
# -------------------------------------
#
# Copyright (c) Digital Creations. All rights reserved.
#
# This license has been certified as Open Source(tm).
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions in source code must retain the above copyright
# notice, this list of conditions, and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions, and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# 3. Digital Creations requests that attribution be given to Zope
# in any manner possible. Zope includes a "Powered by Zope"
# button that is installed by default. While it is not a license
# violation to remove this button, it is requested that the
# attribution remain. A significant investment has been put
# into Zope, and this effort will continue if the Zope community
# continues to grow. This is one way to assure that growth.
#
# 4. All advertising materials and documentation mentioning
# features derived from or use of this software must display
# the following acknowledgement:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# In the event that the product being advertised includes an
# intact Zope distribution (with copyright and license included)
# then this clause is waived.
#
# 5. Names associated with Zope or Digital Creations must not be used to
# endorse or promote products derived from this software without
# prior written permission from Digital Creations.
#
# 6. Modified redistributions of any form whatsoever must retain
# the following acknowledgment:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# Intact (re-)distributions of any official Zope release do not
# require an external acknowledgement.
#
# 7. Modifications are encouraged but must be packaged separately as
# patches to official Zope releases. Distributions that do not
# clearly separate the patches from the original work must be clearly
# labeled as unofficial distributions. Modifications which do not
# carry the name Zope may be packaged in any form, as long as they
# conform to all of the clauses above.
#
#
# Disclaimer
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
#
# This software consists of contributions made by Digital Creations and
# many individuals on behalf of Digital Creations. Specific
# attributions are listed in the accompanying credits file.
#
##############################################################################
__doc__='''Database Connection
$Id$'''
__version__='$Revision$'[11:-2]
import Shared.DC.ZRDB.Connection, sys
from Globals import HTMLFile
from ImageFile import ImageFile
from ExtensionClass import Base
import Acquisition
class Connection(Shared.DC.ZRDB.Connection.Connection):
_isAnSQLConnection=1
manage_options=Shared.DC.ZRDB.Connection.Connection.manage_options+(
{'label': 'Browse', 'action':'manage_browse'},
# {'label': 'Design', 'action':'manage_tables'},
)
manage_tables=HTMLFile('tables',globals())
manage_browse=HTMLFile('browse',globals())
info=None
def tpValues(self):
#if hasattr(self, '_v_tpValues'): return self._v_tpValues
r=[]
# self._v_tables=tables=TableBrowserCollection()
#tables=tables.__dict__
c=self._v_database_connection
try:
for d in c.tables(rdb=0):
try:
name=d['TABLE_NAME']
b=TableBrowser()
b.__name__=name
b._d=d
b._c=c
#b._columns=c.columns(name)
b.icon=table_icons.get(d['TABLE_TYPE'],'text')
r.append(b)
# tables[name]=b
except:
# print d['TABLE_NAME'], sys.exc_type, sys.exc_value
pass
finally: pass #print sys.exc_type, sys.exc_value
#self._v_tpValues=r
return r
def __getitem__(self, name):
if name=='tableNamed':
if not hasattr(self, '_v_tables'): self.tpValues()
return self._v_tables.__of__(self)
raise KeyError, name
def manage_wizard(self, tables):
" "
def manage_join(self, tables, select_cols, join_cols, REQUEST=None):
"""Create an SQL join"""
def manage_insert(self, table, cols, REQUEST=None):
"""Create an SQL insert"""
def manage_update(self, table, keys, cols, REQUEST=None):
"""Create an SQL update"""
class TableBrowserCollection(Acquisition.Implicit):
"Helper class for accessing tables via URLs"
class Browser(Base):
def __getattr__(self, name):
try: return self._d[name]
except KeyError: raise AttributeError, name
class values:
def len(self): return 1
def __getitem__(self, i):
try: return self._d[i]
except AttributeError: pass
self._d=self._f()
return self._d[i]
class TableBrowser(Browser, Acquisition.Implicit):
icon='what'
Description=check=''
info=HTMLFile('table_info',globals())
menu=HTMLFile('table_menu',globals())
def tpValues(self):
v=values()
v._f=self.tpValues_
return v
def tpValues_(self):
r=[]
tname=self.__name__
for d in self._c.columns(tname):
b=ColumnBrowser()
b._d=d
b.icon=d['Icon']
b.TABLE_NAME=tname
r.append(b)
return r
def tpId(self): return self._d['TABLE_NAME']
def tpURL(self): return "Table/%s" % self._d['TABLE_NAME']
def Name(self): return self._d['TABLE_NAME']
def Type(self): return self._d['TABLE_TYPE']
manage_designInput=HTMLFile('designInput',globals())
def manage_buildInput(self, id, source, default, REQUEST=None):
"Create a database method for an input form"
args=[]
values=[]
names=[]
columns=self._columns
for i in range(len(source)):
s=source[i]
if s=='Null': continue
c=columns[i]
d=default[i]
t=c['Type']
n=c['Name']
names.append(n)
if s=='Argument':
values.append("<!--#sql-value %s type=%s-->'" %
(n, vartype(t)))
a='%s%s' % (n, boboType(t))
if d: a="%s=%s" % (a,d)
args.append(a)
elif s=='Property':
values.append("<!--#sql-value %s type=%s-->'" %
(n, vartype(t)))
else:
if isStringType(t):
if find(d,"\'") >= 0: d=join(split(d,"\'"),"''")
values.append("'%s'" % d)
elif d:
values.append(str(d))
else:
raise ValueError, (
'no default was given for <em>%s</em>' % n)
class ColumnBrowser(Browser):
icon='field'
def check(self):
return ('\t<input type=checkbox name="%s.%s">' %
(self.TABLE_NAME, self._d['Name']))
def tpId(self): return self._d['Name']
def tpURL(self): return "Column/%s" % self._d['Name']
def Description(self): return " %s" % self._d['Description']
table_icons={
'TABLE': 'table',
'VIEW':'view',
'SYSTEM_TABLE': 'stable',
}

View File

@ -1,4 +0,0 @@
* MySQL-python-0.9.2 or newer
* Zope-2.3.0 or newer

View File

@ -1,43 +0,0 @@
Z MySQL DA
This is the Z MySQL database adapter product for the
Z Object Publishing Environment.
** NOTE **
Note that the Z MySQL database adapter is compatible with MySQL
versions 3.22 and later (including MySQL 3.23).
** IMPORTANT **
This product is distributed as a NON-BINARY release!
This product requires compiled Python extensions that are
NOT included as a binary with this release. You must build
or install the required extensions using the instructions
below before the product will work properly!
Installation
The Z MySQL database adapter uses the MySQLdb package.
This must be installed before you can use the Z MySQL DA.
You can find this at::
http://sourceforge.net/projects/mysql-python
You need at least version 0.9.0. If you are compiling this
yourself, you must use the same python executable as your
Zope installation uses, otherwise Zope will not find it.
Connection Strings
The connection string used for Z MySQL Database Connection
are of the form::
database[@host[:port]] [user [password [unix_socket]]]
or typically just::
database user password
to use the default server.

View File

@ -1 +0,0 @@
ZMySQLDA 2.0.9

View File

@ -1,107 +0,0 @@
##############################################################################
#
# Zope Public License (ZPL) Version 1.0
# -------------------------------------
#
# Copyright (c) Digital Creations. All rights reserved.
#
# This license has been certified as Open Source(tm).
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions in source code must retain the above copyright
# notice, this list of conditions, and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions, and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# 3. Digital Creations requests that attribution be given to Zope
# in any manner possible. Zope includes a "Powered by Zope"
# button that is installed by default. While it is not a license
# violation to remove this button, it is requested that the
# attribution remain. A significant investment has been put
# into Zope, and this effort will continue if the Zope community
# continues to grow. This is one way to assure that growth.
#
# 4. All advertising materials and documentation mentioning
# features derived from or use of this software must display
# the following acknowledgement:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# In the event that the product being advertised includes an
# intact Zope distribution (with copyright and license included)
# then this clause is waived.
#
# 5. Names associated with Zope or Digital Creations must not be used to
# endorse or promote products derived from this software without
# prior written permission from Digital Creations.
#
# 6. Modified redistributions of any form whatsoever must retain
# the following acknowledgment:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# Intact (re-)distributions of any official Zope release do not
# require an external acknowledgement.
#
# 7. Modifications are encouraged but must be packaged separately as
# patches to official Zope releases. Distributions that do not
# clearly separate the patches from the original work must be clearly
# labeled as unofficial distributions. Modifications which do not
# carry the name Zope may be packaged in any form, as long as they
# conform to all of the clauses above.
#
#
# Disclaimer
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
#
# This software consists of contributions made by Digital Creations and
# many individuals on behalf of Digital Creations. Specific
# attributions are listed in the accompanying credits file.
#
##############################################################################
__doc__='''Generic Database Adapter Package Registration
$Id$'''
__version__='$Revision$'[11:-2]
import sys, string
import DA
methods=DA.folder_methods
misc_=DA.misc_
def initialize(context):
context.registerClass(
DA.Connection,
permission='Add Z MySQL Database Connections',
constructors=(DA.manage_addZMySQLConnectionForm,
DA.manage_addZMySQLConnection),
)
context.registerHelp()
context.registerHelpTitle('ZMySQLDA')

View File

@ -1,12 +0,0 @@
<html>
<head><title><!--#var title_or_id--> tables</title></head>
<body bgcolor="#FFFFFF" link="#000099" vlink="#555555" alink="#77003B">
<!--#var manage_tabs-->
<!--#tree header=info-->
<IMG SRC="<!--#var SCRIPT_NAME-->/misc_/ZMySQLDA/<!--#var icon-->"
ALT="<!--#var Type-->" BORDER="0">
<!--#var Name--><!--#var Description-->
<!--#/tree-->
</body>
</html>

View File

@ -1,92 +0,0 @@
<html>
<head><title>Add Z MySQL Database Connection</title></head>
<body bgcolor="#FFFFFF" link="#000099" vlink="#555555" alink="#77003B">
<h2>Add Z MySQL Database Connection</h2>
<form action="manage_addZMySQLConnection" method="POST">
<table cellspacing="2">
<tr>
<th align="LEFT" valign="TOP">Id</th>
<td align="LEFT" valign="TOP">
<input type="TEXT" name="id" size="40"
value="MySQL_database_connection">
</td>
</tr>
<tr>
<th align="LEFT" valign="TOP"><em>Title</em></th>
<td align="LEFT" valign="TOP">
<input type="TEXT" name="title" size="40"
value="Z MySQL Database Connection">
</td>
</tr>
<tr>
<th align="LEFT" valign="TOP">
Enter a Database Connection String
<a href="#1"><sup>1</sup></a></th>
<td align="LEFT" valign="TOP">
<input type="TEXT" name="connection_string" size="40">
</td>
</tr>
<tr>
<th align="LEFT" valign="TOP">Connect immediately</th>
<td align="LEFT" valign="TOP">
<input name="check" type="CHECKBOX" value="YES" CHECKED>
</td>
</tr>
<tr>
<td></td>
<td><br><input type="SUBMIT" value="Add"></td>
</tr>
</table>
</form>
<dt><a hname="1"><sup>1</sup></a> Connection Strings</dt>
<dd>
<p>
The connection string used for Z MySQL Database Connection
is of the form:
<pre>
[*lock] [+/-][database][@host[:port]] [user [password [unix_socket]]]
</pre>
or typically:
<pre>
database user password
</pre>
to use a MySQL server on localhost via the standard UNIX socket.
Only specify host if the server is on a remote system. You can
use a non-standard port, if necessary. Hint: To use a non-standard
port on the local system, use 127.0.0.1 for the host instead of
localhost.
<p>
Either a database or a host or both must be specified.
<p>
If the UNIX socket is in a non-standard location, you can specify
the full path to it after the password.
<p>
A '-' in front of the database tells ZMySQLDA to not use Zope's
Transaction Manager, even if the server supports transactions. A
'+' in front of the database tells ZMySQLDA that it must use
transactions; an exception will be raised if they are not
supported by the server. If neither '-' or '+' are present, then
transactions will be enabled if the server supports them. If you
are using non-transaction safe tables (TSTs) on a server that
supports TSTs, use '-'. If you require transactions, use '+'. If
you aren't sure, don't use either.
<p>
*<em>lock</em> at the begining of the connection string means to
psuedo-transactional. When the transaction begins, it will acquire
a lock on the server named <em>lock</em> (i.e. MYLOCK). When the
transaction commits, the lock will be released. If the transaction
is aborted and restarted, which can happen due to a ConflictError,
you'll get an error in the logs, and inconsistent data. In this
respect, it's equivalent to transactions turned off.
<p>
Transactions are highly recommended. Using a named lock in
conjunctions with transactions is probably pointless.
</dd></dl>
</body>
</html>

View File

@ -1,48 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html lang="en">
<head><title>Edit <dtml-var title_or_id></title></head>
<body bgcolor="#FFFFFF" link="#000099" vlink="#555555" alink="#77003B">
<dtml-var manage_tabs>
<h2>Edit <dtml-var title_or_id></h2>
<form action="manage_edit" method="POST">
<table cellspacing="2">
<tr>
<th align="LEFT" valign="TOP">Id</th>
<td align="LEFT" valign="TOP"><dtml-var id></td>
</tr>
<tr>
<th align="LEFT" valign="TOP"><em>Title</em></th>
<td align="LEFT" valign="TOP">
<input type="TEXT" name="title" size="40"
value="<dtml-var title html_quote>">
</td>
</tr>
<tr>
<th align="LEFT" valign="TOP">Database Connection String</th>
<td align="LEFT" valign="TOP">
<input type="TEXT" name="connection_string" size="40"
value="<dtml-var connection_string html_quote>">
</td>
</tr>
<tr>
<th align="LEFT" valign="TOP">Connect immediately</th>
<td align="LEFT" valign="TOP">
<input name="check" type="CHECKBOX" value="YES" CHECKED>
</td>
</tr>
<tr>
<td></td>
<td><br><input type="SUBMIT" value="Change"></td>
</tr>
</table>
</form>
</body>
</html>

View File

@ -1,405 +0,0 @@
##############################################################################
#
# Zope Public License (ZPL) Version 1.0
# -------------------------------------
#
# Copyright (c) Digital Creations. All rights reserved.
#
# This license has been certified as Open Source(tm).
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions in source code must retain the above copyright
# notice, this list of conditions, and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions, and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# 3. Digital Creations requests that attribution be given to Zope
# in any manner possible. Zope includes a "Powered by Zope"
# button that is installed by default. While it is not a license
# violation to remove this button, it is requested that the
# attribution remain. A significant investment has been put
# into Zope, and this effort will continue if the Zope community
# continues to grow. This is one way to assure that growth.
#
# 4. All advertising materials and documentation mentioning
# features derived from or use of this software must display
# the following acknowledgement:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# In the event that the product being advertised includes an
# intact Zope distribution (with copyright and license included)
# then this clause is waived.
#
# 5. Names associated with Zope or Digital Creations must not be used to
# endorse or promote products derived from this software without
# prior written permission from Digital Creations.
#
# 6. Modified redistributions of any form whatsoever must retain
# the following acknowledgment:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# Intact (re-)distributions of any official Zope release do not
# require an external acknowledgement.
#
# 7. Modifications are encouraged but must be packaged separately as
# patches to official Zope releases. Distributions that do not
# clearly separate the patches from the original work must be clearly
# labeled as unofficial distributions. Modifications which do not
# carry the name Zope may be packaged in any form, as long as they
# conform to all of the clauses above.
#
#
# Disclaimer
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
#
# This software consists of contributions made by Digital Creations and
# many individuals on behalf of Digital Creations. Specific
# attributions are listed in the accompanying credits file.
#
##############################################################################
'''$Id$'''
__version__='$Revision$'[11:-2]
import _mysql
from _mysql_exceptions import OperationalError, NotSupportedError
MySQLdb_version_required = (0,9,2)
_v = getattr(_mysql, 'version_info', (0,0,0))
if _v < MySQLdb_version_required:
raise NotSupportedError, \
"ZMySQLDA requires at least MySQLdb %s, %s found" % \
(MySQLdb_version_required, _v)
from MySQLdb.converters import conversions
from MySQLdb.constants import FIELD_TYPE, CR, CLIENT
from Shared.DC.ZRDB.TM import TM
from DateTime import DateTime
from zLOG import LOG, ERROR, INFO
import string, sys
from string import strip, split, find, upper, rfind
from time import time
hosed_connection = (
CR.SERVER_GONE_ERROR,
CR.SERVER_LOST
)
key_types = {
"PRI": "PRIMARY KEY",
"MUL": "INDEX",
"UNI": "UNIQUE",
}
field_icons = "bin", "date", "datetime", "float", "int", "text", "time"
icon_xlate = {
"varchar": "text", "char": "text",
"enum": "what", "set": "what",
"double": "float", "numeric": "float",
"blob": "bin", "mediumblob": "bin", "longblob": "bin",
"tinytext": "text", "mediumtext": "text",
"longtext": "text", "timestamp": "datetime",
"decimal": "float", "smallint": "int",
"mediumint": "int", "bigint": "int",
}
type_xlate = {
"double": "float", "numeric": "float",
"decimal": "float", "smallint": "int",
"mediumint": "int", "bigint": "int",
"int": "int", "float": "float",
"timestamp": "datetime", "datetime": "datetime",
"time": "datetime",
}
def _mysql_timestamp_converter(s):
if len(s) < 14:
s = s + "0"*(14-len(s))
parts = map(int, (s[:4],s[4:6],s[6:8],
s[8:10],s[10:12],s[12:14]))
return DateTime("%04d-%02d-%02d %02d:%02d:%02d" % tuple(parts))
def DateTime_or_None(s):
try: return DateTime(s)
except: return None
def int_or_long(s):
try: return int(s)
except: return long(s)
"""Locking strategy:
The minimum that must be done is a mutex around a query, store_result
sequence. When using transactions, the mutex must go around the
entire transaction."""
class DB(TM):
Database_Connection=_mysql.connect
Database_Error=_mysql.Error
defs={
FIELD_TYPE.CHAR: "i", FIELD_TYPE.DATE: "d",
FIELD_TYPE.DATETIME: "d", FIELD_TYPE.DECIMAL: "n",
FIELD_TYPE.DOUBLE: "n", FIELD_TYPE.FLOAT: "n", FIELD_TYPE.INT24: "i",
FIELD_TYPE.LONG: "i", FIELD_TYPE.LONGLONG: "l",
FIELD_TYPE.SHORT: "i", FIELD_TYPE.TIMESTAMP: "d",
FIELD_TYPE.TINY: "i", FIELD_TYPE.YEAR: "i",
}
conv=conversions.copy()
conv[FIELD_TYPE.LONG] = int_or_long
conv[FIELD_TYPE.DATETIME] = DateTime_or_None
conv[FIELD_TYPE.DATE] = DateTime_or_None
conv[FIELD_TYPE.DECIMAL] = float
del conv[FIELD_TYPE.TIME]
_p_oid=_p_changed=_registered=None
def __init__(self,connection):
from thread import allocate_lock
self.connection=connection
self.kwargs = kwargs = self._parse_connection_string(connection)
self.db=apply(self.Database_Connection, (), kwargs)
LOG("ZMySQLDA", INFO, "Opened new connection %s: %s" \
% (self.db, connection))
transactional = self.db.server_capabilities & CLIENT.TRANSACTIONS
if self._try_transactions == '-':
transactional = 0
elif not transactional and self._try_transactions == '+':
raise NotSupportedError, "transactions not supported by this server"
self._use_TM = self._transactions = transactional
if self._mysql_lock:
self._use_TM = 1
if self._use_TM:
self._tlock = allocate_lock()
self._lock = allocate_lock()
def __del__(self):
LOG("ZMySQLDA", INFO, "Closing connection %s: %s" \
% (self.db, self.connection))
self.db.close()
self.db = None
def _parse_connection_string(self, connection):
kwargs = {'conv': self.conv}
items = split(connection)
self._use_TM = None
if not items: return kwargs
lockreq, items = items[0], items[1:]
if lockreq[0] == "*":
self._mysql_lock = lockreq[1:]
db_host, items = items[0], items[1:]
self._use_TM = 1
else:
self._mysql_lock = None
db_host = lockreq
if '@' in db_host:
db, host = split(db_host,'@',1)
kwargs['db'] = db
if ':' in host:
host, port = split(host,':',1)
kwargs['port'] = int(port)
kwargs['host'] = host
else:
kwargs['db'] = db_host
if kwargs['db'] and kwargs['db'][0] in ('+', '-'):
self._try_transactions = kwargs['db'][0]
kwargs['db'] = kwargs['db'][1:]
else:
self._try_transactions = None
if not kwargs['db']:
del kwargs['db']
if not items: return kwargs
kwargs['user'], items = items[0], items[1:]
if not items: return kwargs
kwargs['passwd'], items = items[0], items[1:]
if not items: return kwargs
kwargs['unix_socket'], items = items[0], items[1:]
return kwargs
def tables(self, rdb=0,
_care=('TABLE', 'VIEW')):
r=[]
a=r.append
self._lock.acquire()
try:
self.db.query("SHOW TABLES")
result = self.db.store_result()
finally:
self._lock.release()
row = result.fetch_row(1)
while row:
a({'TABLE_NAME': row[0][0], 'TABLE_TYPE': 'TABLE'})
row = result.fetch_row(1)
return r
def columns(self, table_name):
from string import join
try:
try:
self._lock.acquire()
# Field, Type, Null, Key, Default, Extra
self.db.query('SHOW COLUMNS FROM %s' % table_name)
c=self.db.store_result()
finally:
self._lock.release()
except:
return ()
r=[]
for Field, Type, Null, Key, Default, Extra in c.fetch_row(0):
info = {}
field_default = Default and "DEFAULT %s"%Default or ''
if Default: info['Default'] = Default
if '(' in Type:
end = rfind(Type,')')
short_type, size = split(Type[:end],'(',1)
if short_type not in ('set','enum'):
if ',' in size:
info['Scale'], info['Precision'] = \
map(int, split(size,',',1))
else:
info['Scale'] = int(size)
else:
short_type = Type
if short_type in field_icons:
info['Icon'] = short_type
else:
info['Icon'] = icon_xlate.get(short_type, "what")
info['Name'] = Field
info['Type'] = type_xlate.get(short_type,'string')
info['Extra'] = Extra,
info['Description'] = join([Type, field_default, Extra or '',
key_types.get(Key, Key or ''),
Null != 'YES' and 'NOT NULL' or '']),
info['Nullable'] = (Null == 'YES') and 1 or 0
if Key:
info['Index'] = 1
if Key == 'PRI':
info['PrimaryKey'] = 1
info['Unique'] = 1
elif Key == 'UNI':
info['Unique'] = 1
r.append(info)
return r
def query(self,query_string, max_rows=1000):
self._use_TM and self._register()
desc=None
result=()
db=self.db
try:
try:
self._lock.acquire()
for qs in filter(None, map(strip,split(query_string, '\0'))):
qtype = upper(split(qs, None, 1)[0])
if qtype == "SELECT" and max_rows:
qs = "%s LIMIT %d" % (qs,max_rows)
r=0
db.query(qs)
c=db.store_result()
if desc is not None:
if c and (c.describe() != desc):
raise 'Query Error', (
'Multiple select schema are not allowed'
)
if c:
desc=c.describe()
result=c.fetch_row(max_rows)
else:
desc=None
finally:
self._lock.release()
except OperationalError, m:
if m[0] not in hosed_connection: raise
# Hm. maybe the db is hosed. Let's restart it.
db=self.db=apply(self.Database_Connection, (), self.kwargs)
return self.query(query_string, max_rows)
if desc is None: return (),()
items=[]
func=items.append
defs=self.defs
for d in desc:
item={'name': d[0],
'type': defs.get(d[1],"t"),
'width': d[2],
'null': d[6]
}
func(item)
return items, result
def string_literal(self, s): return self.db.string_literal(s)
def _begin(self, *ignored):
self._tlock.acquire()
try:
if self._transactions:
self.db.query("BEGIN")
self.db.store_result()
if self._mysql_lock:
self.db.query("SELECT GET_LOCK('%s',0)" % self._mysql_lock)
self.db.store_result()
except:
LOG('ZMySQLDA', ERROR, "exception during _begin",
error=sys.exc_info())
self._tlock.release()
raise
def _finish(self, *ignored):
try:
try:
if self._mysql_lock:
self.db.query("SELECT RELEASE_LOCK('%s')" % self._mysql_lock)
self.db.store_result()
if self._transactions:
self.db.query("COMMIT")
self.db.store_result()
except:
LOG('ZMySQLDA', ERROR, "exception during _finish",
error=sys.exc_info())
raise
finally:
self._tlock.release()
def _abort(self, *ignored):
try:
if self._mysql_lock:
self.db.query("SELECT RELEASE_LOCK('%s')" % self._mysql_lock)
self.db.store_result()
if self._transactions:
self.db.query("ROLLBACK")
self.db.store_result()
else:
LOG('ZMySQLDA', ERROR, "aborting when non-transactional")
finally:
self._tlock.release()

View File

@ -1,61 +0,0 @@
def manage_addZMySQLConnection(self, id, title,
connection_string,
check=None, REQUEST=None):
"""Add a MySQL connection to a folder.
Arguments:
REQUEST -- The current request
title -- The title of the ZMySQLDA Connection (string)
id -- The id of the ZMySQLDA Connection (string)
connection_string -- The connection string is of the form:
'[*lock] [+/-][database][@host[:port]] [user [password [unix_socket]]]'
or typically:
'database user password'
to use a MySQL server on localhost via the standard UNIX
socket. Only specify host if the server is on a remote
system. You can use a non-standard port, if necessary. If the
UNIX socket is in a non-standard location, you can specify the
full path to it after the password. Hint: To use a
non-standard port on the local system, use 127.0.0.1 for the
host instead of localhost.
Either a database or a host or both must be specified.
A '-' in front of the database tells ZMySQLDA to not use
Zope's Transaction Manager, even if the server supports
transactions. A '+' in front of the database tells ZMySQLDA
that it must use transactions; an exception will be raised if
they are not supported by the server. If neither '-' or '+'
are present, then transactions will be enabled if the server
supports them. If you are using non-transaction safe tables
(TSTs) on a server that supports TSTs, use '-'. If you require
transactions, use '+'. If you aren't sure, don't use either.
*lock at the begining of the connection string means to
psuedo-transactional. When the transaction begins, it will
acquire a lock on the server named lock (i.e. MYLOCK). When
the transaction commits, the lock will be released. If the
transaction is aborted and restarted, which can happen due to
a ConflictError, you'll get an error in the logs, and
inconsistent data. In this respect, it's equivalent to
transactions turned off.
Transactions are highly recommended. Using a named lock in
conjunctions with transactions is probably pointless.
"""
class Connection:
"""MySQL Connection Object"""
__constructor__ = manage_addZMySQLConnection

View File

@ -1,35 +0,0 @@
def manage_addZMySQLConnection(self, id, title,
connection_string,
check=None, REQUEST=None):
"""Add a MySQL connection to a folder.
Arguments:
REQUEST -- The current request
title -- The title of the ZMySQLDA Connection (string)
id -- The id of the ZMySQLDA Connection (string)
connection_string -- The connection string is of the form:
'database[@host[:port]] [user [password [unix_socket]]]'
or typically:
'database user password'
to use a MySQL server on localhost via the standard UNIX socket.
Only specify host if the server is on a remote system. You can
use a non-standard port, if necessary. If the UNIX socket is in
a non-standard location, you can specify the full path to it
after the password.
"""
class Connection:
"""MySQL Connection Object"""
__constructor__ = manage_addZMySQLConnection

View File

@ -1,28 +0,0 @@
class DB:
"""This is the ZMySQLDA Database Connection Object."""
def __init__(self,connection):
"""
connection
blah blah
"""
def tables(self, rdb=0,
_care=('TABLE', 'VIEW')):
"""Returns a list of tables in the current database."""
def columns(self, table_name):
"""Returns a list of column descriptions for 'table_name'."""
def query(self,query_string, max_rows=1000):
"""Execute 'query_string' and return at most 'max_rows'."""
def _begin(self, *ignored):
"""Begin a transaction (when TM is enabled)."""
def _finish(self, *ignored):
"""Commit a transaction (when TM is enabled)."""
def _abort(self, *ignored):
"""Rollback a transaction (when TM is enabled)."""

Binary file not shown.

Before

Width:  |  Height:  |  Size: 924 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 930 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 925 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 915 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 929 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 918 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 884 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 878 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 918 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 926 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 893 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 894 B

View File

@ -1,7 +0,0 @@
<dtml-var standard_html_header>
<dtml-var TABLE_TYPE><dtml-if TABLE_OWNER>
owned by <dtml-var TABLE_OWNER></dtml-if>
<dtml-if REMARKS><br><dtml-var REMARKS></dtml-if>
<dtml-var standard_html_footer>

View 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 _mysql 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 _mysql 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])

View File

@ -1,8 +0,0 @@
prune CVS
recursive-include doc *
recursive-include examples *
include README.MySQLmodule
include license.py
include MANIFEST.in
include MANIFEST
include GPL

View File

@ -1,518 +0,0 @@
"""MySQLdb - A DB API v2.0 compatible interface to MySQL.
This module is a thin wrapper around _mysql, which mostly implements
the MySQL C API. All symbols from that module are imported.
connect() -- connects to server
See the API specification and the MySQL documentation for more info on
other items.
For information on how MySQLdb handles type conversion, see the
_mysql_const.converters module.
"""
__author__ = "Andy Dustman <andy@dustman.net>"
__version__ = "0.3.6"
__revision__ = """$Revision$"""[11:-2]
import _mysql
from _mysql import *
if __version__ != getattr(_mysql, '__version__', None):
raise ImportError, "this is MySQLdb version %s, but _mysql is version %s" %\
(__version__, _mysql.__version__)
from _mysql_const.converters import *
import re, types
from types import ListType, TupleType
from string import rfind, join, split, atoi
threadsafety = 2
apilevel = "2.0"
paramstyle = "format"
try:
import threading
_threading = threading
del threading
except ImportError:
_threading = None
class DBAPITypeObject:
"""Helper class for determining column types; required by DB API."""
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()
def Binary(x): return str(x)
insert_values = re.compile(r'values\s(\(.+\))', re.IGNORECASE)
class BaseCursor:
"""A base for Cursor classes. Useful attributes:
description -- DB API 7-tuple describing columns in last query
arraysize -- default number of rows fetchmany() will fetch
See the MySQL docs for more information."""
def __init__(self, connection):
self.connection = connection
self.description = None
self.rowcount = -1
self.arraysize = 100
self._thequery = ''
def close(self):
"""Close the cursor. No further queries will be possible."""
self.connection = None
def _check_open(self):
if not self.connection:
raise ProgrammingError, "cursor closed"
def setinputsizes(self, *args):
"""Does nothing, required by DB API."""
def setoutputsizes(self, *args):
"""Does nothing, required by DB API."""
def execute(self, query, args=None):
"""Execute a query.
query -- string, query to execute on server
args -- sequence or mapping, parameters to use with query.
returns long integer rows affected, if any"""
self._check_open()
self._thequery = query
qc = self.connection.quote_conv
if not args:
return self._query(query)
elif type(args) is ListType and type(args[0]) is TupleType:
return self.executemany(query, args) # deprecated
else:
try:
return self._query(query % escape(args, qc))
except TypeError, m:
if m.args[0] in ("not enough arguments for format string",
"not all arguments converted"):
raise ProgrammingError, m.args[0]
else:
raise
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. The query must contain the clause "values ( ... )".
The parenthetical portion will be repeated once for each
item in the sequence.
returns long integer rows affected, if any
This method performs multiple-row inserts and similar queries."""
self._check_open()
self._thequery = query
from string import join
m = insert_values.search(query)
if not m: raise ProgrammingError, "can't find values"
p = m.start(1)
qc = self.connection.quote_conv
try:
q = [query % escape(args[0], qc)]
except TypeError, msg:
if msg.args[0] in ("not enough arguments for format string",
"not all arguments converted"):
raise ProgrammingError, msg.args[0]
else:
raise
qv = query[p:]
for a in args[1:]: q.append(qv % escape(a, qc))
return self._query(join(q, ',\n'))
def __do_query(self, q):
from string import split, atoi
db = self.connection.db
db.query(q)
self._result = self._get_result()
self.rowcount = db.affected_rows()
self.description = self._result and self._result.describe() or None
self._insert_id = db.insert_id()
self._info = db.info()
self._check_for_warnings()
return self.rowcount
def _check_for_warnings(self): pass
_query = __do_query
def info(self):
"""Return some information about the last query (db.info())"""
try: return self._info
except AttributeError: raise ProgrammingError, "execute() first"
def insert_id(self):
"""Return the last inserted ID on an AUTO_INCREMENT columns."""
try: return self._insert_id
except AttributeError: raise ProgrammingError, "execute() first"
def nextset(self):
"""Does nothing. Required by DB API."""
return None
def _fetch_row(self):
r = self._result.fetch_row(1, self._fetch_type)
return r and r[0] or ()
def _fetch_rows(self, size):
return self._result.fetch_row(size, self._fetch_type)
def _fetch_all_rows(self):
return self._result.fetch_row(0, self._fetch_type)
class CursorWarningMixIn:
"""This is a MixIn class that provides the capability of raising
the Warning exception when something went slightly wrong with your
query."""
def _check_for_warnings(self):
from string import atoi, split
if self._info:
warnings = atoi(split(self._info)[-1])
if warnings:
raise Warning, self._info
class CursorStoreResultMixIn:
"""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.connection.db.store_result()
def close(self):
"""Close the cursor. Further queries will not be possible."""
self.connection = None
self._rows = ()
def _query(self, q):
self.connection._acquire()
try:
rowcount = self._BaseCursor__do_query(q)
self._rows = self._result and self._fetch_all_rows() or ()
self._pos = 0
del self._result
return rowcount
finally:
self.connection._release()
def fetchone(self):
"""Fetches a single row from the cursor."""
if not self._thequery: raise ProgrammingError, "execute() first"
if self._pos >= len(self._rows): return None
result = self._rows[self._pos]
self._pos = self._pos+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."""
if not self._thequery: raise ProgrammingError, "execute() first"
end = self._pos + size or self.arraysize
result = self._rows[self._pos:end]
self._pos = end
return result
def fetchall(self):
"""Fetchs all available rows from the cursor."""
if not self._thequery: raise ProgrammingError, "execute() first"
result = self._pos and self._rows[self._pos:] or self._rows
self._pos = len(self._rows)
return result
def seek(self, row, whence=0):
"""seek to a given row of the result set analogously to file.seek().
This is non-standard extension."""
if whence == 0:
self._pos = row
elif whence == 1:
self._pos = self._pos + row
elif whence == 2:
self._pos = len(self._rows) + row
def tell(self):
"""Return the current position in the result set analogously to
file.tell(). This is a non-standard extension."""
return self._pos
class CursorUseResultMixIn:
"""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."""
def __init__(self, connection):
BaseCursor.__init__(self, connection)
if not self.connection._acquire(0):
raise ProgrammingError, "would deadlock"
def close(self):
"""Close the cursor. No further queries can be executed."""
if self.connection: self.connection._release()
self.connection = None
def __del__(self):
try:
del self._result
finally:
self.close()
def _get_result(self): return self.connection.db.use_result()
def fetchone(self):
"""Fetches a single row from the cursor."""
self._check_open()
if not self._thequery: raise ProgrammingError, "execute() first"
return self._fetch_row()
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_open()
if not self._thequery: raise ProgrammingError, "execute() first"
return self._fetch_rows(size or self.arraysize)
def fetchall(self):
"""Fetchs all available rows from the cursor."""
self._check_open()
if not self._thequery: raise ProgrammingError, "execute() first"
return self._fetch_all_rows()
class CursorTupleRowsMixIn:
"""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:
"""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, *args, **kwargs):
"""Fetch a single row as a dictionary. Deprecated:
Use fetchone() instead."""
return apply(self.fetchone, args, kwargs)
def fetchmanyDict(self, *args, **kwargs):
"""Fetch several rows as a list of dictionaries. Deprecated:
Use fetchmany() instead."""
return apply(self.fetchmany, args, kwargs)
def fetchallDict(self, *args, **kwargs):
"""Fetch all available rows as a list of dictionaries. Deprecated:
Use fetchall() instead."""
return apply(self.fetchall, args, kwargs)
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 CursorNW(CursorStoreResultMixIn, CursorTupleRowsMixIn,
BaseCursor):
"""This is a basic Cursor class that returns rows as tuples and
stores the result set in the client. Warnings are not raised."""
class Cursor(CursorWarningMixIn, CursorNW):
"""This is the standard Cursor class that returns rows as tuples and
stores the result set in the client. Warnings are raised as necessary."""
class DictCursorNW(CursorStoreResultMixIn, CursorDictRowsMixIn,
BaseCursor):
"""This is a Cursor class that returns rows as dictionaries and
stores the result set in the client. Warnings are not raised."""
class DictCursor(CursorWarningMixIn, DictCursorNW):
"""This is a Cursor class that returns rows as dictionaries and
stores the result set in the client. Warnings are raised as necessary."""
class SSCursorNW(CursorUseResultMixIn, CursorTupleRowsMixIn,
BaseCursor):
"""This is a basic Cursor class that returns rows as tuples and
stores the result set in the server. Warnings are not raised."""
class SSCursor(CursorWarningMixIn, SSCursorNW):
"""This is a Cursor class that returns rows as tuples and
stores the result set in the server. Warnings are raised as necessary."""
class SSDictCursorNW(CursorUseResultMixIn, CursorDictRowsMixIn,
BaseCursor):
"""This is a Cursor class that returns rows as dictionaries and
stores the result set in the server. Warnings are not raised."""
class SSDictCursor(CursorWarningMixIn, SSDictCursorNW):
"""This is a Cursor class that returns rows as dictionaries and
stores the result set in the server. Warnings are raised as necessary."""
class Connection:
"""Create a connection to the database. Note that this interface
uses keyword arguments exclusively.
host -- string, host to connect to or NULL pointer (localhost)
user -- string, user to connect as or NULL (your username)
passwd -- string, password to use or NULL (no password)
db -- string, database to use or NULL (no DB selected)
port -- integer, TCP/IP port to connect to or default MySQL port
unix_socket -- string, location of unix_socket to use or use TCP
client_flags -- integer, flags to use or 0 (see MySQL docs)
conv -- dictionary, maps MySQL FIELD_TYPE.* to Python functions which
convert a string to the appropriate Python type
quote_conv -- dictionary, maps Python types or classes to Python
functions which convert a value of that type (or instance
of that class) into an SQL literal value
connect_time -- number of seconds to wait before the connection
attempt fails.
compress -- if set, compression is enabled
init_command -- command which is run once the connection is created
read_default_file -- see the MySQL documentation for mysql_options()
read_default_group -- see the MySQL documentation for mysql_options()
Returns a Connection object.
There are a number of undocumented, non-standard methods. See the
documentation for the MySQL C API for some hints on what they do.
"""
def __init__(self, **kwargs):
from _mysql import connect
from string import split
if not kwargs.has_key('conv'): kwargs['conv'] = type_conv.copy()
self.quote_conv = kwargs.get('quote_conv', quote_conv.copy())
if kwargs.has_key('cursorclass'):
self.cursorclass = kwargs['cursorclass']
del kwargs['cursorclass']
else:
self.cursorclass = Cursor
self.db = apply(connect, (), kwargs)
self.quote_conv[types.StringType] = self.db.string_literal
self._transactional = self.db.server_capabilities & CLIENT.TRANSACTIONS
if _threading: self.__lock = _threading.Lock()
def __del__(self):
self.close()
if _threading:
def _acquire(self, blocking=1): return self.__lock.acquire(blocking)
def _release(self): return self.__lock.release()
else:
def _acquire(self, blocking=1): return 1
def _release(self): return 1
def close(self):
"""Close the connection. No further activity possible."""
self.db.close()
def commit(self):
"""Commit the current transaction."""
if self._transactional:
self.db.query("COMMIT")
def rollback(self):
"""Rollback the current transaction."""
if self._transactional:
self.db.query("ROLLBACK")
else: raise NotSupportedError, "Not supported by server"
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=Cursor is used."""
return (cursorclass or self.cursorclass)(self)
# Non-portable MySQL-specific stuff
# Methods not included on purpose (use Cursors instead):
# query, store_result, use_result
def affected_rows(self): return self.db.affected_rows()
def dump_debug_info(self): return self.db.dump_debug_info()
def escape_string(self, s): return self.db.escape_string(s)
def get_host_info(self): return self.db.get_host_info()
def get_proto_info(self): return self.db.get_proto_info()
def get_server_info(self): return self.db.get_server_info()
def info(self): return self.db.info()
def kill(self, p): return self.db.kill(p)
def list_dbs(self): return self.db.list_dbs().fetch_row(0)
def list_fields(self, table): return self.db.list_fields(table).fetch_row(0)
def list_processes(self): return self.db.list_processes().fetch_row(0)
def list_tables(self, db): return self.db.list_tables(db).fetch_row(0)
def field_count(self): return self.db.field_count()
num_fields = field_count # used prior to MySQL-3.22.24
def ping(self): return self.db.ping()
def row_tell(self): return self.db.row_tell()
def select_db(self, db): return self.db.select_db(db)
def shutdown(self): return self.db.shutdown()
def stat(self): return self.db.stat()
def string_literal(self, s): return self.db.string_literal(s)
def thread_id(self): return self.db.thread_id()
def _try_feature(self, feature, *args, **kwargs):
try:
return apply(getattr(self.db, feature), args, kwargs)
except AttributeError:
raise NotSupportedError, "not supported by MySQL library"
def character_set_name(self):
return self._try_feature('character_set_name')
def change_user(self, *args, **kwargs):
return apply(self._try_feature, ('change_user',)+args, kwargs)
def Connect(*args, **kwargs):
"""Factory function for Connection."""
return apply(Connection, args, kwargs)
connect = Connect

View File

@ -1,9 +0,0 @@
Metadata-Version: 1.0
Name: MySQL-python
Version: 0.3.6
Platform: POSIX, Windows
Summary: An interface to the MySQL RDBMS
Keywords: MySQL
Author: Andy Dustman
Author-email: <andy@dustman.net>
License: GNU GPL

View File

@ -1,57 +0,0 @@
Prerequisites:
Python 1.5.2 or higher
-- http://www.pythonlabs.com/products/python2.0/download_python2.0.html
-- http://www.python.org/1.6/
-- http://www.python.org/1.5/
-- Versions lower than 1.5.2 WON'T WORK.
-- If you have Red Hat Linux or a similar packaging system, make sure
you have the Python development headers and libraries (python-devel).
Distutils 1.0 or higher
-- comes with Python 1.6 and 2.0
-- http://www.python.org/sigs/distutils-sig/download.html
MySQL 3.22.19 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.
-- The current (recommended) 3.22 release is 3.22.32.
-- MySQL-3.23 is beta at present but supported.
-- If you have Red Hat Linux or a similar packaging system, make sure
you have the MySQL development headers and libraries (MySQL-devel).
First thing to do is edit setup.py. There are some variables towards the
beginning that tell it where your MySQL include files and libraries are.
The values are right for MySQL's standard Red Hat Linux (6.2) RPMs. If
you have another platform, you'll have to figure out the right values
yourself.
Note that recent binary distributions include two sets of client
libraries: mysqlclient and mysqlclient_r. The latter are the
"thread-safe" libraries, so use those if you can, and if threading is
important to you.
If you have the dynamic client libraries (on Linux, .so vs. .a), those
will be used by default. If they are not on your standard loader path,
you will have to set or adjust the LD_LIBRARY_PATH environment variable
(on Linux) or whatever your platform requires. Otherwise, you can adjust
setup.py to link against the static library.
Finally, putting it together:
$ python setup.py build
# python setup.py install
TIP: If you are using a binary package of Zope, you need run setup.py
with Zope's python executable. Otherwise, Zope (ZMySQLDA) will not
be able to find _mysql.
If you prefer RPMs, you can use the bdist_rpm command with setup.py.
Thanks go to Brian Fordham for cooking up an early version of setup.py.
License: GPL or the original license based on Python 1.5.2's license.
Andy Dustman <andy@dustman.net>
2000-11-30

View File

@ -1,9 +0,0 @@
If you have code that uses the old MySQLmodule's Mysqldb interface,
try CompatMysqldb. It is the old module adapted to use _mysql instead
of MySQL[module]. The original Mysqldb was written by James Henstridge.
If it's broken, it's probably my fault: I haven't tested it very much.
Consider it experimental.
Andy Dustman
<andy@dustman.net>
2000-08-09

View File

@ -1,94 +0,0 @@
Notes:
1) The patches are applied already, so you won't find them.
2) Supposedly the compile.py that is included here will work on
both unix and windows, but I've tried it on neither.
Andy
From bkline@rksystems.com Tue Sep 14 16:09:13 1999
Date: Sat, 11 Sep 1999 13:22:06 -0400 (EDT)
From: Bob Kline <bkline@rksystems.com>
To: adustman@comstar.net
Subject: Win32 Build of MySQLdb
Andy:
In the documentation for MySQLdb, you wrote:
> If you work out an installation routine for Windows, please contact
> the author.
I have built MySQLdb on Windows NT 4.0, PL5, using MSVC 6.0. The steps
I took were:
1. Pull down and modify David Ascher's compile.py.
2. Modify _mysqlmodule.c.
3. Modify Setup.in.
4. Run compile.py.
5. Copy _mysql.pyd and MySQLdb.py into the PYTHONPATH.
I have attached a zip archive containing:
* _mysqlmodule.c
* _mysqlmodule.diff
* Setup.in
* Setup.diff
* compile.py
Specifics about the modifications:
1. Ascher's script linked to the single-threaded C run-time libraries,
but the mysql libraries are multi-threaded. Changed /MD to /MT and
/MDd to /MTd.
2. The mysql headers need but fail to include windows.h on WIN32. Added
conditional #include statement.
3. The non-standard type uint needed to be defined.
4. Some of the mysql constants used by MySQLdb are presumably from
version 3.22.19 (as you indicate in the documentation), but the
latest version of the client/development tools available for
Win32 is 3.22.14, which doesn't have all of those constants defined.
Added some #ifdef statements to make sure symbols that aren't
defined aren't used.
5. The PyObject_HEAD_INIT(&PyType_Type) don't work on Win32, as
explained in the online Python tutorials. Added conditional
replacement approach as instructed by that documentation.
6. Added a null pointer test to a Py_DECREF call to avoid a
segmentation fault.
7. Modifed Setup.in to account for the location of the mysql
headers and libraries on my system, and to include the Win32
sockets library (wsock32.lib)
The modified C source code should still work on all platforms. The
Setup file will need to be customized for each platform which doesn't
have its mysql headers and libraries in the default locations, and Win32
builds will need wsock32 in the setup file. I wasn't able to determine
how to put conditional portions in the setup file (ideally I wouldn't
have needed to modify compily.py at all). I presume there is
documentation somewhere for this setup file, but I'm new enough to the
Python world that I haven't found it yet.
Assuming the modifications to _mysqlmodule.c get folded into the
distribution, and a version of Setup.in for Win32 (including
"-lwsock32") is added to the distribution (for example, as Setup.w32),
and the attached version of Ascher's script is included, the steps
someone else would take in order to build with the current version of
MSVC would be:
1. Copy Setup.w32 to Setup.in.
2. Adjust paths in Setup.in as needed.
3. Run compile.py.
4. Copy _mysql.pyd and MySQLdb.py into the PYTHONPATH.
Hope this is useful.
--
Bob Kline
mailto:bkline@rksystems.com
http://www.rksystems.com
[ Part 2, "Mods for building MySQLdb on Win32 platforms" ]
[ Application/ZIP 29KB. ]
[ Unable to print this part. ]

View File

@ -1,23 +0,0 @@
"""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

View File

@ -1,30 +0,0 @@
"""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

View File

@ -1,211 +0,0 @@
"""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
ERROR_MESSAGES = 203

View File

@ -1,33 +0,0 @@
"""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
ENUM = 247
SET = 248
TINY_BLOB = 249
MEDIUM_BLOB = 250
LONG_BLOB = 251
BLOB = 252
VAR_STRING = 253
STRING = 254
CHAR = TINY
INTERVAL = ENUM

View File

@ -1,23 +0,0 @@
"""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

View File

@ -1,17 +0,0 @@
"""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

View File

@ -1 +0,0 @@
__all__ = ['converters','exc','CR', 'FIELD_TYPE','CLIENT','REFRESH','ER','FLAG']

View File

@ -1,191 +0,0 @@
"""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. Dictionaries are used to map "types" to convertor functions:
type_conv -- type conversion dictionary mapping SQL column types
(FIELD_TYPE) to Python functions. Each function converts a single
string argument to an appropriate Python data type. By default,
SQL types not included here are returned as Python strings.
quote_conv -- quoting dictionary mapping Python types to
functions. Each function takes one argument of the indicated (key)
type and a mapping argument, and returns an SQL literal,
i.e. strings will be escaped and quoted. The mapping argument is
the quoting dictionary itself, and is only used for recursive
quoting (i.e. when quoting sequences). Most simple converters will
not need this and can ignore it, but must be prepared to accept
it. Keys may be either TypeObjects or ClassObjects. Instances will
be converted by the converter matching the class, if available; or
the first converter found that is a parent class of the instance;
or else the str() function will be used converted as a string
literal.
Don't modify these dictionaries 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 FIELD_TYPE, string_literal, \
escape_sequence, escape_dict, NULL
from time import localtime, strftime
import types
def Thing2Str(s, d):
"""Convert something into a string via str()."""
return str(s)
# Python 1.5.2 compatibility hack
if str(0L)[-1]=='L':
def Long2Int(l, d):
"""Convert a long integer to a string, chopping the L."""
return str(l)[:-1]
else:
Long2Int = Thing2Str
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)
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 quote_conv; 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 d.has_key(o.__class__): return
d[o.__class__](o, d)
cl = filter(lambda x,o=o: type(x)==types.ClassType and isinstance(o,x), d.keys())
if not cl:
return d[types.StringType](o,d)
d[o.__class__] = d[cl[0]]
return d[cl[0]](o, d)
quote_conv = {
types.IntType: Thing2Str,
types.LongType: Long2Int,
types.FloatType: Thing2Str,
types.NoneType: None2NULL,
types.TupleType: escape_sequence,
types.ListType: escape_sequence,
types.DictType: escape_dict,
types.InstanceType: Instance2Str,
types.StringType: Thing2Literal, # default
}
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
}
try:
try:
# new packaging
from mx.DateTime import Date, Time, Timestamp, ISO, \
DateTimeType, DateTimeDeltaType
except ImportError:
# old packaging
from DateTime import Date, Time, Timestamp, ISO, \
DateTimeType, DateTimeDeltaType
def DateFromTicks(ticks):
"""Convert UNIX ticks into a mx.DateTime.Date."""
return apply(Date, localtime(ticks)[:3])
def TimeFromTicks(ticks):
"""Convert UNIX ticks into a mx.DateTime.Time."""
return apply(Time, localtime(ticks)[3:6])
def TimestampFromTicks(ticks):
"""Convert UNIX ticks into a mx.DateTime.Timestamp."""
return apply(Timestamp, localtime(ticks)[:6])
def format_DATE(d):
"""Format a DateTime object as an ISO date."""
return d.strftime("%Y-%m-%d")
def format_TIME(d):
"""Format a DateTime object as a time value."""
return d.strftime("%H:%M:%S")
def format_TIMESTAMP(d):
"""Format a DateTime object as an ISO timestamp."""
return d.strftime("%Y-%m-%d %H:%M:%S")
def mysql_timestamp_converter(s):
"""Convert a MySQL TIMESTAMP to a mx.DateTime.Timestamp."""
parts = map(int, filter(None, (s[:4],s[4:6],s[6:8],
s[8:10],s[10:12],s[12:14])))
try: return apply(Timestamp, tuple(parts))
except: return None
def DateTime_or_None(s):
try: return ISO.ParseDateTime(s)
except: return None
def TimeDelta_or_None(s):
try: return ISO.ParseTimeDelta(s)
except: return None
def Date_or_None(s):
try: return ISO.ParseDate(s)
except: return None
type_conv[FIELD_TYPE.TIMESTAMP] = mysql_timestamp_converter
type_conv[FIELD_TYPE.DATETIME] = DateTime_or_None
type_conv[FIELD_TYPE.TIME] = TimeDelta_or_None
type_conv[FIELD_TYPE.DATE] = Date_or_None
def DateTime2literal(d, c):
"""Format a DateTime object as an ISO timestamp."""
return "'%s'" % format_TIMESTAMP(d)
def DateTimeDelta2literal(d, c):
"""Format a DateTimeDelta object as a time."""
return "'%s'" % format_TIME(d)
quote_conv[DateTimeType] = DateTime2literal
quote_conv[DateTimeDeltaType] = DateTimeDelta2literal
except ImportError:
# no DateTime? We'll muddle through somehow.
def DateFromTicks(ticks):
"""Convert UNIX ticks to ISO date format."""
return strftime("%Y-%m-%d", localtime(ticks))
def TimeFromTicks(ticks):
"""Convert UNIX ticks to time format."""
return strftime("%H:%M:%S", localtime(ticks))
def TimestampFromTicks(ticks):
"""Convert UNIX ticks to ISO timestamp format."""
return strftime("%Y-%m-%d %H:%M:%S", localtime(ticks))
def format_DATE(d):
"""Format a date as a date (does nothing, you don't have mx.DateTime)."""
return d
format_TIME = format_TIMESTAMP = format_DATE
__all__ = [ 'quote_conv', 'type_conv', 'DateFromTicks', 'TimeFromTicks',
'TimestampFromTicks', 'format_DATE', 'format_TIME',
'format_TIMESTAMP' ]

View File

@ -1,59 +0,0 @@
"""_mysql_const.exc: 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
"""
from exceptions import Exception, StandardError
class MySQLError(StandardError):
"""Exception related to operation with MySQL."""
class 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."""
del Exception, StandardError

File diff suppressed because it is too large Load Diff

View File

@ -1,127 +0,0 @@
<!doctype linuxdoc system>
<article>
<title>MySQLdb FAQ
<author>Andy Dustman
<date>$Id$
<sect>Compiling <tt/_mysqlmodule.so/
<P>Here are some common errors that happen during the build.
This section covers UNIX/Linux problems only, as I don't do Windows.
<tt/.so/ is a dynamically loading library on Linux and most other UNIX
variants; a few use extensions other than <tt/.so/. Windows probably
uses <tt/.dll/.
<sect1>ImportError: libmysqlclient.so.6: cannot open shared object file:
No such file or directory
<P>
You have dynamic MySQL libraries, and by default, your compiler links
<tt/_mysqlmodule.so/ against these, but these are not on your loader path
when you start Python.
You have two basic options:
<p>
<enum>
<item>
Modify setup.py so that it links against the static library; see the comments.
<item>
Change your system environment so that the MySQL libraries are on
your loader path. With Linux, you can modify <tt>/etc/ld.so.conf</tt> (see
<tt/man ldconfig/ for more details) or you can add to or create the
<tt/LD_LIBRARY_PATH/ environment variable before starting Python, i.e.
<p><code>
LD_LIBRARY_PATH=/path/to/mysql/libs python ... # Bourne-ish shell
</code>
</enum>
<sect1>ImportError: ./_mysqlmodule.so: undefined symbol: PyLong_FromUnsignedLongLong
<p>
<tt/PyLong_FromUnsignedLongLong()/ first appears in Python 1.5.2, so you are
linking against an earlier version. You may also have more than one version
installed. Get Python 1.5.2 from your vendor or python.org.
<sect1>ImportError: ./_mysqlmodule.so: undefined symbol: uncompress
<P>
It seems that MySQL-3.23 client libraries require libz for gzip
compression. setup.py should add this automatically.
<sect1>./_mysqlmodule.c:33: mysql.h: No such file or directory
<P>The include path (-I) to your MySQL include files is wrong; modify
setup.py. OR: You don't have the MySQL development stuff loaded. If you
are using the Red Hat RPMs, you need the <tt/MySQL-devel/ RPM to compile
<tt/_mysqlmodule.so/. However, if you link against the static MySQL
libraries (see above), you can install <tt/_mysqlmodule.so/ on a system
that does not have the MySQL client libraries (<tt/libmysqlclient/).
<sect1>I'm using Windows...
<P>Say no more.
<P>I don't use Windows. setup.py is supposed to work for building.
There may also be a link to some user-contributed binaries on the web site.
</sect1>
<sect>
Trouble with ZMySQLDA
<p>What? ZMySQLDA never fails! Well, actually, I just don't have any
good questions yet. Except: Install MySQLdb first, and then untar
the ZMySQLDA source into your Zope home, and restart Zope.
<sect>Using MySQLdb
<p>
MySQLdb is a
<htmlurl url="http://www.python.org/topics/database/DatabaseAPI-2.0.html"
name="Python Database API Specification 2.0"> database module, so you
should be familiar with the spec. Deviations from the spec are documented in the
<htmlurl url="http://dustman.net/andy/python/MySQLdb/doc/MySQLdb.html"
name="MySQLdb documentation">.
<sect1>What do I do if I am completely clueless?
<p>Get a clue. Clues have been provided in the <tt/examples/ directory
of the MySQLdb distribution.
<sect1>No, I mean <em/really/ clueless!
<p>Okay, it goes something like this:
<enum>
<item>
Import MySQLdb.
<item>
Create a Connection object.
<item>
Create a Cursor object.
<item>
Execute your query on the Cursor object.
<item>
If your query returns rows, you can use the Cursor object to fetch them.
<item>
Rinse, lather, repeat.
</enum>
Example:
<code>
import MySQLdb
db = MySQLdb.connect(db='mydb',user='myuser',passwd='mypasswd')
c = db.cursor()
c.execute(myquery)
results = c.fetchall()
</code>
<sect1>But MySQL doesn't have cursors!
<p>True enough. MySQLdb fakes it, though, because the spec requires it.
<sect1>cursor.rollback() always fails!
<p>MySQL now supports transactions using BDB tables.
If your server doesn't support them, rollbacks will always fail, as they should,
because it can't do what you asked.
Even if your server does support them, rollbacks will fail if you
modified any non-BDB tables.
<p>OTOH, <tt/cursor.commit()/, which attempts to commit the transaction
to the database, <em/does/ exist and always succeeds, because MySQL
essentially is always in auto-commit mode.
<sect1>How do I use some of the special MySQL features?
<P>Short answer: Don't, if you can avoid it. Your program will not
be portable to other databases.
<P>Long answer: MySQLdb exports all symbols from _mysql. There are only
a couple MySQL functions available this way, though. The Connection object
does wrap nearly all of the various MySQL calls that use a <tt/MYSQL/
argument (the connection handle in the C API). So let's say you want to
use <tt/mysql_select_db(newdb)/. In MySQLdb, that's
<tt/db.select_db(newdb)/ where <tt/db/ is your Connection object.
<sect1>I still wanna use _mysql directly.
<p>Well, it <tt/may/ be appropriate in some cirumstances.
ZMySQLDA does this, because MySQLdb does a lot of type conversion that
isn't necessary for Zope's purposes.
<enum>
<item>
Read the MySQL docs, particularly the C API, for an overview.
<item>
Read the MySQLdb docs. This shows how the C API is transliterated
into Python.
</enum>
</article>

View File

@ -1,477 +0,0 @@
<!DOCTYPE linuxdoc system>
<article>
<title>MySQLdb: a Python interface for MySQL
<author>Andy Dustman
<date>$Id$
<abstract>MySQLdb is an thread-compatible interface to the popular
MySQL database server that provides the Python database API.
<sect>Introduction
<P>This module should be <ref id="MySQLmodule" name="mostly compatible">
with an older interface
written by Joe Skinner and others. However, the older version is a)
not thread-friendly (database operations could cause all other threads
to block), b) written for MySQL 3.21 (does not compile against newer
versions without patches), c) apparently not actively
maintained. MySQLdb is a completely new module, distributed free of
charge under a license derived from the Python license.
<p>
<sect1>Platforms
<p>
<sect2>Linux/UNIX
<p>
This module is developed on RedHat Linux (currently 7.0)
for Intel. It should build without
much trouble on most platforms by using the <tt/setup.py/ script.
Supposedly it builds on MacOS X.
Be aware that you need the Distutils package which comes with
Python 2.0. If you don't have it (i.e. you have Python 1.5.2), you
can find it over at <htmlurl url="http://www.python.org/" name="www.python.org">.
<sect2>Windows (3.11, 95, 98, NT, 2000, CE, BSOD, XYZ, etc.)
<p>
Windows is <em/not/ a supported platform.
However, the <tt/setup.py/ script
reportedly gets the job done.
There is probably a link on the web page for getting a precompiled
Windows installer from someone or other.
Be aware that this is a user-contributed package; the author
cannot help you with compiling and running under Windows.
<sect1>Python
<p>
MySQLdb requires Python 1.5.2. Earlier versions will not work, because
support for C <tt/long long/ is required by MySQL. If you have an
earlier version of Python, upgrade to 1.5.2 or beyond.
<sect1>MySQL
<p>
<sect2>MySQL-3.22
<p>
Only versions 3.22.32 and
up are guaranteed to work. Some older versions may work;
if you have an older version you should
seriously consider upgrading to get the bug fixes and particularly
the security updates.
MySQL-3.22 seems to have a problem trying to insert <tt/TIME/
values with fractional seconds. Values like 12:56:13.00 are
returned as 344:13:00, apparently interpreting the original input
as 12 days, 56 hours, 13 minutes, 0 seconds. (12 days and 56 hours
is 344 hours.) To avoid this problem, use the <tt/DateTimeDelta/
type.
<sect2>MySQL-3.23
<p>
MySQL-3.23 is presently in gamma (stable prerelease). Several API
additions have been made so far. These will be incorporated into
MySQLdb as work progresses. As of 3.23.30, transactions are supported
in MySQL using BDB tables. MySQLdb (0.3.0 and up) detects the
presence of BDB table support
upon connection and will issue <tt/COMMIT/ and <tt/ROLLBACK/
statements when appropriate. Note that MySQL operates in
<tt/AUTOCOMMIT/ mode by default; you will have to issue SQL to
change this.
<sect1>DateTime
<p>If you have the <htmlurl
url="http://www.lemburg.com/files/python/mxDateTime.html"
name="DateTime"> module installed (recommended), MySQLdb will use
it for date-related objects. Otherwise, these will be returned to
Python as strings. You can also modify the type conversion
dictionaries to return these as other object classes, if you
prefer.
<sect1>MySQLmodule<label id="MySQLmodule">
<p>
MySQLmodule, the older MySQL interface by Joe Skinner and others,
is also a split C/Python
interface. <tt/MySQL/, the C portion, has an interface similar to
perl's DBI internally. In addition, there is Python portion, <tt/Mysqldb/,
which provides a DB API v1.0 interface, written by James Henstridge.
MySQLdb-0.2.2 and up include <tt/CompatMysqldb/, which is an adaptation
of <tt/Mysqldb/ to <tt/_mysql/. It should be considered experimental.
In contrast, MySQLdb's C portion, <tt><ref id="_mysql"></tt>, is designed
to mimic the MySQL C API in an object-oriented way; you should not
expect to move from <tt/MySQL/ to <tt/_mysql/ without a fair amount of
work. <tt><ref id="MySQLdb"></tt> provides a DB API v2.0 interface,
which has some changes from the v1.0 interface. Things to watch out
for in particular:
<table>
<tabular ca="foo">
Operation | Mysqldb | MySQLdb
@ Connecting | <tt>db = Mysqldb.Mysqldb("db@host user pass")</tt>
| <tt>db = MySQLdb.connect(db='db', host='host', user='user', passwd='pass')</tt>
@ Implicit cursor | <tt>db.execute(SQL)</tt> |
implicit cursors dropped from DB API v2.0; always use <tt>c = db.cursor()</tt>
@ Fetch row as dictionary | <tt>c.fetchDict()</tt>,
keys are "<em/table.column/" |
not standard; alternate cursor class <tt>DictCursor</tt>
provides a dictionary interface,
keys are "<em/column/" or "<em/table.column/" if there are two columns
with the same name; use SQL <tt/AS/ to rename fields.
@ Transactions | <tt>db.commit()</tt> and <tt>db.rollback()</tt>
both exist and silently do nothing <ref id="rollback" name="(danger!)">
| <tt>db.commit()</tt> and <tt>db.rollback()</tt> work if the MySQL
server can perform transactions; otherwise <tt>db.rollback()</tt>
always fails
<caption>Mysqldb to MySQLdb changes</tabular></table>
<sect1>Zope and ZMySQLDA
<p>I wrote a <htmlurl url="http://dustman.net/andy/python/ZMySQLDA" name="ZMySQLDA"> for use with MySQLdb.
<sect1>Documentation
<p>The web page documentation may be slightly ahead of the latest release
and may reflect features of the next release.
<sect1>FAQs
<p>A FAQ is available at
<htmlurl url="http://dustman.net/andy/python/MySQLdb/faq/MySQLdb-FAQ.html">.
<sect>_mysql module<label id="_mysql">
<P>
If you want to write applications which are portable across databases,
avoid using this module directly. <tt>_mysql</tt> 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 <ref id="MySQLdb"> module. If you really need it, use the
standard MySQL docs and transliterate as necessary.
<p>Compatibility note: As of 0.3.0, the various fetch_rowXXX() cursor
methods have been combined into a single fetch_row([n=1[,how=0]])
method. See the built-in module documentation for more details.
<p>
The C API has been wrapped in an object-oriented way. The only MySQL
data structures which are implemented are the <tt>MYSQL</tt> (database
connection handle) and <tt>MYSQL_RES</tt> (result handle) types. In
general, any function which takes <tt>MYSQL *mysql</tt> as an argument
is now a method of the connection object, and any function which takes
<tt>MYSQL_RES *result</tt> 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 <tt>mysql_</tt>
prefix is dropped from the name. Most of the <tt>conn</tt> methods
listed are also available as MySQLdb Connection object methods. Their
use is explicitly non-portable.
<table>
<tabular ca="MySQL C API foo foo function mapping">
C API | <tt>_mysql</tt>
@ <tt>mysql_affected_rows()</tt> | <tt>conn.affected_rows()</tt>
@ <tt>mysql_close()</tt> | <tt>conn.close()</tt>
@ <tt>mysql_connect()</tt> | <tt>_mysql.connect()</tt>
@ <tt>mysql_data_seek()</tt> | <tt>result.data_seek()</tt>
@ <tt>mysql_debug()</tt> | <tt>_mysql.debug()</tt>
@ <tt>mysql_dump_debug_info</tt> | <tt>conn.dump_debug_info()</tt>
@ <tt>mysql_escape_string()</tt> | <tt>_mysql.escape_string()</tt>
@ <tt>mysql_fetch_row()</tt> | <tt>result.fetch_row()</tt>
@ <tt>mysql_get_client_info()</tt> | <tt>_mysql.get_client_info()</tt>
@ <tt>mysql_get_host_info()</tt> | <tt>conn.get_host_info()</tt>
@ <tt>mysql_get_proto_info()</tt> | <tt>conn.get_proto_info()</tt>
@ <tt>mysql_get_server_info()</tt> | <tt>conn.get_server_info()</tt>
@ <tt>mysql_info()</tt> | <tt>conn.info()</tt>
@ <tt>mysql_insert_id()</tt> | <tt>conn.insert_id()</tt>
@ <tt>mysql_list_dbs()</tt> | <tt>conn.list_dbs()</tt>
@ <tt>mysql_list_fields()</tt> | <tt>conn.list_fields()</tt>
@ <tt>mysql_list_processes()</tt> | <tt>conn.list_processes()</tt>
@ <tt>mysql_list_tables()</tt> | <tt>conn.list_tables()</tt>
@ <tt>mysql_num_fields()</tt> | <tt>result.num_fields()</tt>
@ <tt>mysql_num_rows()</tt> | <tt>result.num_rows()</tt>
@ <tt>mysql_options()</tt> | <tt>_mysql.connect()</tt>
@ <tt>mysql_ping()</tt> | <tt>conn.ping()</tt>
@ <tt>mysql_query()</tt> | <tt>conn.query()</tt>
@ <tt>mysql_real_connect()</tt> | <tt>_mysql.connect()</tt>
@ <tt>mysql_real_query()</tt> | <tt>conn.query()</tt>
@ <tt>mysql_real_escape_string()</tt> | <tt>conn.escape_string()</tt>
@ <tt>mysql_row_seek()</tt> | <tt>result.row_seek()</tt>
@ <tt>mysql_row_tell()</tt> | <tt>result.row_tell()</tt>
@ <tt>mysql_select_db()</tt> | <tt>conn.select_db()</tt>
@ <tt>mysql_stat()</tt> | <tt>conn.stat()</tt>
@ <tt>mysql_store_result()</tt> | <tt>conn.store_result()</tt>
@ <tt>mysql_thread_id()</tt> | <tt>conn.thread_id()</tt>
@ <tt>mysql_use_result()</tt> | <tt>conn.use_result()</tt>
@ <tt>CLIENT_*</tt> | <tt>_mysql.CLIENT.*</tt>
@ <tt>CR_*</tt> | <tt>_mysql.CR.*</tt>
@ <tt>ER_*</tt> | <tt>_mysql.ER.*</tt>
@ <tt>FIELD_TYPE_*</tt> | <tt>_mysql.FIELD_TYPE.*</tt>
@ <tt>FLAG_*</tt> | <tt>_mysql.FLAG.*</tt>
<caption>MySQL C API function mapping
</tabular>
</table>
<sect>MySQLdb -- DB API interface<label id="MySQLdb">
<p>
MySQLdb is a thin Python wrapper around <tt><ref id="_mysql"></tt>
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 <tt>_mysql</tt> for the sake of efficiency.
<p>
The
<htmlurl url="http://www.python.org/topics/database/DatabaseAPI-2.0.html"
name="DB API specification"> should be your primary guide for using this
module. Only deviations from the spec and other database-dependent
things will be documented here. Note that all symbols from
<tt>_mysql</tt> are imported into this module. Mostly these are the
required exceptions, the constant classes, and a very few functions.
<sect1>Functions and attributes <P>Only a few top-level functions and
attributes are defined within MySQLdb.
<descrip>
<tag><label id="connect()">connect(parameters...)</tag> 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 <tt/mysql_options()/ before connecting. Note
that all 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:
<descrip>
<tag>host</tag>
name of host to connect to. Default: use local host
<tag>user</tag>
user to authenticate as. Default: current effective user.
<tag>passwd</tag>
password to authenticate with. Default: no password.
<tag>db</tag>
database to use. Default: no default database.
<tag>conv</tag> literal-to-Python type conversion dictionary.
Default: <tt/MySQLdb.type_conv/
<tag>quote_conv</tag> Python type-to-literal conversion
dictionary. Default: <tt/MySQLdb.quote_conv/
<tag>cursorclass</tag> cursor class that <tt/cursor()/ uses,
unless overridden. Default: <tt/MySQLdb.Cursor/.
<tag>compress</tag> Enable protocol compression. Default: no compression.
<tag>connect_timeout</tag> Abort if connect is not completed within
given number of seconds. Default: no timeout (?)
<tag>named_pipe</tag> Use a named pipe (Windows). Default: don't.
<tag>init_command</tag> Initial command to issue to server upon
connection. Default: Nothing.
<tag>read_default_file</tag> MySQL configuration file to read; see
the MySQL documentation for <tt/mysql_options()/.
<tag>read_default_group</tag> Default group to read; see the MySQL
documentation for <tt/mysql_options()/.
<tag>unix_socket</tag>
location of UNIX socket. Default: use TCP.
<tag>port</tag>
TCP port of MySQL server. Default: standard port (3306).
</descrip>
<tag>apilevel</tag>
String constant stating the supported DB API level. '2.0'
<tag>threadsafety</tag> Integer constant stating the level of thread
safety the interface supports. As of MySQLdb version 0.2.0, this
is set to 2, which means: Threads may share the module and connections.
Cursors employ a mutex in the connection object to ensure that
cursors do not use the connection at the same time. Generally,
sharing a connection probably reduces performance; the MySQL
server maintains a seperate thread for each connection.
See the MySQL documentation for more details.
<tag>paramstyle</tag> 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.
Compatibility note: The older MySQLmodule uses a similar
parameter scheme, but requires that quotes be placed around
format strings which will contain strings, dates, and similar
character data. This is not necessary for MySQLdb. It is
recommended that %s (and not '%s') be used for all parameters,
regardless of type. The interface performs all necessary
quoting.
<tag><label id="type_conv">type_conv</tag> A dictionary mapping MySQL
types (from <TT>FIELD_TYPE.*</TT>) to callable Python objects
(usually functions) which convert from a string to the desired
type. 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 <tt>type_conv</tt> which is safe to modify on a
per-connection basis. The dictionary includes some of the
factory functions from the <tt>DateTime</tt> module, if it is
available. Several non-standard types (<tt>SET, ENUM</tt>) are
returned as strings, which is how MySQL returns all
columns. Note: <tt>TIME</tt> columns are returned as strings
presently. This should be a temporary condition.
<tag><label id="quote_conv">quote_conv</tag> A dictionary mapping
Python types (from the standard <tt>types</tt> module or
built-in function <tt>type()</tt> to MySQL literals. By
default, the value is treated as a string. When creating a
Connection object, you can pass your own quote converter
dictionary as a keyword parameter.
<P>As of MySQL-3.23, MySQL supports different character sets in the
server, and a new quoting function, <tt/mysql_real_escape_string()/.
This requires the string quoting function to be a method bound to
the connection object. MySQLdb handles this for you automatically.
However, if you feel the need to do something goofy with your strings,
you will have to modify the dictionary after opening the connection.
In practice, you should never have to worry about this.
</descrip>
<sect1>Connection Objects
<P>Connection objects are returned by the <tt>connect()</tt> function.
<descrip>
<tag>commit()</tag> If the database supports transactions, this
commits the current transaction; otherwise this method
successfully does nothing. <footnote>MySQL supports transactions
as of version 3.23.15-alpha.</footnote>
<tag><label id="rollback">rollback()</tag> If the
database supports transactions, this rolls back (cancels) the
current transaction; otherwise a <tt>NotSupportedError</tt> is
raised.
Compatibility note: The older <ref id="MySQLmodule"> defines this method,
which sucessfully does nothing. This is dangerous behavior, as a
successful rollback indicates that the current transaction was
backed out, which is not true, and fails to notify the
programmer that the database now needs to be cleaned up by other
means.
<tag>cursor([cursorclass])</tag>
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 <tt/Cursor/
class. Also see the additional supplied cursor classes in the
<ref id="usage"> section.
</descrip>
<sect1>Cursor Objects
<p>
<descrip>
<tag>callproc()</tag>
Not implemented.
<tag>close()</tag>
Closes the cursor. Future operations raise <tt/ProgrammingError/.
If you are using <ref id="SSCursor" name="server-side cursors">,
it is very important to close the cursor when you are done with
it and before creating a new one. Otherwise, deadlock may occur.
<tag/insert_id()/
Returns the last <tt/AUTO_INCREMENT/ field value inserted
into the database. (Non-standard)
<tag>nextset()</tag>
Not implemented.
<tag>setinputsizes()</tag>
Does nothing, successfully.
<tag>setoutputsizes()</tag>
Does nothing, successfully.
</descrip>
<sect>Using and extending<label id="usage">
<P>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 <tt><ref id="connect()"></tt> 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.
For an example of this, see the author's
<htmlurl url="http://dustman.net/andy/python"
name="SQLDict module">, which allows standard queries to be
defined and accessed using an object which looks like a
dictionary, and reads/writes user-defined objects.
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:
<p>
<descrip>
<tag>BaseCursor</tag> The base class for Cursor objects.
This does not raise Warnings.
<tag>CursorWarningMixIn</tag> Causes the Warning exception to be raised
on queries which produce warnings.
<tag>CursorStoreResultMixIn</tag> Causes the Cursor to use the
<tt>mysql_store_result()</tt> function to get the query result. The
entire result set is stored on the client side.
<tag><label id="SSCursor">CursorUseResultMixIn</tag> Causes the cursor to use the
<tt>mysql_use_result()</tt> function to get the query result. The
result set is stored on the server side and is transferred row by row
using fetch operations. Not recommended, particularly for threaded
applications that share connections. Note that creating the cursor
causes it to acquire a lock on the connection object, and this is
not released until the cursor is deleted or <tt/cursor.close()/.
If you aren't careful about this, it can result in deadlock, which
is bad.
<tag>CursorTupleRowsMixIn</tag> Causes the cursor to return rows
as a tuple of the column values.
<tag>CursorDictRowsMixIn</tag> 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 <em/table.column/.
This can be avoided by using
the SQL <tt>AS</TT> keyword. (This is yet-another reason not to use
<tt/*/ in SQL queries, particularly where <tt/JOIN/ is involved.
<tag>Cursor</tag> The default cursor class. This class is composed
of <tt>CursorWarningMixIn, CursorStoreResultMixIn, CursorTupleRowsMixIn,</tt>
and <tt>BaseCursor</tt>, i.e. it raises <tt>Warning</tt>, uses
<tt>mysql_store_result()</tt>, and returns rows as tuples.
<tag>DictCursor</tag> Like <tt/Cursor/ except it returns rows as
dictionaries.
<tag>SSCursor</tag> A "server-side" cursor. Like <tt/Cursor/ but uses
<tt/CursorUseResultMixIn/. Thread-safe, but not recommended for
threaded applications which share connections.
Use only if you are dealing with potentially large result sets.
<tag/SSDictCursor/ Like <tt/SSCursor/ except it returns rows as
dictionaries.
<tag/XXXCursorNW/> Cursors with the "NW" suffix do not raise Warnings.
</descrip>
<p>For an example of how to use these classes,
read the code. If you need something more exotic than this,
you will have to roll your own.
</article>

View File

@ -1,7 +0,0 @@
These examples were kindly contributed by Bradley Stec of RuleSpace, Inc.
I made a few changes to illustrate some points and some new features.
If something doesn't work, it's probably my fault.
Andy Dustman
<adustman@comstar.net>
2000-03-08

View File

@ -1,266 +0,0 @@
#!/usr/bin/python
__version__ = "$Revision$"[11:-2]
# This version mangled by Andy Dustman <adustman@comstar.net>.
# Original credits follow. This is a nice introduction in general,
# but I felt there were a few bits and pieces that needs to be cleaned up.
# TITLE: dbtrainer0
# WRITTEN BY: Bradley Stec, July 1999
# RuleSpace, Inc.
# SUPPORTS: WebOps Database Interface Trainer Script
# PURPOSE: This script is an code and output example of how to use the
# MySQLdb API to communicate with a database and perform basic
# SQL queries.
# FUNCTION: Both by executing the script and by reading the source code,
# a programmer should be able to get a grasp on how the interface
# works and may borrow code for their own script projects.
# REQUIREMENTS: This script requires the access to the webops module, and that a
# database named "TEST" be installed in the webops specified
# database server. The contents of the test database can be created
# using the following SQL command sets.
#
# CREATE TABLE COLORS (
# COLOR varchar(32) DEFAULT '' NOT NULL,
# PRIME_COLOR enum('No','Yes') DEFAULT 'No' NOT NULL,
# LAST_DATE timestamp(14) DEFAULT '' NOT NULL,
# OPEN_DATE timestamp(14) DEFAULT '' NOT NULL,
# PRIMARY KEY (COLOR),
# KEY PRIME_COLOR (PRIME_COLOR),
# KEY LAST_DATE (LAST_DATE),
# KEY OPEN_DATE (OPEN_DATE)
# );
#
# INSERT INTO COLORS VALUES ('red','Yes',NOW(),NOW());
# INSERT INTO COLORS VALUES ('blue','Yes',NOW(),NOW());
# INSERT INTO COLORS VALUES ('green','Yes',NOW(),NOW());
# INSERT INTO COLORS VALUES ('yellow','No',NOW(),NOW());
# INSERT INTO COLORS VALUES ('orange','No',NOW(),NOW());
# INSERT INTO COLORS VALUES ('purple','No',NOW(),NOW());
# INSERT INTO COLORS VALUES ('cyan','No',NOW(),NOW());
#
# CREATE TABLE TEAM (
# MEMBER_ID int(11) DEFAULT '0' NOT NULL auto_increment,
# FIRST_NAME varchar(32) DEFAULT '' NOT NULL,
# LAST_NAME varchar(32) DEFAULT '' NOT NULL,
# REMARK varchar(64) DEFAULT '' NOT NULL,
# FAV_COLOR varchar(32) DEFAULT '' NOT NULL,
# LAST_DATE timestamp(14) DEFAULT '' NOT NULL,
# OPEN_DATE timestamp(14) DEFAULT '' NOT NULL,
# PRIMARY KEY (MEMBER_ID),
# KEY FAV_COLOR (FAV_COLOR),
# KEY LAST_DATE (LAST_DATE),
# KEY OPEN_DATE (OPEN_DATE)
# );
#
# INSERT INTO TEAM VALUES (1,'Brad','Stec','Techno Needy','aquamarine',NOW(),NOW());
# INSERT INTO TEAM VALUES (2,'Nick','Borders','Meticulous Nick','blue',NOW(),NOW());
# INSERT INTO TEAM VALUES (3,'Brittney','McChristy','The Data Diva','blue',NOW(),NOW());
# INSERT INTO TEAM VALUES (4,'Fuzzy','Logic','The Logic Bunny','cyan',NOW(),NOW());
#
# CHANGES: 7/99 Initial Version
import sys
#import webops
import traceback
sys.stderr = sys.stdout
# Set Up Page Layout
print "content-type: text/html"
print
print "<HTML>\n"
print "<BODY BGCOLOR=\"#FFFFFF\">\n"
print "<FONT FACE=\"arial\" SIZE=\"3\"><B>RuleSpace, Inc. WebOps Database Interface Trainer - Part 0</B><BR><HR>"
print "The purpose of this page is to present sample code for interfacing with the databases within the Web Operations server farm. The display below illustrates real database queries as well as how the information is handled and presented.<P>"
print "By viewing the CGI script which presents the information below you'll be able to see how the database interface and API works within the WebOps scripting environment.<P>"
print "<HR>"
# Loading The API Support
# The API MySQLdb is a thin wrapper around a C program which is also in the site-packages directory called _mysqlmodule.so
# The API follows the Python Database API Spec version 2.0 which basically sets standards for what kind of methods will be
# used to access databases within the Python environment. The _mysqlmodule.so and MySQLdb.py programs allow a programmer
# to pass SQL commands/queries through to a database. The database server may be remote or local. The MySQL database server
# software doesn't provide an interactive cursor, so the API programs create a "cursor" in local memory. Read the Python
# Database API Spec version 2.0 for details.
# This command loads the support files
import MySQLdb
# PREPARE TO CONNECT TO DATABASE
# This command forms a connection through the support files to the target database server and database name.
try:
# Note: most of these keyword values have reasonable defaults.
# The following line with probably also work, depending on your
# MySQL configuration:
WebOpsDB = MySQLdb.Connect(db='test')
#WebOpsDB = MySQLdb.Connection(host=webops.dbserver,user=webops.dbuser,passwd=webops.dbpass,db='test',port=3306,unix_socket="")
except:
print "\n\n<PRE>"
traceback.print_exc()
sys.exit()
# A LITTLE BONUS INFORMATION FROM THE API
# The API can provide some information about the connection and server.
# These functions are not portable to other databases.
print "<B>CONNECTED TO</B><BR>"
print "&nbsp;&nbsp;&nbsp;&nbsp;server <B> ", WebOpsDB.get_host_info(), "</B><BR>"
print "&nbsp;&nbsp;&nbsp;&nbsp;running <B>mySQL server v", WebOpsDB.get_server_info(), "</B><BR>"
print "&nbsp;&nbsp;&nbsp;&nbsp;current status: ",WebOpsDB.stat(), "<P>"
print "<HR>"
# CREATE YOUR PERSONAL CONNECTION TO THE "RESULTS" WITHIN THE CONNECTION OBJECT
# We haven't actually queried anything yet, so don't get confused, we're just preparing for it.
# A cursor is a "result set" holding object. The API creates a "cursor" object complete with a set of
# methods for executing query results into it.
try:
cursor = WebOpsDB.cursor()
except:
print "\n\n<PRE>"
traceback.print_exc()
sys.exit()
# PERFORM A QUERY
# The cursor object is a Python class object. In it, we can specify a query. Below we query the TEAM table from the
# WebOpsDB object by referring to our new "cursor" object.
try:
cursor.execute("SELECT * FROM TEAM")
except:
print "\n\n<PRE>"
traceback.print_exc()
sys.exit()
# STORE THE RESULTS INTO A LOCALLY CONTROLLED MEMORY LOCATION
# Two things just came from our query: 1) a description of the table structure and 2) a result set stored in the API cursor.
# The API "cursor" must be "consumed" by your script to get the results out. Therefore its a good idea to store the results
# into a local variable. The results will become a nicely formatted Python list data type. If you don't store it locally,
# you'll need to requery the database every time you need the data again.
# 1) THE TABLE STRUCTURE
# The cursor.description attribute will provide a Python list data type representation of the field structure.
# In the example below we use the for loop to travel through the list and read the first element of each list.
# 2) THE RESULT SET
# The result set can be completely fetched into one list data type.
try:
resultSet = cursor.fetchall()
except:
print "\n\n<PRE>"
traceback.print_exc()
sys.exit()
# AND NOW YOU CAN SEE RESULTS
# Now you can take your information and present it.
print "<B>EXAMPLES OF USING THE <U>SELECT</U> SQL COMMAND.</B><P>"
print "QUERY OF TEAM TABLE<BR>"
print "<FONT SIZE=\"1\"><B>("
# The Table Field Names
for cursorFieldname in cursor.description:
print cursorFieldname[0]+","
print ")</B>"
print "<BR>"
# The Result Set
for cursorRecord in resultSet:
print cursorRecord
print "<BR>"
print "<P></FONT>"
print "<FONT SIZE=\"1\">same results in very nicely formatted columns:<BR>"
print "<TABLE BORDER=\"1\"><TR>"
for cursorFieldname in cursor.description:
print "<TD><CENTER><FONT FACE=\"arial\" SIZE=\"2\">" +cursorFieldname[0]+ "</FONT></CENTER></TD>"
print "</TR>"
for cursorRecord in resultSet:
print "<TR>"
for cursorField in cursorRecord:
print "<TD><FONT FACE=\"arial\" SIZE=\"1\">"
print cursorField
print "</FONT></TD>"
print "</TR>"
print "</TABLE>"
print "</CENTER>"
print "&nbsp;<P></FONT><P><HR><P>"
# HERE'S ANOTHER TABLE
try:
cursor.execute("SELECT * FROM COLORS")
except:
print "\n\n<PRE>"
traceback.print_exc()
sys.exit()
print "QUERY OF COLORS TABLE<BR>"
print "<FONT SIZE=\"1\"><B>("
for cursorFieldname in cursor.description:
print cursorFieldname[0]+","
print ")</B>"
print "<BR>"
# The values are loaded into the object 'resultSet'
resultSet = cursor.fetchall()
for cursorRecord in resultSet:
print cursorRecord
print "<BR>"
print "&nbsp;<BR></FONT>"
# Display Query Results In Columns
print "<FONT SIZE=\"1\">same results in very nicely formatted columns:<BR>"
print "<TABLE BORDER=\"1\"><TR>"
for cursorFieldname in cursor.description:
print "<TD><CENTER><FONT FACE=\"arial\" SIZE=\"1\">" +cursorFieldname[0]+ "</FONT></CENTER></TD>"
print "</TR>"
for cursorRecord in resultSet:
print "<TR>"
for cursorField in cursorRecord:
print "<TD><FONT FACE=\"arial\" SIZE=\"1\">"
print cursorField
print "</FONT></TD>"
print "</TR>"
print "</TABLE>"
print "</CENTER>"
print "&nbsp;<P><HR><P></FONT>"
# NOW WE CAN SEE HOW TO COMBINE KEYED TABLES
# The following query uses standard SQL commands to join the two databases together and produce a list of each of the team's
# favorite colors.
try:
cursor.execute("SELECT TEAM.FIRST_NAME,TEAM.LAST_NAME,TEAM.FAV_COLOR,COLORS.PRIME_COLOR FROM TEAM,COLORS WHERE TEAM.FAV_COLOR = COLORS.COLOR")
except:
print "\n\n<PRE>"
traceback.print_exc()
sys.exit()
print "JOINED QUERY OF TEAM AND COLORS TABLES<BR>"
print "Now we can compare our team membership list to our colors table to determine which of their favorite colors are primary colors. Notice that records in the TEAM list that don't have a \"known\" color don't show up in the results.<P>"
print "<FONT SIZE=\"1\">results of query<BR>"
resultSet = cursor.fetchall()
print "<TABLE BORDER=\"1\"><TR>"
for cursorFieldname in cursor.description:
print "<TD><CENTER><FONT FACE=\"arial\" SIZE=\"1\">" +cursorFieldname[0]+ "</FONT></CENTER></TD>"
print "</TR>"
print "</TR>"
for cursorRecord in resultSet:
print "<TR>"
for cursorField in cursorRecord:
print "<TD><FONT FACE=\"arial\" SIZE=\"1\">"
print cursorField
print "</FONT></TD>"
print "</TR>"
print "</TABLE>"
print "</CENTER>"
print "<P>"
# CLOSING THE DATABASE OBJECT
try:
WebOpsDB.close()
except:
print "\n\n<PRE>"
traceback.print_exc()
sys.exit()
# CONTINUED IN DBTRAINER1
# To learn more about inserting records, and performing other SQL functions review
# dbtrainer1.
# END YOUR HTML PAGE
print "</FONT></BODY>\n"
print "</HTML>\n"

View File

@ -1,163 +0,0 @@
#!/usr/bin/python
__version__ = "$Revision$"[11:-2]
# This version mangled by Andy Dustman <adustman@comstar.net>.
# Original credits follow. This is a nice introduction in general,
# but I felt there were a few bits and pieces that needs to be cleaned up.
# TITLE: dbtrainer1
# WRITTEN BY: Bradley Stec, July 1999
# RuleSpace, Inc.
# SUPPORTS: WebOps Database Interface Trainer Script
# PURPOSE: This script is a code and output example of how to use the
# MySQLdb API to communicate to a database and perform basic
# SQL command language requests.
# FUNCTION: Both by executing the script and by reading the source code,
# a programmer should be able to get a grasp on how the interface
# works and may borrow code for their own script projects.
# REQUIREMENTS: This script requires the access to the webops module, and that a
# database named "TEST" be installed in the webops specified
# database server.
#
# CHANGES: 7/99 Initial Version
import sys
#import webops
import traceback
sys.stderr = sys.stdout
# Set Up Page Layout
print "content-type: text/html"
print
print "<HTML>\n"
print "<BODY BGCOLOR=\"#FFFFFF\">\n"
print "<FONT FACE=\"arial\" SIZE=\"3\"><B>RuleSpace, Inc. WebOps Database Interface Trainer -- Part 1</B><BR><HR>"
print "The purpose of this page is to present sample code for interfacing with the databases within the Web Operations server farm. The display below illustrates real database queries as well as how the information is handled and presented.<P>"
print "By viewing the CGI script which presents the information below you'll be able to see how the database interface and API works within the WebOps scripting environment.<P>"
print "<HR>"
# Loading The API Support
# The API MySQLdb is a thin wrapper around a C program which is also in the site-packages directory called _mysqlmodule.so
# The API follows the Python Database API Spec version 2.0 which basically sets standards for what kind of methods will be
# used to access databases within the Python environment. The _mysqlmodule.so and MySQLdb.py programs allow a programmer
# to pass SQL commands/queries through to a database. The database server may be remote or local. The MySQL database server
# software doesn't provide an interactive cursor, so the API programs create a "cursor" in local memory. Read the Python
# Database API Spec version 2.0 for details.
# This command loads the support files
import MySQLdb
# PREPARE TO CONNECT TO DATABASE
# This command forms a connection through the support files to the target database server and database name.
try:
#WebOpsDB = MySQLdb.Connection(host=webops.dbserver,user=webops.dbuser,passwd=webops.dbpass,db='test',port=3306,unix_socket="")
WebOpsDB = MySQLdb.Connect(db='test')
except:
print "\n\n<PRE>"
traceback.print_exc()
sys.exit()
# A LITTLE BONUS INFORMATION FROM THE API
# The API can provide some information about the connection and server.
# These methods are not portable to other databases.
print "<B>CONNECTED TO</B><BR>"
print "&nbsp;&nbsp;&nbsp;&nbsp;server <B> ", WebOpsDB.get_host_info(), "</B><BR>"
print "&nbsp;&nbsp;&nbsp;&nbsp;running <B>mySQL server v", WebOpsDB.get_server_info(), "</B><BR>"
print "&nbsp;&nbsp;&nbsp;&nbsp;current status: ",WebOpsDB.stat(), "<P>"
print "<HR>"
# CREATE YOUR PERSONAL CONNECTION TO THE "RESULTS" WITHIN THE CONNECTION OBJECT
# We haven't actually queried anything yet, so don't get confused, we're just preparing for it.
try:
cursor = WebOpsDB.cursor()
except:
print "\n\n<PRE>"
traceback.print_exc()
sys.exit()
# EXAMPLE: INSERTING A NEW RECORD
# This example uses a query command to INSERT a new record into the table. The format of the data must exactly match
# the table structure requirements or it will be rejected. Note that we are using single quotes around strings within
# the SQL command.
# GOTCHA #1: The MySQLdb API doesn't respond well to zero value datatime fields. Make sure that you populate your datetime
# fields with positive values. You'll notice I used the built-in mySQL function NOW() to make sure that there was a valid
# date in the created field. The modified field is auto-updated because it is the first timestamp data type in the data table.
# GOTCHA #2: INSERT or REPLACE? Both function in a very similar method, with one minor difference. The INSERT command
# simply creates a new record/row and places the fields/columns into the table. The REPLACE command will INSERT a new record
# into the table, then it compares the Primary Key values of the new record to any pre-existing matches in the table. Any
# older records/rows in the table with a matching Primary Key (which is supposed to be unique) will be deleted in favor of
# the new record. You might consider using REPLACE even when you want to INSERT just to make sure you don't end up with
# duplicate data in your tables.
print "<B>EXAMPLES USING THE <U>INSERT</U> AND <U>REPLACE</U> SQL COMMANDS.</B><P>"
# REPLACE
try:
cursor.execute("REPLACE INTO TEAM (MEMBER_ID,FIRST_NAME,LAST_NAME,REMARK,FAV_COLOR,OPEN_DATE) VALUES ('6','Frederick','Clueless','Clueless Fred','blue',NOW());")
except:
print "\n\n<PRE>"
traceback.print_exc()
sys.exit()
# INSERT -- Note that since the Primary Key for the TEAM table is not specified in our insert command and member_id is an
# autoincrement data type, a new member_id is assigned to this inserted record. Try reloading this web page in your browser
# a few times to observe the results.
try:
cursor.execute("INSERT INTO TEAM (FIRST_NAME,LAST_NAME,REMARK,FAV_COLOR,OPEN_DATE) VALUES ('Ruprecht','Lionheart','Lost Rupe','cyan',NOW());")
except:
print "\n\n<PRE>"
traceback.print_exc()
sys.exit()
# INSERT -- This example will cause an INTEGRITY ERROR, because the MEMBER_ID will conflict with an existing MEMBER_ID.
try:
cursor.execute("INSERT INTO TEAM (MEMBER_ID,FIRST_NAME,LAST_NAME,REMARK,FAV_COLOR,OPEN_DATE) VALUES ('4','Fuzzy','Illogic','Evil Twin of Fuzzy Logic','red',NOW());")
except:
print "<FONT SIZE=\"1\">SAMPLE INTEGRITY ERROR</FONT><BR>"
print "<PRE>"
traceback.print_exc()
print "</PRE><P>"
# REQUERY TO SEE RESULTS
try:
cursor.execute("SELECT * FROM TEAM")
except:
print "\n\n<PRE>"
traceback.print_exc()
sys.exit()
resultSet = cursor.fetchall()
print "<B>ADDING NEW TEAM MEMBERS</B><BR>"
print "<FONT SIZE=\"1\">results of query:<BR>"
print "<TABLE BORDER=\"1\"><TR>"
for cursorFieldname in cursor.description:
print "<TD><CENTER><FONT FACE=\"arial\" SIZE=\"2\">" +cursorFieldname[0]+ "</FONT></CENTER></TD>"
print "</TR>"
for cursorRecord in resultSet:
print "<TR>"
for cursorField in cursorRecord:
print "<TD><FONT FACE=\"arial\" SIZE=\"1\">"
print cursorField
print "</FONT></TD>"
print "</TR>"
print "</TABLE>"
print "</CENTER>"
print "&nbsp;<P></FONT><P><HR><P>"
# CLOSING THE DATABASE OBJECT
try:
WebOpsDB.close()
except:
print "\n\n<PRE>"
traceback.print_exc()
sys.exit()
# CONTINUED IN DBTRAINER2
# To learn more about replacing and updating records, and performing other SQL functions review
# dbtrainer2.
# END YOUR HTML PAGE
print "</FONT></BODY>\n"
print "</HTML>\n"

View File

@ -1,130 +0,0 @@
#!/usr/bin/python
__version__ = "$Revision$"[11:-2]
# This version mangled by Andy Dustman <adustman@comstar.net>.
# Original credits follow. This is a nice introduction in general,
# but I felt there were a few bits and pieces that needs to be cleaned up.
# TITLE: dbtrainer2
# WRITTEN BY: Bradley Stec, July 1999
# RuleSpace, Inc.
# SUPPORTS: WebOps Database Interface Trainer Script
# PURPOSE: This script is a code and output example of how to use the
# MySQLdb API to communicate to a database and perform basic
# SQL command language requests.
# FUNCTION: Both by executing the script and by reading the source code,
# a programmer should be able to get a grasp on how the interface
# works and may borrow code for their own script projects.
# REQUIREMENTS: This script requires the access to the webops module, and that a
# database named "test" be installed in the webops specified
# database server.
#
# CHANGES: 7/99 Initial Version
import sys
#import webops
import traceback
sys.stderr = sys.stdout
# Set Up Page Layout
print "content-type: text/html"
print
print "<HTML>\n"
print "<BODY BGCOLOR=\"#FFFFFF\">\n"
print "<FONT FACE=\"arial\" SIZE=\"3\"><B>RuleSpace, Inc. WebOps Database Interface Trainer -- Part 2</B><BR><HR>"
print "The purpose of this page is to present sample code for interfacing with the databases within the Web Operations server farm. The display below illustrates real database queries as well as how the information is handled and presented.<P>"
print "By viewing the CGI script which presents the information below you'll be able to see how the database interface and API works within the WebOps scripting environment.<P>"
print "<HR>"
# Loading The API Support
# The API MySQLdb is a thin wrapper around a C program which is also in the site-packages directory called _mysqlmodule.so
# The API follows the Python Database API Spec version 2.0 which basically sets standards for what kind of methods will be
# used to access databases within the Python environment. The _mysqlmodule.so and MySQLdb.py programs allow a programmer
# to pass SQL commands/queries through to a database. The database server may be remote or local. The MySQL database server
# software doesn't provide an interactive cursor, so the API programs create a "cursor" in local memory. Read the Python
# Database API Spec version 2.0 for details.
# This command loads the support files
import MySQLdb
# PREPARE TO CONNECT TO DATABASE
# This command forms a connection through the support files to the target database server and database name.
try:
#WebOpsDB = MySQLdb.Connection(host=webops.dbserver,user=webops.dbuser,passwd=webops.dbpass,db='test',port=3306,unix_socket="")
WebOpsDB = MySQLdb.Connect(db='test')
except:
print "\n\n<PRE>"
traceback.print_exc()
sys.exit()
# A LITTLE BONUS INFORMATION FROM THE API
# The API can provide some information about the connection and server.
# These methods are not portable to other databases.
print "<B>CONNECTED TO</B><BR>"
print "&nbsp;&nbsp;&nbsp;&nbsp;server <B> ", WebOpsDB.get_host_info(), "</B><BR>"
print "&nbsp;&nbsp;&nbsp;&nbsp;running <B>mySQL server v", WebOpsDB.get_server_info(), "</B><BR>"
print "&nbsp;&nbsp;&nbsp;&nbsp;current status: ",WebOpsDB.stat(), "<P>"
print "<HR>"
# CREATE YOUR PERSONAL CONNECTION TO THE "RESULTS" WITHIN THE CONNECTION OBJECT
# We haven't actually queried anything yet, so don't get confused, we're just preparing for it.
try:
cursor = WebOpsDB.cursor()
except:
print "\n\n<PRE>"
traceback.print_exc()
sys.exit()
# EXAMPLE: UPDATING A RECORD
# This example modifies an existing field/column with new information using the UPDATE command. It is recommended that
# you use this method over a REPLACE command, since REPLACE uses INSERT and requires additional processing for file locking.
try:
cursor.execute("UPDATE TEAM SET TEAM.FAV_COLOR='green',TEAM.LAST_DATE=NOW() WHERE TEAM.FIRST_NAME='Frederick' AND TEAM.LAST_NAME='Clueless';")
except:
print "\n\n<PRE>"
traceback.print_exc()
sys.exit()
# REQUERY TO SEE RESULTS
try:
cursor.execute("SELECT * FROM TEAM;")
resultSet = cursor.fetchall()
except:
print "\n\n<PRE>"
traceback.print_exc()
sys.exit()
print "<B>EXAMPLES OF USING THE <U>UPDATE</U> SQL COMMAND.</B><P>"
print "MODIFYING AN EXISTING RECORD (Fred changes his favorite color!)<BR>"
print "<FONT SIZE=\"1\">"
print "<TABLE BORDER=\"1\"><TR>"
for cursorFieldname in cursor.description:
print "<TD><CENTER><FONT FACE=\"arial\" SIZE=\"2\">" +cursorFieldname[0]+ "</FONT></CENTER></TD>"
print "</TR>"
for cursorRecord in resultSet:
print "<TR>"
for cursorField in cursorRecord:
print "<TD><FONT FACE=\"arial\" SIZE=\"1\">"
print cursorField
print "</FONT></TD>"
print "</TR>"
print "</TABLE>"
print "</CENTER>"
print "&nbsp;<P></FONT><P><HR><P>"
# CLOSING THE DATABASE OBJECT
try:
WebOpsDB.close()
except:
print "\n\n<PRE>"
traceback.print_exc()
sys.exit()
# CONTINUED IN DBTRAINER3
# To learn more about deleting records, and performing other SQL functions review
# dbtrainer3.
# END YOUR HTML PAGE
print "</FONT></BODY>\n"
print "</HTML>\n"

View File

@ -1,128 +0,0 @@
#!/usr/bin/python
__version__ = "$Revision$"[11:-2]
# This version mangled by Andy Dustman <adustman@comstar.net>.
# Original credits follow. This is a nice introduction in general,
# but I felt there were a few bits and pieces that needs to be cleaned up.
# TITLE: dbtrainer3
# WRITTEN BY: Bradley Stec, July 1999
# RuleSpace, Inc.
# SUPPORTS: WebOps Database Interface Trainer Script
# PURPOSE: This script is a code and output example of how to use the
# MySQLdb API to communicate to a database and perform basic
# SQL command language requests.
# FUNCTION: Both by executing the script and by reading the source code,
# a programmer should be able to get a grasp on how the interface
# works and may borrow code for their own script projects.
# REQUIREMENTS: This script requires the access to the webops module, and that a
# database named "test" be installed in the webops specified
# database server.
#
# CHANGES: 7/99 Initial Version
import sys
#import webops
import traceback
sys.stderr = sys.stdout
# Set Up Page Layout
print "content-type: text/html"
print
print "<HTML>\n"
print "<BODY BGCOLOR=\"#FFFFFF\">\n"
print "<FONT FACE=\"arial\" SIZE=\"3\"><B>RuleSpace, Inc. WebOps Database Interface Trainer -- Part 3</B><BR><HR>"
print "The purpose of this page is to present sample code for interfacing with the databases within the Web Operations server farm. The display below illustrates real database queries as well as how the information is handled and presented.<P>"
print "By viewing the CGI script which presents the information below you'll be able to see how the database interface and API works within the WebOps scripting environment.<P>"
print "<HR>"
# Loading The API Support
# The API MySQLdb is a thin wrapper around a C program which is also in the site-packages directory called _mysqlmodule.so
# The API follows the Python Database API Spec version 2.0 which basically sets standards for what kind of methods will be
# used to access databases within the Python environment. The _mysqlmodule.so and MySQLdb.py programs allow a programmer
# to pass SQL commands/queries through to a database. The database server may be remote or local. The MySQL database server
# software doesn't provide an interactive cursor, so the API programs create a "cursor" in local memory. Read the Python
# Database API Spec version 2.0 for details.
# This command loads the support files
import MySQLdb
# PREPARE TO CONNECT TO DATABASE
# This command forms a connection through the support files to the target database server and database name.
try:
#WebOpsDB = MySQLdb.Connection(host=webops.dbserver,user=webops.dbuser,passwd=webops.dbpass,db='test',port=3306,unix_socket="")
WebOpsDB = MySQLdb.Connect(db='test')
except:
print "\n\n<PRE>"
traceback.print_exc()
sys.exit()
# A LITTLE BONUS INFORMATION FROM THE API
# The API can provide some information about the connection and server.
# These methods are not portable to other databases.
print "<B>CONNECTED TO</B><BR>"
print "&nbsp;&nbsp;&nbsp;&nbsp;server <B> ", WebOpsDB.get_host_info(), "</B><BR>"
print "&nbsp;&nbsp;&nbsp;&nbsp;running <B>mySQL server v", WebOpsDB.get_server_info(), "</B><BR>"
print "&nbsp;&nbsp;&nbsp;&nbsp;current status: ",WebOpsDB.stat(), "<P>"
print "<HR>"
# CREATE YOUR PERSONAL CONNECTION TO THE "RESULTS" WITHIN THE CONNECTION OBJECT
# We haven't actually queried anything yet, so don't get confused, we're just preparing for it.
try:
cursor = WebOpsDB.cursor()
except:
print "\n\n<PRE>"
traceback.print_exc()
sys.exit()
# EXAMPLE: DELETING A RECORD
# This example deletes record.
try:
cursor.execute("DELETE FROM TEAM WHERE FIRST_NAME='Frederick' AND LAST_NAME='Clueless';")
cursor.execute("DELETE FROM TEAM WHERE FIRST_NAME='Ruprecht';")
except:
print "\n\n<PRE>"
traceback.print_exc()
sys.exit()
# REQUERY TO SEE RESULTS
try:
cursor.execute("SELECT * FROM TEAM")
resultSet = cursor.fetchall()
except:
print "\n\n<PRE>"
traceback.print_exc()
sys.exit()
print "<B>EXAMPLES OF USING THE <U>DELETE</U> SQL COMMAND.</B><P>"
print "DELETING FRED AND HIS FRIEND RUPRECHT<BR>"
print "<FONT SIZE=\"1\">"
print "<TABLE BORDER=\"1\"><TR>"
for cursorFieldname in cursor.description:
print "<TD><CENTER><FONT FACE=\"arial\" SIZE=\"2\">" +cursorFieldname[0]+ "</FONT></CENTER></TD>"
print "</TR>"
for cursorRecord in resultSet:
print "<TR>"
for cursorField in cursorRecord:
print "<TD><FONT FACE=\"arial\" SIZE=\"1\">"
print cursorField
print "</FONT></TD>"
print "</TR>"
print "</TABLE>"
print "</CENTER>"
print "&nbsp;<P></FONT><P><HR><P>"
# CLOSING THE DATABASE OBJECT
try:
WebOpsDB.close()
except:
print "\n\n<PRE>"
traceback.print_exc()
sys.exit()
# CONTINUED IN DBTRAINER4
# To learn more about converting result sets into Python dictionary data types, see dbtrainer4.
print "</FONT></BODY>\n"
print "</HTML>\n"

View File

@ -1,147 +0,0 @@
#!/usr/bin/python
__version__ = "$Revision$"[11:-2]
# This version mangled by Andy Dustman <adustman@comstar.net>.
# Original credits follow. This is a nice introduction in general,
# but I felt there were a few bits and pieces that needs to be cleaned up.
# TITLE: dbtrainer4
# WRITTEN BY: Bradley Stec, July 1999
# RuleSpace, Inc.
# SUPPORTS: WebOps Database Interface Trainer Script
# PURPOSE: This script is a code and output example of how to use the
# MySQLdb API to communicate to a database and perform basic
# SQL command language requests.
# FUNCTION: Both by executing the script and by reading the source code,
# a programmer should be able to get a grasp on how the interface
# works and may borrow code for their own script projects.
# REQUIREMENTS: This script requires the access to the webops module, and that a
# database named "test" be installed in the webops specified
# database server.
#
# CHANGES: 7/99 Initial Version
import sys
#import webops
import traceback
sys.stderr = sys.stdout
# Set Up Page Layout
print "content-type: text/html"
print
print "<HTML>\n"
print "<BODY BGCOLOR=\"#FFFFFF\">\n"
print "<FONT FACE=\"arial\" SIZE=\"3\"><B>RuleSpace, Inc. WebOps Database Interface Trainer -- Part 4</B><BR><HR>"
print "The purpose of this page is to present sample code for interfacing with the databases within the Web Operations server farm. The display below illustrates real database queries as well as how the information is handled and presented.<P>"
print "By viewing the CGI script which presents the information below you'll be able to see how the database interface and API works within the WebOps scripting environment.<P>"
print "<HR>"
# Loading The API Support
# The API MySQLdb is a thin wrapper around a C program which is also in the site-packages directory called _mysqlmodule.so
# The API follows the Python Database API Spec version 2.0 which basically sets standards for what kind of methods will be
# used to access databases within the Python environment. The _mysqlmodule.so and MySQLdb.py programs allow a programmer
# to pass SQL commands/queries through to a database. The database server may be remote or local. The MySQL database server
# software doesn't provide an interactive cursor, so the API programs create a "cursor" in local memory. Read the Python
# Database API Spec version 2.0 for details.
# This command loads the support files
import MySQLdb
# PREPARE TO CONNECT TO DATABASE
# This command forms a connection through the support files to the target database server and database name.
try:
#WebOpsDB = MySQLdb.Connection(host=webops.dbserver,user=webops.dbuser,passwd=webops.dbpass,db='test',port=3306,unix_socket="")
WebOpsDB = MySQLdb.Connect(db='test')
except:
print "\n\n<PRE>"
traceback.print_exc()
sys.exit()
# A LITTLE BONUS INFORMATION FROM THE API
# The API can provide some information about the connection and server.
# These methods are not portable to other databases.
print "<B>CONNECTED TO</B><BR>"
print "&nbsp;&nbsp;&nbsp;&nbsp;server <B> ", WebOpsDB.get_host_info(), "</B><BR>"
print "&nbsp;&nbsp;&nbsp;&nbsp;running <B>mySQL server v", WebOpsDB.get_server_info(), "</B><BR>"
print "&nbsp;&nbsp;&nbsp;&nbsp;current status: ",WebOpsDB.stat(), "<P>"
print "<HR>"
# CREATE YOUR PERSONAL CONNECTION TO THE "RESULTS" WITHIN THE CONNECTION OBJECT
# We haven't actually queried anything yet, so don't get confused, we're just preparing for it.
try:
cursor = WebOpsDB.cursor()
except:
print "\n\n<PRE>"
traceback.print_exc()
sys.exit()
# REQUERY TO SEE RESULTS
try:
cursor.execute("SELECT * FROM TEAM")
resultSet = cursor.fetchall()
except:
print "\n\n<PRE>"
traceback.print_exc()
sys.exit()
# CONVERT THE LIST OF LISTS INTO A DICTIONARY
# Note: You don't need to do this anymore. Keep reading. -- Andy
resultDict = {}
numColumns = len(cursor.description)-1
numRows = len(resultSet)-1
cursorColumn = 0
cursorRow = 0
# Put Field Names In As Keys
for cursorFieldname in cursor.description:
tempValues = []
tempDict = {}
tempKey = cursorFieldname[0]
while cursorRow <= numRows:
# print resultSet[cursorRow][cursorColumn]
tempValues.append(str(resultSet[cursorRow][cursorColumn]))
cursorRow = cursorRow + 1
tempDict = {tempKey:tempValues}
cursorRow = 0
cursorColumn = cursorColumn + 1
resultDict.update(tempDict)
# The easy way, new in 0.1.3:
# instead of:
# resultDict = cursor.fetchall()
# just use:
# resultDict = cursor.fetchallDict()
# and then you don't need to do all the above stuff.
# This does the dictionary conversion in C, so it's a lot faster.
print "<P>"
print "<B>EXAMPLE OF CONVERTING THE CURSOR DATA INTO A PYTHON DICTIONARY.</B><BR>"
# NOTE- This column set is different, we're producing the rows by dictionary keys and placing values in the cells.
print "<FONT SIZE=\"2\">A different way to slice the data</FONT><P>"
print "<FONT SIZE=\"1\">"
print "<TABLE BORDER=\"1\">"
for cursorFieldname in cursor.description:
print "<TR><TD><FONT FACE=\"arial\" SIZE=\"2\">" +cursorFieldname[0]+ "</FONT></TD>"
print "<TD><FONT FACE=\"arial\" SIZE=\"2\">"
for x in resultDict[cursorFieldname[0]]:
print x
print ","
print "</FONT></TD></TR>"
print "</TABLE>"
print "</CENTER>"
print "&nbsp;<P></FONT><P><HR><P>"
# CLOSING THE DATABASE OBJECT
try:
WebOpsDB.close()
except:
print "\n\n<PRE>"
traceback.print_exc()
sys.exit()
# CONTINUED IN DBTRAINER4
# To learn more about converting result sets into Python dictionary data types, see dbtrainer4.
print "</FONT></BODY>\n"
print "</HTML>\n"

View File

@ -1,58 +0,0 @@
# MySQL dump 6.0
#
# Host: localhost Database: test
#--------------------------------------------------------
# Server version 3.22.24
#
# Table structure for table 'colors'
#
CREATE TABLE COLORS (
COLOR varchar(32) DEFAULT '' NOT NULL,
PRIME_COLOR enum('No','Yes') DEFAULT 'No' NOT NULL,
LAST_DATE timestamp(14) DEFAULT '' NOT NULL,
OPEN_DATE timestamp(14) DEFAULT '' NOT NULL,
PRIMARY KEY (COLOR),
KEY PRIME_COLOR (PRIME_COLOR),
KEY LAST_DATE (LAST_DATE),
KEY OPEN_DATE (OPEN_DATE)
);
#
# Dumping data for table 'colors'
#
INSERT INTO COLORS VALUES ('red','Yes',NOW(),NOW());
INSERT INTO COLORS VALUES ('blue','Yes',NOW(),NOW());
INSERT INTO COLORS VALUES ('green','Yes',NOW(),NOW());
INSERT INTO COLORS VALUES ('yellow','No',NOW(),NOW());
INSERT INTO COLORS VALUES ('orange','No',NOW(),NOW());
INSERT INTO COLORS VALUES ('purple','No',NOW(),NOW());
INSERT INTO COLORS VALUES ('cyan','No',NOW(),NOW());
#
# Table structure for table 'team'
#
CREATE TABLE TEAM (
MEMBER_ID int(11) DEFAULT '0' NOT NULL auto_increment,
FIRST_NAME varchar(32) DEFAULT '' NOT NULL,
LAST_NAME varchar(32) DEFAULT '' NOT NULL,
REMARK varchar(64) DEFAULT '' NOT NULL,
FAV_COLOR varchar(32) DEFAULT '' NOT NULL,
LAST_DATE timestamp(14) DEFAULT '' NOT NULL,
OPEN_DATE timestamp(14) DEFAULT '' NOT NULL,
PRIMARY KEY (MEMBER_ID),
KEY FAV_COLOR (FAV_COLOR),
KEY LAST_DATE (LAST_DATE),
KEY OPEN_DATE (OPEN_DATE)
);
#
# Dumping data for table 'team'
#
INSERT INTO TEAM VALUES (1,'Brad','Stec','Techno Needy','aquamarine',NOW(),NOW());
INSERT INTO TEAM VALUES (2,'Nick','Borders','Meticulous Nick','blue',NOW(),NOW());
INSERT INTO TEAM VALUES (3,'Brittney','McChristy','Data Diva','blue',NOW(),NOW());
INSERT INTO TEAM VALUES (4,'Fuzzy','Logic','The Logic Bunny','cyan',NOW(),NOW());

View File

@ -1,28 +0,0 @@
"""
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.
"""
if __name__=="__main__": print __doc__

View File

@ -1,106 +0,0 @@
#!/usr/bin/env python
"""Setup script for the MySQLdb module distribution."""
import os, sys
from distutils.core import setup
from distutils.extension import Extension
YES = 1
NO = 0
# set this to 1 if you have the thread-safe mysqlclient library
thread_safe_library = NO
# You probably don't have to do anything past this point. If you
# do, please mail me the configuration for your platform. Don't
# forget to include the value of sys.platform and os.name.
mysqlclient = thread_safe_library and "mysqlclient_r" or "mysqlclient"
if sys.platform == "linux-i386": # Red Hat
include_dirs = ['/usr/include/mysql']
library_dirs = ['/usr/lib/mysql']
libraries = [mysqlclient, "z"]
runtime_library_dirs = []
extra_objects = []
elif sys.platform in ("freebsd4", "openbsd2"):
include_dirs = ['/usr/local/include/mysql']
library_dirs = ['/usr/local/lib/mysql']
libraries = [mysqlclient, "z"]
runtime_library_dirs = []
extra_objects = []
elif sys.platform == "win32":
include_dirs = [r'c:\mysql\include']
library_dirs = [r'c:\mysql\lib\opt']
libraries = [mysqlclient, 'zlib', 'msvcrt', 'libcmt',
'wsock32', 'advapi32']
runtime_library_dirs = []
extra_objects = [r'c:\mysql\lib\opt\mysqlclient.lib']
elif os.name == "posix": # most Linux/UNIX platforms
include_dirs = ['/usr/include/mysql']
library_dirs = ['/usr/lib/mysql']
# MySQL-3.23 seems to need libz
libraries = [mysqlclient, "z"]
# On some platorms, this can be used to find the shared libraries
# at runtime, if they are in a non-standard location. Doesn't
# work for Linux gcc.
## runtime_library_dirs = library_dirs
runtime_library_dirs = []
# This can be used on Linux to force use of static mysqlclient lib
## extra_objects = ['/usr/lib/mysql/libmysqlclient.a']
extra_objects = []
else:
raise "UnknownPlatform", "sys.platform=%s, os.name=%s" % \
(sys.platform, os.name)
long_description = \
"""Python interface to MySQL-3.22 and 3.23
MySQLdb is an interface to the popular MySQL database server for Python.
The design goals are:
- Compliance with Python database API version 2.0
- Thread-safety
- Thread-friendliness (threads will not block each other)
- Compatibility with MySQL 3.22 and 3.23
This module should be mostly compatible with an older interface
written by Joe Skinner and others. However, the older version is
a) not thread-friendly, b) written for MySQL 3.21, c) apparently
not actively maintained. No code from that version is used in
MySQLdb. MySQLdb is distributed free of charge under a license
derived from the Python license.
"""
setup (# Distribution meta-data
name = "MySQL-python",
version = "0.3.6",
description = "An interface to MySQL",
long_description=long_description,
author = "Andy Dustman",
author_email = "andy@dustman.net",
url = "http://dustman.net/andy/python/MySQLdb",
# Description of the modules and packages in the distribution
py_modules = ["MySQLdb", "CompatMysqldb",
"_mysql_const.converters",
"_mysql_const.exc",
"_mysql_const.CR",
"_mysql_const.FIELD_TYPE",
"_mysql_const.ER",
"_mysql_const.FLAG",
"_mysql_const.REFRESH",
"_mysql_const.CLIENT",
],
ext_modules = [Extension(
name='_mysql',
sources=['_mysqlmodule.c'],
include_dirs=include_dirs,
library_dirs=library_dirs,
runtime_library_dirs=runtime_library_dirs,
libraries=libraries,
extra_objects=extra_objects,
)],
)