Initial revision

This commit is contained in:
adustman
2001-05-09 02:23:14 +00:00
parent 38075e7264
commit fce05481aa
19 changed files with 3422 additions and 0 deletions

318
MySQLdb/CompatMysqldb.py Executable file
View File

@ -0,0 +1,318 @@
"""
Original author: James Henstridge <james@daa.com.au>
Adapted by: Andy Dustman <andy@dustman.net>
This is the original Mysqldb.py module which came with MySQLmodule-1.4,
only it has been adapted to use _mysql instead MySQL. It is intended
for backwards compatibility purposes only. But as a bonus, transactions
will work if your database server and table types support them. It is
called CompatMysqldb instead of Mysqldb so as not to interfere with an
existing Mysqldb, or MySQLdb on case-insensitive brain-dead operating
systems.
Under no circumstances should you bug James Henstridge about this!!!
-----
This is a class that implements an interface to mySQL databases, conforming
to the API published by the Python db-sig at
http://www.python.org/sigs/db-sig/DatabaseAPI.html
It is really just a wrapper for an older python interface to mySQL databases
called mySQL, which I modified to facilitate use of a cursor. That module was
Joseph Skinner's port of the mSQL module by David Gibson, which was a modified
version of Anthony Baxter's msql module.
As an example, to add some extra (unprivelledged) users to your database system,
and delete them again:
>>> import Mysqldb
>>> conn = Mysqldb.mysqldb('mysql@localhost root rootpasswd')
>>> curs = conn.cursor()
>>> curs.execute("insert into user (host, user) values ('%s', '%s')",
... [('localhost', 'linus'), ('somewhere.com.au', 'james')])
2
>>> curs.execute("select * from user")
>>> curs.fetchall()
-- record listing --
>>> curs.execute("delete from user where host = 'somewhere.com.au' or user = 'linus'")
2
>>> curs.close()
>>> conn.close()
The argument to mysqldb.mysqldb is of the form 'db@host user pass',
'db@host user', 'db@host', 'db', 'db user pass' or 'db user'.
As always, the source is a good manual :-)
James Henstridge <james@daa.com.au>
"""
import _mysql
MySQL = _mysql
from string import upper, split, join
error = 'mysqldb.error'
from MySQLdb.constants import FIELD_TYPE
_type_conv = { FIELD_TYPE.TINY: int,
FIELD_TYPE.SHORT: int,
FIELD_TYPE.LONG: long,
FIELD_TYPE.FLOAT: float,
FIELD_TYPE.DOUBLE: float,
FIELD_TYPE.LONGLONG: long,
FIELD_TYPE.INT24: int,
FIELD_TYPE.YEAR: int }
def isDDL(q):
return upper(split(q)[0]) in ('CREATE', 'ALTER', 'GRANT', 'REVOKE',
'DROP', 'SET')
def isDML(q):
return upper(split(q)[0]) in ('DELETE', 'INSERT', 'UPDATE', 'LOAD')
def isDQL(q):
return upper(split(q)[0]) in ('SELECT', 'SHOW', 'DESC', 'DESCRIBE')
class DBAPITypeObject:
def __init__(self,*values):
self.values = values
def __cmp__(self,other):
if other in self.values:
return 0
if other < self.values:
return 1
else:
return -1
_Set = DBAPITypeObject
STRING = _Set(FIELD_TYPE.CHAR, FIELD_TYPE.ENUM, FIELD_TYPE.INTERVAL,
FIELD_TYPE.SET, FIELD_TYPE.STRING, FIELD_TYPE.VAR_STRING)
BINARY = _Set(FIELD_TYPE.BLOB, FIELD_TYPE.LONG_BLOB, FIELD_TYPE.MEDIUM_BLOB,
FIELD_TYPE.TINY_BLOB)
NUMBER = _Set(FIELD_TYPE.DECIMAL, FIELD_TYPE.DOUBLE, FIELD_TYPE.FLOAT,
FIELD_TYPE.INT24, FIELD_TYPE.LONG, FIELD_TYPE.LONGLONG,
FIELD_TYPE.TINY, FIELD_TYPE.YEAR)
DATE = _Set(FIELD_TYPE.DATE, FIELD_TYPE.NEWDATE)
TIME = _Set(FIELD_TYPE.TIME)
TIMESTAMP = _Set(FIELD_TYPE.TIMESTAMP, FIELD_TYPE.DATETIME)
ROWID = _Set()
class Connection:
"""This is the connection object for the mySQL database interface."""
def __init__(self, host, user, passwd, db):
from MySQLdb.constants import CLIENT
kwargs = {}
kwargs['conv'] = _type_conv
if host: kwargs['host'] = host
if user: kwargs['user'] = user
if passwd: kwargs['passwd'] = passwd
if db: kwargs['db'] = db
try:
self.__conn = apply(MySQL.connect, (), kwargs)
except MySQL.Error, msg:
raise error, msg
self.__curs = Cursor(self.__conn)
self.__transactional = self.__conn.server_capabilities & CLIENT.TRANSACTIONS
def __del__(self):
self.close()
def __getattr__(self, key):
return getattr(self.__curs, key)
def __setattr__(self, key, val):
if key in ('arraysize', 'description', 'insert_id'):
setattr(self.__curs, key, val)
else:
self.__dict__[key] = val
def close(self):
self.__conn = None
def cursor(self):
if self.__conn == None: raise error, "Connection is closed."
return Cursor(self.__conn)
def commit(self):
"""Commit the current transaction."""
if self.__transactional:
self.__conn.query("COMMIT")
def rollback(self):
"""Rollback the current transaction."""
if self.__transactional:
self.__conn.query("ROLLBACK")
else: raise error, "Not supported by server"
def callproc(self, params=None): pass
# These functions are just here so that every action that is
# covered by mySQL is covered by mysqldb. They are not standard
# DB API. The list* methods are not included, since they can be
# done with the SQL SHOW command.
def create(self, dbname):
"""This is not a standard part of Python DB API."""
self.__conn.query("CREATE DATABASE %s" % dbname)
self.__conn.store_result()
return None
def drop(self, dbname):
"""This is not a standard part of Python DB API."""
self.__conn.query("DROP DATABASE %s" % dbname)
self.__conn.store_result()
return None
def reload(self):
"""This is not a standard part of Python DB API."""
self.__conn.query("RELOAD TABLES")
self.__conn.store_result()
return None
def shutdown(self):
"""This is not a standard part of Python DB API."""
return self.__conn.shutdown()
class Cursor:
"""A cursor object for use with connecting to mySQL databases."""
def __init__(self, conn):
self.__conn = conn
self.__res = None
self.arraysize = 1
self.__dict__['description'] = None
self.__open = 1
self.insert_id = 0
def __del__(self):
self.close()
def __setattr__(self, key, val):
if key == 'description':
raise error, "description is a read-only attribute."
else:
self.__dict__[key] = val
def __delattr__(self, key):
if key in ('description', 'arraysize', 'insert_id'):
raise error, "%s can't be deleted." % (key,)
else:
del self.__dict__[key]
def close(self):
self.__conn = None
self.__res = None
self.__open = 0
def execute(self, op, params=None):
if not self.__open: raise error, "Cursor has been closed."
if params:
if type(params[0]) not in (type(()), type([])):
params = [params]
if isDDL(op):
self.__dict__['description'] = None
try:
for x in params:
self.__res = \
self.__conn.query(op % x)
self.insert_id = self.__res.insert_id()
except MySQL.Error, msg:
raise error, msg
return 1
if isDML(op):
self.__dict__['description'] = None
af = 0
try:
for x in params:
self.__res = \
self.__conn.query(op % x)
af =af+self.__res.affectedrows()
self.insert_id = self.__res.insert_id()
except MySQL.Error, msg:
raise error, msg
return af
if isDQL(op):
try:
self.__res = self.__conn.query(
op % params[-1])
self.insert_id = self.__res.insert_id()
except MySQL.Error, msg:
raise error, msg
self.__dict__['description'] = self.__res.describe()
return None
else:
try:
self.__conn.query(op)
self.__res = self.__conn.store_result()
self.insert_id = self.__conn.insert_id()
except MySQL.Error, msg:
raise error, msg
self.__dict__['description'] = None
if isDDL(op):
return 1
elif self.__conn.affected_rows() != -1:
return self.__conn.affected_rows()
else:
self.__dict__['description'] = self.__res.describe()
return None
def fetchone(self):
if not self.__res: raise error, "no query made yet."
try:
return self.__res.fetch_row(1)[0]
except MySQL.Error, msg:
raise error, msg
def fetchmany(self, size=None):
if not self.__res: raise error, "no query made yet."
try:
return self.__res.fetch_row(size or self.arraysize)
except MySQL.Error, msg:
raise error, msg
def fetchall(self):
if not self.__res: raise error, "no query made yet."
try:
return self.__res.fetch_row(0)
except MySQL.Error, msg:
raise error, msg
def fetchoneDict(self):
"""This is not a standard part of Python DB API."""
if not self.__res: raise error, "no query made yet."
try:
return self.__res.fetch_row(1, 2)[0]
except MySQL.Error, msg:
raise error, msg
def fetchmanyDict(self, size=None):
"""This is not a standard part of Python DB API."""
if not self.__res: raise error, "no query made yet."
try:
return self.__res.fetch_row(size or self.arraysize, 2)
except MySQL.Error, msg:
raise error, msg
def fetchallDict(self):
"""This is not a standard part of Python DB API."""
if not self.__res: raise error, "no query made yet."
try:
return self.__res.fetch_row(0,2)
except MySQL.Error, msg:
raise error, msg
def setinputsizes(self, sizes): pass
def setoutputsize(self, size, col=None): pass
def mysqldb(connect_string):
"""Makes a connection to the MySQL server. The Argument should be of
the form 'db@host user pass' or 'db@host user' or 'db@host' or 'db'
or 'db user pass' or 'db user', where db is the database name, host
is the server's host name, user is your user name, and pass is your
password."""
val = split(connect_string)
if len(val) == 0: raise error, "no database specified"
while len(val) < 3: val.append('')
dh = split(val[0], '@')
if len(dh) == 0: raise error, "no database specified"
while len(dh) < 2: dh.append('')
return Connection(dh[1], val[1], val[2], dh[0])

