mirror of
https://github.com/PyMySQL/mysqlclient.git
synced 2025-08-15 11:10:58 +08:00
Update docs.
result.fetch_row(0,how) returns all rows of the rsult set as a tuple.
This commit is contained in:
@ -1,5 +1,6 @@
|
||||
#author: James Henstridge <james@daa.com.au>
|
||||
#adapted to _mysql by Andy Dustman <adustman@comstar.net>
|
||||
#adapted to _mysql by Andy Dustman <andy@dustman.net>
|
||||
#under no circumstances should you bug James about this!!!
|
||||
|
||||
"""This is a class that implements an interface to mySQL databases, conforming
|
||||
to the API published by the Python db-sig at
|
||||
@ -41,21 +42,10 @@ from string import upper, split, join
|
||||
|
||||
error = 'mysqldb.error'
|
||||
|
||||
_type = {}
|
||||
for a in ('char', 'varchar', 'string', 'unhandled', '????'):
|
||||
_type[a] = 'STRING'
|
||||
for a in ('tiny blob', 'medium blob', 'long blob', 'blob'):
|
||||
_type[a] = 'RAW'
|
||||
for a in ('short', 'long', 'float', 'double', 'decimal'):
|
||||
_type[a] = 'NUMBER'
|
||||
for a in ('date', 'time', 'datetime', 'timestamp'):
|
||||
_type[a] = 'DATE'
|
||||
del a
|
||||
|
||||
from _mysql import FIELD_TYPE
|
||||
_type_conv = { FIELD_TYPE.TINY: int,
|
||||
FIELD_TYPE.SHORT: int,
|
||||
FIELD_TYPE.LONG: int,
|
||||
FIELD_TYPE.LONG: long,
|
||||
FIELD_TYPE.FLOAT: float,
|
||||
FIELD_TYPE.DOUBLE: float,
|
||||
FIELD_TYPE.LONGLONG: long,
|
||||
@ -70,6 +60,33 @@ def isDML(q):
|
||||
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):
|
||||
@ -84,9 +101,10 @@ class Connection:
|
||||
except MySQL.Error, msg:
|
||||
raise error, msg
|
||||
self.__curs = Cursor(self.__conn)
|
||||
self._server_info = i = self.__conn.get_server_info()
|
||||
self._server_version = int(i[0])*10000 + int(i[2:4])*100 + int(i[5:7])
|
||||
|
||||
self.__conn.query("SHOW VARIABLES")
|
||||
self.__vars = {}
|
||||
for k, v in self.__conn.store_result().fetch_row(0):
|
||||
self.__vars[k] = v
|
||||
|
||||
def __del__(self):
|
||||
self.close()
|
||||
@ -109,14 +127,15 @@ class Connection:
|
||||
|
||||
def commit(self):
|
||||
"""Commit the current transaction."""
|
||||
if self._server_version > 32315: self.__conn.query("COMMIT")
|
||||
if self.__vars.get('have_bdb', 'NO') == 'YES':
|
||||
self.__conn.query("COMMIT")
|
||||
|
||||
def rollback(self):
|
||||
"""Rollback the current transaction."""
|
||||
if self._server_version > 32315: self.__conn.query("ROLLBACK")
|
||||
if self.__vars.get('have_bdb', 'NO') == 'YES':
|
||||
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
|
||||
@ -205,12 +224,9 @@ class Cursor:
|
||||
self.__res = self.__conn.query(
|
||||
op % params[-1])
|
||||
self.insert_id = self.__res.insert_id()
|
||||
f = self.__res.fields()
|
||||
except MySQL.Error, msg:
|
||||
raise error, msg
|
||||
self.__dict__['description'] = tuple(map(
|
||||
lambda x: (x[0], _type[x[2]], x[3],
|
||||
x[3]), f))
|
||||
self.__dict__['description'] = self.__res.describe()
|
||||
return None
|
||||
else:
|
||||
try:
|
||||
@ -244,17 +260,10 @@ class Cursor:
|
||||
def fetchall(self):
|
||||
if not self.__res: raise error, "no query made yet."
|
||||
try:
|
||||
rows = r = list(self.__res.fetch_row(self.arraysize))
|
||||
while 1:
|
||||
rows = list(self.__res.fetch_row(self.arraysize))
|
||||
if not rows: break
|
||||
r.extend(rows)
|
||||
return r
|
||||
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."
|
||||
@ -275,16 +284,9 @@ class Cursor:
|
||||
"""This is not a standard part of Python DB API."""
|
||||
if not self.__res: raise error, "no query made yet."
|
||||
try:
|
||||
rows = r = list(self.__res.fetch_row(self.arraysize, 2))
|
||||
while 1:
|
||||
rows = list(self.__res.fetch_row(self.arraysize, 2))
|
||||
if not rows: break
|
||||
r.extend(rows)
|
||||
return r
|
||||
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
|
||||
|
@ -19,9 +19,7 @@ You have two basic options:
|
||||
<p>
|
||||
<enum>
|
||||
<item>
|
||||
Modify the compiler flags in Setup so that it links against the static
|
||||
library. Probably <tt/-static/ will do this for gcc/egcs; YMMV for
|
||||
other C compilers.
|
||||
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
|
||||
@ -38,13 +36,13 @@ 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
|
||||
<sect1>./_mysqlmodule.c:33: mysql.h: No such file or directory
|
||||
<P>
|
||||
It seems that MySQL-3.23 client libraries require libz for gzip
|
||||
compression. Add -lz to the link line in Setup.
|
||||
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. OR: You don't have the MySQL development stuff loaded. If you
|
||||
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
|
||||
@ -52,21 +50,21 @@ that does not have the MySQL client libraries (<tt/libmysqlclient/).
|
||||
|
||||
<sect1>I'm using Windows...
|
||||
<P>Say no more.
|
||||
<P>There is a <tt/compile.py/ script which supposedly gets the job done
|
||||
for Windows, but I can't test it.
|
||||
<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>Not supported. By me, at least. There is a new version on
|
||||
<htmlurl url="http://www.zope.org" name="www.zope.org">
|
||||
that supports MySQLdb without any patching. Use that.
|
||||
<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://starship.python.net/crew/adustman/MySQLdb.html"
|
||||
<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
|
||||
@ -97,18 +95,15 @@ 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() is missing!
|
||||
<p>MySQL doesn't do transactions. <tt/cursor.rollback()/ is supposed to
|
||||
roll back (cancel) the current transaction. If you really need to do
|
||||
this, then you definitely want <tt/cursor.rollback()/ to fail, because
|
||||
it can't do what you want it to do.
|
||||
<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.
|
||||
<p>MySQL-3.23 will, sometime in the near future, support transactions.
|
||||
When this happens, <tt/cursor.commit()/ will actually do something
|
||||
(and may fail if MySQL returns an error or warning condition), and
|
||||
<tt/cursor.rollback()/ will actually exist and undo the current transaction.
|
||||
<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.
|
||||
@ -119,7 +114,7 @@ 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. The patched
|
||||
<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>
|
||||
|
@ -53,7 +53,7 @@ quote_conv = { types.IntType: Thing2Str,
|
||||
|
||||
type_conv = { FIELD_TYPE.TINY: int,
|
||||
FIELD_TYPE.SHORT: int,
|
||||
FIELD_TYPE.LONG: int,
|
||||
FIELD_TYPE.LONG: long,
|
||||
FIELD_TYPE.FLOAT: float,
|
||||
FIELD_TYPE.DOUBLE: float,
|
||||
FIELD_TYPE.LONGLONG: long,
|
||||
@ -144,14 +144,6 @@ def Binary(x): return str(x)
|
||||
|
||||
insert_values = re.compile(r'values\s(\(.+\))', re.IGNORECASE)
|
||||
|
||||
def _fetchall(result, *args):
|
||||
rows = r = list(apply(result.fetch_row, args))
|
||||
while 1:
|
||||
rows = apply(result.fetch_row, args)
|
||||
if not rows: break
|
||||
r.extend(list(rows))
|
||||
return r
|
||||
|
||||
class BaseCursor:
|
||||
|
||||
"""A base for Cursor classes. Useful attributes:
|
||||
@ -256,6 +248,14 @@ class BaseCursor:
|
||||
|
||||
def nextset(self): return None
|
||||
|
||||
def _fetch_row(self): return self._result.fetch_row(1, self._fetch_type)[0]
|
||||
|
||||
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:
|
||||
|
||||
@ -363,16 +363,8 @@ class CursorTupleRowsMixIn:
|
||||
|
||||
_fetch_type = 0
|
||||
|
||||
def _fetch_row(self): return self._result.fetch_row(1, self._fetch_type)[0]
|
||||
|
||||
def _fetch_rows(self, size):
|
||||
return self._result.fetch_row(size, self._fetch_type)
|
||||
|
||||
def _fetch_all_rows(self):
|
||||
return _fetchall(self._result, self.arraysize, self._fetch_type)
|
||||
|
||||
|
||||
class CursorDictRowsMixIn(CursorTupleRowsMixIn):
|
||||
class CursorDictRowsMixIn:
|
||||
|
||||
_fetch_type = 1
|
||||
|
||||
@ -453,9 +445,11 @@ class Connection:
|
||||
self.cursorclass = Cursor
|
||||
self.db = apply(connect, (), kwargs)
|
||||
self.quote_conv[types.StringType] = self.Thing2Literal
|
||||
self._server_info = self.db.get_server_info()
|
||||
i = map(int, split(split(self._server_info, '-')[0],'.'))
|
||||
self._server_version = i[0]*10000 + i[1]*100 + i[2]
|
||||
self.db.query('show variables')
|
||||
r = self.db.store_result()
|
||||
vars = r.fetch_row(0)
|
||||
self._server_vars = {}
|
||||
for k,v in vars: self._server_vars[k] = v
|
||||
if _threading: self.__lock = _threading.Lock()
|
||||
|
||||
if _threading:
|
||||
@ -473,11 +467,13 @@ class Connection:
|
||||
|
||||
def commit(self):
|
||||
"""Commit the current transaction."""
|
||||
if self._server_version > 32315: self.db.query("COMMIT")
|
||||
if self._server_vars.get('have_bdb','NO') == 'YES':
|
||||
self.db.query("COMMIT")
|
||||
|
||||
def rollback(self):
|
||||
"""Rollback the current transaction."""
|
||||
if self._server_version > 32315: self.db.query("ROLLBACK")
|
||||
if self._server_vars.get('have_bdb','NO') == 'YES':
|
||||
self.db.query("ROLLBACK")
|
||||
else: raise NotSupportedError, "Not supported by server"
|
||||
|
||||
def cursor(self, cursorclass=None):
|
||||
@ -496,10 +492,10 @@ class Connection:
|
||||
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 _fetchall(self.db.list_dbs())
|
||||
def list_fields(self, table): return _fetchall(self.db.list_fields(table))
|
||||
def list_processes(self): return _fetchall(self.db.list_processes())
|
||||
def list_tables(self, db): return _fetchall(self.db.list_tables(db))
|
||||
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()
|
||||
|
@ -23,14 +23,21 @@ charge under a license derived from the Python license.
|
||||
<p>
|
||||
<sect2>Linux/UNIX
|
||||
<p>
|
||||
This module is developed on RedHat Linux 5.2 for Intel. It should build without
|
||||
much trouble on most UNIX-like platforms by using the <tt/build.py/ script.
|
||||
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/compile.py/ script
|
||||
However, the <tt/setup.py/ script
|
||||
reportedly gets the job done.
|
||||
Be aware that this is a user-contributed script; the author
|
||||
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>
|
||||
@ -57,19 +64,19 @@ type.
|
||||
|
||||
<sect2>MySQL-3.23
|
||||
<p>
|
||||
MySQLdb has only been lightly tested.
|
||||
MySQL-3.23 is presently in beta (testing) release. Several API
|
||||
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.15, transactions are supported
|
||||
in MySQL using BDB tables. MySQLdb (0.2.2 and up) detects the
|
||||
server version upon connection and will issue <tt/COMMIT/ and <tt/ROLLBACK/
|
||||
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://starship.skyport.net/~lemburg/mxDateTime.html"
|
||||
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
|
||||
@ -109,14 +116,12 @@ 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
|
||||
client library can perform transactions; otherwise <tt>db.rollback()</tt>
|
||||
is not defined
|
||||
server can perform transactions; otherwise <tt>db.rollback()</tt>
|
||||
always fails
|
||||
<caption>Mysqldb to MySQLdb changes</tabular></table>
|
||||
|
||||
<sect1>Zope and ZMySQLDA
|
||||
<p>I'm not distributing a ZMySQLDA patch any more. Somebody else
|
||||
has written a ZMySQLDA that works with MySQLdb. Find it at
|
||||
<htmlurl url="http://www.zope.org/" name="the Zope home site">.
|
||||
<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.
|
||||
@ -132,7 +137,7 @@ 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.2.2, the various fetch_rowXXX() cursor
|
||||
<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>
|
||||
|
@ -880,12 +880,14 @@ _mysql_row_to_dict_old(
|
||||
v = _mysql_field_to_python(c, row[i], length[i]);
|
||||
if (!v) goto error;
|
||||
{
|
||||
int len;
|
||||
char buf[256];
|
||||
strncpy(buf, fields[i].table, 256);
|
||||
len = strlen(buf);
|
||||
strncat(buf, ".", 256-len);
|
||||
len = strlen(buf);
|
||||
int len=0;
|
||||
char buf[256]="";
|
||||
if (strlen(fields[i].table)) {
|
||||
strncpy(buf, fields[i].table, 256);
|
||||
len = strlen(buf);
|
||||
strncat(buf, ".", 256-len);
|
||||
len = strlen(buf);
|
||||
}
|
||||
strncat(buf, fields[i].name, 256-len);
|
||||
PyMapping_SetItemString(r, buf, v);
|
||||
}
|
||||
@ -897,6 +899,45 @@ _mysql_row_to_dict_old(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
typedef PyObject *_PYFUNC(_mysql_ResultObject *, MYSQL_ROW);
|
||||
|
||||
int
|
||||
_mysql__fetch_row(
|
||||
_mysql_ResultObject *self,
|
||||
PyObject *r,
|
||||
int skiprows,
|
||||
int maxrows,
|
||||
_PYFUNC *convert_row)
|
||||
{
|
||||
unsigned int i;
|
||||
MYSQL_ROW row;
|
||||
|
||||
for (i = skiprows; i<(skiprows+maxrows); i++) {
|
||||
PyObject *v;
|
||||
if (!self->use)
|
||||
row = mysql_fetch_row(self->result);
|
||||
else {
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
row = mysql_fetch_row(self->result);
|
||||
Py_END_ALLOW_THREADS;
|
||||
}
|
||||
if (!row && mysql_errno(self->connection)) {
|
||||
_mysql_Exception((_mysql_ConnectionObject *)self->conn);
|
||||
goto error;
|
||||
}
|
||||
if (!row) {
|
||||
if (_PyTuple_Resize(&r, i, 0) == -1) goto error;
|
||||
break;
|
||||
}
|
||||
v = convert_row(self, row);
|
||||
if (!v) goto error;
|
||||
PyTuple_SET_ITEM(r, i, v);
|
||||
}
|
||||
return i-skiprows;
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
_mysql_ResultObject_fetch_row(
|
||||
_mysql_ResultObject *self,
|
||||
@ -912,9 +953,8 @@ _mysql_ResultObject_fetch_row(
|
||||
_mysql_row_to_dict_old
|
||||
};
|
||||
_PYFUNC *convert_row;
|
||||
unsigned int maxrows=1, how=0, i;
|
||||
PyObject *r;
|
||||
MYSQL_ROW row;
|
||||
unsigned int maxrows=1, how=0, skiprows=0, rowsadded;
|
||||
PyObject *r=NULL;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii:fetch_row", kwlist,
|
||||
&maxrows, &how))
|
||||
@ -924,28 +964,30 @@ _mysql_ResultObject_fetch_row(
|
||||
return NULL;
|
||||
}
|
||||
convert_row = row_converters[how];
|
||||
|
||||
if (!(r = PyTuple_New(maxrows))) return NULL;
|
||||
for (i = 0; i<maxrows; i++) {
|
||||
PyObject *v;
|
||||
if (!self->use)
|
||||
row = mysql_fetch_row(self->result);
|
||||
else {
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
row = mysql_fetch_row(self->result);
|
||||
Py_END_ALLOW_THREADS;
|
||||
if (maxrows) {
|
||||
if (!(r = PyTuple_New(maxrows))) goto error;
|
||||
rowsadded = _mysql__fetch_row(self, r, skiprows, maxrows,
|
||||
convert_row);
|
||||
if (rowsadded == -1) goto error;
|
||||
} else {
|
||||
if (self->use) {
|
||||
maxrows = 1000;
|
||||
if (!(r = PyTuple_New(maxrows))) goto error;
|
||||
while (1) {
|
||||
rowsadded = _mysql__fetch_row(self, r, skiprows,
|
||||
maxrows, convert_row);
|
||||
if (rowsadded == -1) goto error;
|
||||
skiprows += rowsadded;
|
||||
if (rowsadded < maxrows) break;
|
||||
}
|
||||
} else {
|
||||
/* XXX if overflow, maxrows<0? */
|
||||
maxrows = (int) mysql_num_rows(self->result);
|
||||
if (!(r = PyTuple_New(maxrows))) goto error;
|
||||
rowsadded = _mysql__fetch_row(self, r, 0,
|
||||
maxrows, convert_row);
|
||||
if (rowsadded == -1) goto error;
|
||||
}
|
||||
if (!row && mysql_errno(self->connection)) {
|
||||
Py_XDECREF(r);
|
||||
return _mysql_Exception((_mysql_ConnectionObject *)self->conn);
|
||||
}
|
||||
if (!row) {
|
||||
if (_PyTuple_Resize(&r, i, 0) == -1) goto error;
|
||||
break;
|
||||
}
|
||||
v = convert_row(self, row);
|
||||
if (!v) goto error;
|
||||
PyTuple_SET_ITEM(r, i, v);
|
||||
}
|
||||
return r;
|
||||
error:
|
||||
|
@ -69,7 +69,7 @@ derived from the Python license.
|
||||
|
||||
setup (# Distribution meta-data
|
||||
name = "MySQL-python",
|
||||
version = "0.3.0",
|
||||
version = "0.3.2",
|
||||
description = "An interface to MySQL",
|
||||
long_description=long_description,
|
||||
author = "Andy Dustman",
|
||||
|
Reference in New Issue
Block a user