9
MySQLdb/MANIFEST.in Normal file
View File

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

View File

@ -0,0 +1,82 @@
"""MySQLdb - A DB API v2.0 compatible interface to MySQL.
This package is a wrapper around _mysql, which mostly implements the
MySQL C API.
connect() -- connects to server
See the C API specification and the MySQL documentation for more info
on other items.
For information on how MySQLdb handles type conversion, see the
MySQLdb.converters module.
"""
__author__ = "Andy Dustman <andy@dustman.net>"
__revision__ = """$Revision$"""[11:-2]
version_info = (
0,
9,
0,
"beta",
1)
if version_info[3] == "final": __version__ = "%d.%d.%d" % version_info[:3]
else: __version__ = "%d.%d.%d%1.1s%d" % version_info[:5]
import _mysql
if __version__ != getattr(_mysql, '__version__', None):
raise ImportError, "this is MySQLdb version %s, but _mysql is version %s" %\
(__version__, _mysql.__version__)
threadsafety = 2
apilevel = "2.0"
paramstyle = "format"
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
from constants import FIELD_TYPE
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)
from _mysql import *
from connections import Connection
def Connect(*args, **kwargs):
"""Factory function for connections.Connection."""
return apply(Connection, args, kwargs)
connect = Connect
__all__ = ['BINARY', 'Binary', 'Connect', 'Connection', 'DATE', 'DataError', 'DatabaseError', 'Error', 'FIELD_TYPE', 'IntegrityError', 'InterfaceError', 'InternalError', 'MySQLError', 'NULL', 'NUMBER', 'NotSupportedError', 'OperationalError', 'ProgrammingError', 'ROWID', 'STRING', 'TIME', 'TIMESTAMP', 'Warning', 'apilevel', 'connect', 'connections', 'constants', 'cursors', 'debug', 'escape', 'escape_dict', 'escape_sequence', 'escape_string', 'get_client_info', 'paramstyle', 'string_literal', 'threadsafety', 'version_info']

View File

@ -0,0 +1,209 @@
"""MySQLdb Connections Module
This module implements connections for MySQLdb. Presently there is
only one class: Connection. Others are unlikely. However, you might
want to make your own subclasses. In most cases, you will probably
override Connection.default_cursor with a non-standard Cursor class.
"""
import cursors
from _mysql_exceptions import NotSupportedError, ProgrammingError
class Connection:
"""Create a connection to the database. It is strongly recommended
that you only use keyword parameters. "NULL pointer" indicates that
NULL will be passed to mysql_real_connect(); the value in parenthesis
indicates how MySQL interprets the NULL. Consult the MySQL C API
documentation for more information.
host -- string, host to connect to or NULL pointer (localhost)
user -- string, user to connect as or NULL pointer (your username)
passwd -- string, password to use or NULL pointer (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 -- conversion dictionary, see MySQLdb.converters
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()
cursorclass -- class object, used to create cursors or cursors.Cursor.
This parameter MUST be specified as a keyword parameter.
threads -- boolean, if false threading is disabled, otherwise threads
are enabled by default. (MUST be a keyword parameter.)
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.
"""
default_cursor = cursors.Cursor
def __init__(self, *args, **kwargs):
from _mysql import connect
from constants import CLIENT
from converters import conversions
import types
kwargs2 = kwargs.copy()
self.__threads = kwargs.get('threads',1)
if kwargs.has_key('threads'):
del kwargs2['threads']
if not kwargs.has_key('conv'):
kwargs2['conv'] = conversions.copy()
if kwargs.has_key('cursorclass'):
self.cursorclass = kwargs['cursorclass']
del kwargs2['cursorclass']
else:
self.cursorclass = self.default_cursor
self._db = apply(connect, args, kwargs2)
self._db.converter[types.StringType] = self._db.string_literal
self._transactional = self._db.server_capabilities & CLIENT.TRANSACTIONS
self._autocommit = 1
if self.__threads:
# __c_lock: connection lock. Cursors must always obtain the
# connection lock before doing any queries. A blocking
# call is used. If the same thread tries to acquire the
# lock, produce an error.
#
# _t_lock: transaction lock. If operating transactionally,
# Cursors must acquire the transaction lock on the first
# query. The same thread may acquire the lock more than
# once. commit() or rollback() or an error releases this
# lock.
import threading
self.__c_lock = threading.Lock()
self.__c_locker = None
self.__t_lock = threading.Lock()
self.__t_locker = None
def __del__(self):
self.close()
def _begin(self):
"""Obtain the transaction lock. A thread may try to obtain this
lock multiple times."""
if not self.__threads: return
import threading
me = threading.currentThread()
if self.__t_locker == me: return
self.__t_lock.acquire()
self.__t_locker = me
def _end(self):
"""Release the transaction lock. If a thread tries to release this
lock when it is not currently locking it, it does nothing."""
if not self.__threads: return
import threading
me = threading.currentThread()
if self.__t_locker != me: return
self.__t_locker = None
self.__t_lock.release()
def _acquire(self):
"""Acquire the connection. ProgrammingError is raised if the
thread has already acquired the connection."""
if not self.__threads: return
import threading
me = threading.currentThread()
if self.__c_locker == me:
raise ProgrammingError, "would produce deadlock"
self.__c_lock.acquire()
self.__c_locker = me
def _release(self):
"""Release the connection. If a thread tries to release this
lock when it is not currently locking it, ProgrammingError
is raised (this shouldn't happen)."""
if not self.__threads: return
import threading
me = threading.currentThread()
if self.__c_locker != me:
if not self.__c_locker: return
raise ProgrammingError, "tried to release another %s's lock" % self.__c_locker
self.__c_locker = None
self.__c_lock.release()
def close(self):
"""Close the connection. No further activity possible."""
self._db.close()
def autocommit(self, v):
"""Turn autocommit on or off."""
self._db.query("SET AUTOCOMMIT=%d"%v)
self._transactional = not v
self._autocommit = v
def begin(self):
"""Explicitly begin a transaction. Non-standard."""
self._db.query("BEGIN")
self._transactional = 1
def commit(self):
"""Commit the current transaction."""
try:
if self._transactional:
self._db.query("COMMIT")
finally:
self._end()
self._transactional = not self._autocommit
def rollback(self):
"""Rollback the current transaction."""
try:
if self._transactional:
self._db.query("ROLLBACK")
else:
raise NotSupportedError, "Not supported by server"
finally:
self._end()
self._transactional = not self._autocommit
def cursor(self, cursorclass=None):
"""Create a cursor on which queries may be performed. The
optional cursorclass parameter is used to create the
Cursor. By default, self.cursorclass=cursors.Cursor is
used."""
return (cursorclass or self.cursorclass)(self)
# 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)

View File

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

@ -0,0 +1,30 @@
"""MySQL Connection Errors
Nearly all of these raise OperationalError. COMMANDS_OUT_OF_SYNC
raises ProgrammingError.
"""
MIN_ERROR = 2000
MAX_ERROR = 2999
UNKNOWN_ERROR = 2000
SOCKET_CREATE_ERROR = 2001
CONNECTION_ERROR = 2002
CONN_HOST_ERROR = 2003
IPSOCK_ERROR = 2004
UNKNOWN_HOST = 2005
SERVER_GONE_ERROR = 2006
VERSION_ERROR = 2007
OUT_OF_MEMORY = 2008
WRONG_HOST_INFO = 2009
LOCALHOST_CONNECTION = 2010
TCP_CONNECTION = 2011
SERVER_HANDSHAKE_ERR = 2012
SERVER_LOST = 2013
COMMANDS_OUT_OF_SYNC = 2014
NAMEDPIPE_CONNECTION = 2015
NAMEDPIPEWAIT_ERROR = 2016
NAMEDPIPEOPEN_ERROR = 2017
NAMEDPIPESETSTATE_ERROR = 2018
CANT_READ_CHARSET = 2019
NET_PACKET_TOO_LARGE = 2020

View File

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

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

@ -0,0 +1,23 @@
"""MySQL FLAG Constants
These flags are used along with the FIELD_TYPE to indicate various
properties of columns in a result set.
"""
NOT_NULL = 1
PRI_KEY = 2
UNIQUE_KEY = 4
MULTIPLE_KEY = 8
BLOB = 16
UNSIGNED = 32
ZEROFILL = 64
BINARY = 128
ENUM = 256
AUTO_INCREMENT = 512
TIMESTAMP = 1024
SET = 2048
NUM = 32768
PART_KEY = 16384
GROUP = 32768
UNIQUE = 65536

View File

@ -0,0 +1,17 @@
"""MySQL REFRESH Constants
These constants seem to mostly deal with things internal to the
MySQL server. Forget you saw this.
"""
GRANT = 1
LOG = 2
TABLES = 4
HOSTS = 8
STATUS = 16
THREADS = 32
SLAVE = 64
MASTER = 128
READ_LOCK = 16384
FAST = 32768

View File

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

View File

@ -0,0 +1,187 @@
"""MySQLdb type conversion module
This module handles all the type conversions for MySQL. If the default
type conversions aren't what you need, you can make your own. The
dictionary conversions maps some kind of type to a conversion function
which returns the corresponding value:
Key: FIELD_TYPE.* (from MySQLdb.constants)
Conversion function:
Arguments: string
Returns: Python object
Key: Python type object (from types) or class
Conversion function:
Arguments: Python object of indicated type or class AND
conversion dictionary
Returns: SQL literal value
Notes: Most conversion functions can ignore the dictionary, but
it is a required parameter. It is necessary for converting
things like sequences and instances.
Don't modify conversions if you can avoid it. Instead, make copies
(with the copy() method), modify the copies, and then pass them to
MySQL.connect().
"""
from _mysql import string_literal, escape_sequence, escape_dict, escape, NULL
from constants import FIELD_TYPE
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, d)
def Instance2Str(o, d):
"""Convert an Instance to a string representation. If the
__str__() method produces acceptable output, then you don't need
to add the class to conversions; it will be handled by the default
converter. If the exact class is not found in d, it will use the
first class it can find for which o is an instance."""
if 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)
conversions = {
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
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, deprecated
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
conversions[FIELD_TYPE.TIMESTAMP] = mysql_timestamp_converter
conversions[FIELD_TYPE.DATETIME] = DateTime_or_None
conversions[FIELD_TYPE.TIME] = TimeDelta_or_None
conversions[FIELD_TYPE.DATE] = Date_or_None
def DateTime2literal(d, c):
"""Format a DateTime object as an ISO timestamp."""
return escape(format_TIMESTAMP(d),c)
def DateTimeDelta2literal(d, c):
"""Format a DateTimeDelta object as a time."""
return escape(format_TIME(d),c)
conversions[DateTimeType] = DateTime2literal
conversions[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__ = [ 'conversions', 'DateFromTicks', 'TimeFromTicks',
'TimestampFromTicks', 'format_DATE', 'format_TIME',
'format_TIMESTAMP' ]

390
MySQLdb/MySQLdb/cursors.py Normal file
View File

@ -0,0 +1,390 @@
"""MySQLdb Cursors
This module implements Cursors of various types for MySQLdb. By
default, MySQLdb uses the Cursor class.
"""
import re
insert_values = re.compile(r'values\s(\(.+\))', re.IGNORECASE)
from _mysql import escape, ProgrammingError, Warning
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.__conn = connection
self.description = None
self.rowcount = -1
self.arraysize = 100
self._executed = None
self._transaction = 0
self.__c_locked = 0
def __del__(self):
self.close()
def close(self):
"""Close the cursor. No further queries will be possible."""
if not self.__conn: return
self._end()
self.__conn = None
self._executed = None
self._transaction = None
def _check_executed(self):
if not self._executed:
raise ProgrammingError, "execute() first"
def setinputsizes(self, *args):
"""Does nothing, required by DB API."""
def setoutputsizes(self, *args):
"""Does nothing, required by DB API."""
def _get_db(self):
if not self.__conn:
raise ProgrammingError, "cursor closed"
return self.__conn._db
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"""
from types import ListType, TupleType
qc = self._get_db().converter
if not args:
r = self._query(query)
elif type(args) is ListType and type(args[0]) is TupleType:
r = self.executemany(query, args) # deprecated
else:
try:
r = 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
self._executed = query
return r
def executemany(self, query, args):
"""Execute a multi-row query.
query -- string, query to execute on server
args -- sequence of sequences or mappings, parameters to use with
query. 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."""
from string import join
qc = self._get_db().converter
m = insert_values.search(query)
if not m: raise ProgrammingError, "can't find values"
p = m.start(1)
qv = query[p:]
qargs = escape(args, qc)
try:
q = [ query % qargs[0] ]
for a in qargs[1:]: q.append( qv % a )
except TypeError, msg:
if msg.args[0] in ("not enough arguments for format string",
"not all arguments converted"):
raise ProgrammingError, (0, msg.args[0])
else:
raise
r = self._query(join(q,',\n'))
self._executed = query
return r
def __do_query(self, q):
from string import split, atoi
db = self._get_db()
if self._transaction: self._begin()
try:
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()
except:
self._end()
raise
return self.rowcount
def _check_for_warnings(self): pass
_query = __do_query
def info(self):
"""Return some information about the last query (db.info())"""
self._check_executed()
return self._info
def insert_id(self):
"""Return the last inserted ID on an AUTO_INCREMENT columns."""
self._check_executed()
return self._insert_id
def nextset(self):
"""Does nothing. Required by DB API."""
self._check_executed()
return None
def _fetch_row(self, size=1):
return self._result.fetch_row(size, self._fetch_type)
def _begin(self):
self.__conn._begin()
self._transaction = 1
def _end(self):
self._transaction = 0
self.__conn._end()
def _acquire(self):
if self.__c_locked: return
self.__conn._acquire()
self.__c_locked = 1
def _release(self):
if not self.__conn: return
self.__conn._release()
self.__c_locked = 0
def _is_transactional(self):
return self.__conn._transactional
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 __init__(self, connection):
BaseCursor.__init__(self, connection)
self._acquire()
def _get_result(self): return self._get_db().store_result()
def close(self):
"""Close the cursor. Further queries will not be possible."""
self._rows = ()
BaseCursor.close(self)
def _query(self, q):
self._acquire()
try:
rowcount = self._BaseCursor__do_query(q)
self._rows = self._result and self._fetch_row(0) or ()
self._pos = 0
del self._result
if not self._is_transactional: self._end()
return rowcount
finally:
self._release()
def fetchone(self):
"""Fetches a single row from the cursor."""
self._check_executed()
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."""
self._check_executed()
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."""
self._check_executed()
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."""
self._check_executed()
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."""
self._check_executed()
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 close(self):
"""Close the cursor. No further queries can be executed."""
self._release()
self._result = None
BaseCursor.close(self)
def _get_result(self): return self._get_db().use_result()
def fetchone(self):
"""Fetches a single row from the cursor."""
self._check_executed()
r = self._fetch_row(1)
return r and r[0] or None
def fetchmany(self, size=None):
"""Fetch up to size rows from the cursor. Result set may be smaller
than size. If size is not defined, cursor.arraysize is used."""
self._check_executed()
return self._fetch_row(size or self.arraysize)
def fetchall(self):
"""Fetchs all available rows from the cursor."""
self._check_open()
return self._fetch_row(0)
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):
"""Fetch a single row as a dictionary. Deprecated:
Use fetchone() instead."""
return self.fetchone()
def fetchmanyDict(self, size=None):
"""Fetch several rows as a list of dictionaries. Deprecated:
Use fetchmany() instead."""
return self.fetchmany(size)
def fetchallDict(self):
"""Fetch all available rows as a list of dictionaries. Deprecated:
Use fetchall() instead."""
return self.fetchall()
class CursorOldDictRowsMixIn(CursorDictRowsMixIn):
"""This is a MixIn class that returns rows as dictionaries with
the same key convention as the old Mysqldb (MySQLmodule). Don't
use this."""
_fetch_type = 2
class 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."""

26
MySQLdb/PKG-INFO Normal file
View File

@ -0,0 +1,26 @@
Metadata-Version: 1.0
Name: MySQL-python
Version: 0.9.0a3
Summary: An interface to MySQL
Home-page: http://dustman.net/andy/python/MySQLdb
Author: Andy Dustman
Author-email: andy@dustman.net
License: UNKNOWN
Description: Python interface to MySQL-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.23 and later
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 free software.
Platform: UNKNOWN

57
MySQLdb/README Normal file
View File

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

1613
MySQLdb/_mysql.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,83 @@
"""_mysql_exceptions: Exception classes for _mysql and MySQLdb.
These classes are dictated by the DB API v2.0:
http://www.python.org/topics/database/DatabaseAPI-2.0.html
"""
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

1
MySQLdb/_mysql_version.h Normal file
View File

@ -0,0 +1 @@
static char _mysql__version__[] = "0.9.0b1";

109
MySQLdb/setup.py Normal file
View File

@ -0,0 +1,109 @@
#!/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.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.23 and later
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 free software.
"""
setup (# Distribution meta-data
name = "MySQL-python",
version = "0.9.0b1",
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 = ["CompatMysqldb",
"_mysql_exceptions",
"MySQLdb.converters",
"MySQLdb.connections",
"MySQLdb.cursors",
"MySQLdb.constants.CR",
"MySQLdb.constants.FIELD_TYPE",
"MySQLdb.constants.ER",
"MySQLdb.constants.FLAG",
"MySQLdb.constants.REFRESH",
"MySQLdb.constants.CLIENT",
],
ext_modules = [Extension(
name='_mysql',
sources=['_mysql.c'],
include_dirs=include_dirs,
library_dirs=library_dirs,
runtime_library_dirs=runtime_library_dirs,
libraries=libraries,
extra_objects=extra_objects,
)],
)