RE: how to get return value of update/delete
"Nidositko, James" <[email protected]> Wed, 26 Oct 2005 11:39:32 -0400
| Newsgroups | gmane.comp.python.sybase |
|---|---|
| Message-ID | <D511E431A087CE46983D5B54404CCCBD17BB3B45@gsnmp20es.firmwide.corp.gs.com> |
Mike, I had some discussions earlier this year with Dave about fixing the rowcount stuff in the recent versions of the Sybase module (0.36 and 0.37). I was under the impression that these fixes had been incorporated and released, but I did not check that before responding to your question. Sorry for the confusion. The last official version that I know of where rowcount() worked was 0.36-pre2. There were extensive changes to the structure of the code between that version and the actual 0.36 release. The rowcount problems were introduced by some of those changes and carried forward into 0.37. I'm assuming that you're using 0.37. The attached copy of Sybase.py fixes the rowcount issues. It is based on the version released with 0.37. Dave, any chance of getting an official release with rowcount() working? -Jim _____ From: mike [mailto:[email protected]] Sent: Wednesday, October 26, 2005 10:56 AM To: Nidositko, James Cc: [email protected] Subject: Re: [python-sybase] how to get return value of update/delete hi thanks for the reply. I went to try the codes out def exec_updtstmt(Svr,Login,Pass,Db,SQL): ''' Connects to database specified, exec the SQL and returns value''' try: db = Sybase.connect(Svr, Login,Pass ,Db) c = db.cursor() try: c.execute(SQL) print "Cursor rowcount after update (no rows) is: %d" % c.rowcount db.commit() db.close() except Sybase.DatabaseError: return 9 except: return 2 stmt = ''' update table set col_1 = 1 where login = "user" ''' exec_updtstmt(Svr,Login,Pass,DbInt,stmt) what i got is "Cursor rowcount after update (no rows) is: -1" and when i checked the table it is updated. Although the update works, i would wish to get that return to indicate to the user whether success or failure . thanks for any further help On 10/26/05, Nidositko, James <[email protected] <mailto:[email protected]> > wrote: Mike, There is no inherent concept of a "return value" from an executed SQL statement. You can produce such a result by encapsulating your SQL statements within stored procedures by detecting the rowcount and setting the return value in response, but there isn't really any need for you to do that. 1) It sounds like the error case that you're trying to describe below should be detected by getting a rowcount of zero from the update. 2) Rowcount does work. Here is some sample code that will show rowcount working in various situations. c=dbc.cursor() print "Cursor rowcount is initialized to: %d" % c.rowcount c.execute ("create table __test_rowcount (col1 varchar(10) NULL)") print "Cursor rowcount after create table is: %d" % c.rowcount c.execute("insert __test_rowcount (col1) values ('asdf')") print "Cursor rowcount after insert 1 is: %d" % c.rowcount c.execute("insert __test_rowcount (col1) values ('asdf')") print "Cursor rowcount after insert 2 is: %d" % c.rowcount c.execute("update __test_rowcount set col1 = 'qwer' where col1 = 'asdf'") print "Cursor rowcount after update is: %d" % c.rowcount c.execute("update __test_rowcount set col1 = 'qwer' where col1 = 'not there'") print "Cursor rowcount after update (no rows) is: %d" % c.rowcount c.execute("select count(*) from __test_rowcount") print "Cursor rowcount after execute for select is: %d" % c.rowcount c.fetchall() print "Cursor rowcount after fetch for select is: %d" % c.rowcount c.execute("delete __test_rowcount where col1 = 'qwer'") print "Cursor rowcount after delete is: %d" % c.rowcount The only unusual case is select. Then, the rowcount is not set until the fetch is performed. -Jim -----Original Message----- From: [email protected] <mailto:[email protected]> [mailto:[email protected] <mailto:[email protected]> ] On Behalf Of [email protected] <mailto:[email protected]> Sent: Tuesday, October 25, 2005 10:00 PM To: [email protected] <mailto:[email protected]> Subject: Python-sybase Digest, Vol 5, Issue 3 Today's Topics: 1. how to get return value of update/delete statement (michael lee) ---------------------------------------------------------------------- Message: 1 Date: Tue, 25 Oct 2005 18:30:07 +0800 From: michael lee <[email protected] <mailto:[email protected]> > Subject: [python-sybase] how to get return value of update/delete statement To: Python Sybase < <mailto:[email protected]> [email protected]> Message-ID: <[email protected] <mailto:[email protected]> > Content-Type: text/plain; charset="iso-8859-1" hi how can i successfully get the return of an update or delete statement using the Sybase module? i am doing a CGI script whereby if a user keys in the wrong name, i would want to catch that error eg if key in wrong username, my CGI script will call Sybase to execute < update table set this = a-value where name = 'wronguser' > and then return a value indicating "not found" but i am not able to figure out how to catch this return value. Any advise? .... cur.execute(update_statement) .... my table is being updated though when i tried a valid user. I tried rowcount but also not working. thanks -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.object-craft.com.au/pipermail/python-sybase/attachments/20051025/ <http://www.object-craft.com.au/pipermail/python-sybase/attachments/20051025 /> 0c35109c/attachment-0001.html ------------------------------ _______________________________________________ Python-sybase mailing list [email protected] <mailto:[email protected]> https://www.object-craft.com.au/cgi-bin/mailman/listinfo/python-sybase <https://www.object-craft.com.au/cgi-bin/mailman/listinfo/python-sybase> End of Python-sybase Digest, Vol 5, Issue 3 ******************************************* _______________________________________________ Python-sybase mailing list [email protected] https://www.object-craft.com.au/cgi-bin/mailman/listinfo/python-sybase
Sybase.py
(application/octet-stream, 31 KB)
#
# Copyright 2001 by Object Craft P/L, Melbourne, Australia.
#
# LICENCE - see LICENCE file distributed with this software for details.
#
try:
import DateTime
use_datetime = 1
except ImportError:
try:
import mx.DateTime
DateTime = mx.DateTime
use_datetime = 1
except ImportError:
use_datetime = 0
import sys
import time
import string
import threading
from sybasect import *
from sybasect import __have_freetds__
set_debug(sys.stderr)
__version__ = '0.37'
# DB-API values
apilevel = '2.0' # DB API level supported
threadsafety = 2 # Threads may share the module
# and connections.
paramstyle = 'named' # Named style,
# e.g. '...WHERE name=@name'
# DB-API exceptions
#
# StandardError
# |__Warning
# |__Error
# |__InterfaceError
# |__DatabaseError
# |__DataError
# |__OperationalError
# |__IntegrityError
# |__InternalError
# |__ProgrammingError
# |__NotSupportedError
class Warning(StandardError):
pass
class Error(StandardError):
def append(self, other):
self.args = (self.args[0] + other.args[0],)
class InterfaceError(Error):
pass
class DatabaseError(Error):
pass
class DataError(DatabaseError):
pass
class OperationalError(DatabaseError):
pass
class IntegrityError(DatabaseError):
pass
class InternalError(DatabaseError):
pass
class ProgrammingError(DatabaseError):
pass
class NotSupportedError(DatabaseError):
pass
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
STRING = DBAPITypeObject(CS_LONGCHAR_TYPE, CS_VARCHAR_TYPE,
CS_TEXT_TYPE, CS_CHAR_TYPE)
BINARY = DBAPITypeObject(CS_IMAGE_TYPE, CS_LONGBINARY_TYPE,
CS_VARBINARY_TYPE, CS_BINARY_TYPE)
NUMBER = DBAPITypeObject(CS_BIT_TYPE, CS_TINYINT_TYPE,
CS_SMALLINT_TYPE, CS_INT_TYPE,
CS_MONEY_TYPE, CS_REAL_TYPE, CS_FLOAT_TYPE,
CS_DECIMAL_TYPE, CS_NUMERIC_TYPE)
DATETIME = DBAPITypeObject(CS_DATETIME4_TYPE, CS_DATETIME_TYPE)
ROWID = DBAPITypeObject(CS_DECIMAL_TYPE, CS_NUMERIC_TYPE)
def OUTPUT(value):
buf = DataBuf(value)
buf.status = CS_RETURN
return buf
def Date(year, month, day):
return datetime('%s-%s-%s' % (year, month, day))
def Time(hour, minute, second):
return datetime('%d:%d:%d' % (hour, minute, second))
def Timestamp(year, month, day, hour, minute, second):
return datetime('%s-%s-%s %d:%d:%d' % (year, month, day,
hour, minute, second))
def DateFromTicks(ticks):
return apply(Date, time.localtime(ticks)[:3])
def TimeFromTicks(ticks):
return apply(Time, time.localtime(ticks)[3:6])
def TimestampFromTicks(ticks):
return apply(Timestamp, time.localtime(ticks)[:6])
def Binary(str):
return str
_output_hooks = {}
def _fmt_server(msg):
parts = []
for label, name in (('Msg', 'msgnumber'),
('Level', 'severity'),
('State', 'state'),
('Procedure', 'proc'),
('Line', 'line')):
value = getattr(msg, name)
if value:
parts.append('%s %s' % (label, value))
text = '%s\n%s' % (string.join(parts, ', '), msg.text)
_ctx.debug_msg(text)
return text
def _fmt_client(msg):
text = 'Layer: %s, Origin: %s\n' \
'%s' % (CS_LAYER(msg.msgnumber), CS_ORIGIN(msg.msgnumber),
msg.msgstring)
_ctx.debug_msg(text)
return text
def _cslib_cb(ctx, msg):
raise Error(_fmt_client(msg))
def _clientmsg_cb(ctx, conn, msg):
raise DatabaseError(_fmt_client(msg))
def _servermsg_cb(ctx, conn, msg):
mn = msg.msgnumber
if mn in (0, 5701, 5703, 5704) or ((mn >= 6200) and (mn < 6300)):
# Non-errors:
# 0 PRINT
# 5701 Changed db context
# 5703 Changed language
# 5704 Changed character set (Sybase)
# 6200-6299 SHOWPLAN output (Sybase)
hook = _output_hooks.get(conn)
if hook:
hook(conn, msg)
else:
raise DatabaseError(_fmt_server(msg))
def _row_bind(cmd, count=1):
'''Bind buffers for count rows of column data.
'''
status, num_cols = cmd.ct_res_info(CS_NUMDATA)
if status != CS_SUCCEED:
raise Error('ct_res_info')
bufs = []
for i in range(num_cols):
status, fmt = cmd.ct_describe(i + 1)
if status != CS_SUCCEED:
raise Error('ct_describe')
fmt.count = count
if fmt.datatype == CS_VARBINARY_TYPE:
fmt.datatype = CS_BINARY_TYPE
if fmt.maxlength > 65536:
fmt.maxlength = 65536
status, buf = cmd.ct_bind(i + 1, fmt)
if status != CS_SUCCEED:
raise Error('ct_bind')
bufs.append(buf)
return bufs
def _column_value(val):
if use_datetime and type(val) is DateTimeType:
return DateTime.DateTime(val.year, val.month + 1, val.day,
val.hour, val.minute,
val.second + val.msecond / 1000.0)
else:
return val
def _extract_row(bufs, n):
'''Extract a row tuple from buffers.
'''
row = [None] * len(bufs)
col = 0
for buf in bufs:
row[col] = _column_value(buf[n])
col = col + 1
return tuple(row)
def _fetch_rows(cmd, bufs, rows):
'''Fetch rows into bufs.
When bound to buffers for a single row, return a row tuple.
When bound to multiple row buffers, return a list of row
tuples.
'''
_ctx.debug_msg('_fetch_rows\n')
status, rows_read = cmd.ct_fetch()
if status == CS_SUCCEED:
pass
elif status == CS_END_DATA:
return 0
elif status in (CS_ROW_FAIL, CS_FAIL, CS_CANCELED):
raise Error('ct_fetch')
if bufs[0].count > 1:
for i in xrange(rows_read):
rows.append(_extract_row(bufs, i))
return rows_read
else:
rows.append(_extract_row(bufs, 0))
return 1
def _bufs_description(bufs):
desc = []
for buf in bufs:
desc.append((buf.name, buf.datatype, 0,
buf.maxlength, buf.precision, buf.scale,
buf.status & CS_CANBENULL))
return desc
# Setup global library context
status, _ctx = cs_ctx_alloc()
if status != CS_SUCCEED:
raise InternalError('cs_ctx_alloc failed')
set_global_ctx(_ctx)
if _ctx.ct_init() != CS_SUCCEED:
raise Error('ct_init')
_ctx.cs_config(CS_SET, CS_MESSAGE_CB, _cslib_cb)
_ctx.ct_callback(CS_SET, CS_CLIENTMSG_CB, _clientmsg_cb)
_ctx.ct_callback(CS_SET, CS_SERVERMSG_CB, _servermsg_cb)
if _ctx.ct_config(CS_SET, CS_NETIO, CS_SYNC_IO) != CS_SUCCEED:
raise Error('ct_config')
class _FetchNow:
def __init__(self, owner):
self._owner = owner
self._conn = owner._conn
self._result_list = []
self._description_list = []
self._rownum = 0
status, self._cmd = self._conn.ct_cmd_alloc()
if status != CS_SUCCEED:
self._raise_error(Error, 'ct_cmd_alloc')
def start(self, arraysize):
self._arraysize = arraysize
status = self._cmd.ct_send()
if status != CS_SUCCEED:
self._raise_error(Error, 'ct_send')
while 1:
try:
status, result = self._cmd.ct_results()
except Exception, e:
self._conn.ct_cancel(CS_CANCEL_ALL)
raise e
if status == CS_END_RESULTS:
if self._description_list:
return self._description_list[0]
return None
elif status != CS_SUCCEED:
self._raise_error(Error, 'ct_results')
if result == CS_ROW_RESULT:
self._row_result()
elif result == CS_STATUS_RESULT:
self._status_result()
elif result == CS_PARAM_RESULT:
self._param_result()
elif result == CS_COMPUTE_RESULT:
self._compute_result()
elif result in (CS_CMD_DONE, CS_CMD_SUCCEED):
status, self.rowcount = self._cmd.ct_res_info(CS_ROW_COUNT)
if status != CS_SUCCEED:
self._raise_error(Error, 'ct_res_info')
elif result not in (CS_CMD_DONE, CS_CMD_SUCCEED):
self._raise_error(Error, 'ct_results')
def _is_idle(self):
return 1
def _raise_error(self, exc, text):
self._conn.ct_cancel(CS_CANCEL_ALL)
raise exc(text)
def _read_result(self):
bufs = _row_bind(self._cmd, self._arraysize)
self._description_list.append(_bufs_description(bufs))
logical_result = []
while _fetch_rows(self._cmd, bufs, logical_result):
pass
self._result_list.append(logical_result)
_row_result = _read_result
_status_result = _read_result
_param_result = _read_result
_compute_result = _read_result
def result_list(self):
return self._result_list
def fetchone(self):
rownum = self._rownum
if self._result_list and rownum < len(self._result_list[0]):
self._rownum = self._rownum + 1
return self._result_list[0][rownum]
def fetchmany(self, num):
if self._result_list:
rownum = self._rownum
rows = self._result_list[0][rownum: rownum + num]
self._rownum = rownum + num
return rows
return []
def fetchall(self):
if self._result_list:
rows = self._result_list[0][self._rownum:]
self._rownum = len(self._result_list[0])
return rows
return []
def nextset(self):
if self._result_list:
del self._result_list[0]
del self._description_list[0]
self._rownum = 0
if self._result_list:
return self._description_list[0]
return None
class _FetchNowParams(_FetchNow):
def start(self, arraysize, params):
self._params = params
return _FetchNow.start(self, arraysize)
def _param_result(self):
bufs = _row_bind(self._cmd, 1)
while 1:
status, rows_read = self._cmd.ct_fetch()
if status == CS_SUCCEED:
pass
elif status == CS_END_DATA:
break
elif status in (CS_ROW_FAIL, CS_FAIL, CS_CANCELED):
self._raise_error(Error, 'ct_fetch')
pos = -1
for buf in bufs:
if type(self._params) is type({}):
self._params[buf.name] = _column_value(buf[0])
else:
while 1:
pos += 1
param = self._params[pos]
if (type(param) is DataBufType
and param.status & CS_RETURN):
break
self._params[pos] = _column_value(buf[0])
def _status_result(self):
bufs = _row_bind(self._cmd, 1)
status_result = []
while _fetch_rows(self._cmd, bufs, status_result):
pass
if len(status_result) == 1:
row = status_result[0]
if len(row) == 1:
self.return_status = row[0]
_LAZY_IDLE = 0 # prepared command
_LAZY_FETCHING = 1 # fetching rows
_LAZY_END_RESULT = 2 # fetching rows
_LAZY_CLOSED = 3 # cursor closed
_state_names = { _LAZY_IDLE: '_LAZY_IDLE',
_LAZY_FETCHING: '_LAZY_FETCHING',
_LAZY_END_RESULT: '_LAZY_END_RESULT',
_LAZY_CLOSED: '_LAZY_CLOSED' }
class _FetchLazy:
def __init__(self, owner):
self._owner = owner
self._conn = owner._conn
self._cmd = None
self._lock_count = 0
self._state = _LAZY_IDLE
self.rowcount = -1
self._open()
def _set_state(self, state):
_ctx.debug_msg('_set_state: %s\n' % _state_names[state])
self._state = state
def _lock(self):
self._lock_count = self._lock_count + 1
_ctx.debug_msg('_lock: count -> %d\n' % self._lock_count)
self._owner._lock()
def _unlock(self):
self._lock_count = self._lock_count - 1
_ctx.debug_msg('_unlock: count -> %d\n' % self._lock_count)
self._owner._unlock()
def _open(self):
self._lock()
try:
status, self._cmd = self._owner._conn.ct_cmd_alloc()
if status != CS_SUCCEED:
self._raise_error(Error, 'ct_cmd_alloc')
self._lock()
self._set_state(_LAZY_IDLE)
finally:
self._unlock()
def _close(self):
if self._state == _LAZY_CLOSED:
return
self._lock()
try:
if self._state != _LAZY_IDLE:
status = self._cmd.ct_cancel(CS_CANCEL_ALL)
if status == CS_SUCCEED:
self._unlock()
self._cmd = None
self._set_state(_LAZY_CLOSED)
finally:
self._unlock()
def __del__(self):
if self._state not in (_LAZY_IDLE, _LAZY_CLOSED):
if self._owner._is_connected:
self._owner._conn.ct_cancel(CS_CANCEL_ALL)
if self._lock_count:
# By the time we get called the threading module might
# have killed the thread the lock was created in ---
# oops.
count, owner = self._owner._connlock._release_save()
self._owner._connlock._acquire_restore((count, threading.currentThread()))
while self._lock_count:
self._unlock()
def _raise_error(self, exc, text):
if self._state not in (_LAZY_IDLE, _LAZY_CLOSED):
if self._owner._conn.ct_cancel(CS_CANCEL_ALL) == CS_SUCCEED:
self._set_state(_LAZY_IDLE)
self._unlock()
raise exc(text)
def _is_idle(self):
return self._state == _LAZY_IDLE
def start(self, arraysize):
self._arraysize = arraysize
self._set_state(_LAZY_FETCHING)
status = self._cmd.ct_send()
if status != CS_SUCCEED:
self._raise_error(Error, 'ct_send')
return self._start_results()
def fetchone(self):
self._lock()
try:
if self._state == _LAZY_IDLE:
self._raise_error(ProgrammingError, 'no result set pending')
if self._state == _LAZY_CLOSED:
self._raise_error(ProgrammingError, 'cursor is closed')
if self._state == _LAZY_FETCHING:
if self._array_pos >= len(self._array):
try:
self._array_pos = 0
self._array = []
_fetch_rows(self._cmd, self._bufs, self._array)
except Error:
status = self._cmd.ct_cancel(CS_CANCEL_ALL)
if status == CS_SUCCEED:
self._set_state(_LAZY_IDLE)
self._unlock()
raise
if self._array_pos < len(self._array):
row = self._array[self._array_pos]
self._array_pos = self._array_pos + 1
return row
self._fetch_rowcount()
self._set_state(_LAZY_END_RESULT)
finally:
self._unlock()
def fetchmany(self, num):
self._lock()
try:
if self._state == _LAZY_IDLE:
self._raise_error(ProgrammingError, 'no result set pending')
if self._state == _LAZY_CLOSED:
self._raise_error(ProgrammingError, 'cursor is closed')
if self._state == _LAZY_FETCHING:
if num == -1:
num = self._arraysize
if num != self._bufs[0].count:
rows = []
for i in xrange(num):
row = self.fetchone()
if not row:
break
rows.append(row)
return rows
elif self._array and self._array_pos < len(self._array):
rows = self._array[self._array_pos:]
else:
try:
rows = []
_fetch_rows(self._cmd, self._bufs, rows)
except Error:
status = self._cmd.ct_cancel(CS_CANCEL_ALL)
if status == CS_SUCCEED:
self._set_state(_LAZY_IDLE)
self._unlock()
raise
self._array = []
self._array_pos = 0
if rows:
return rows
self._fetch_rowcount()
self._set_state(_LAZY_END_RESULT)
return []
finally:
self._unlock()
def fetchall(self):
self._lock()
try:
rows = []
while 1:
row = self.fetchone()
if not row:
break
rows.append(row)
return rows
finally:
self._unlock()
def nextset(self):
self.rowcount = 0
self._lock()
try:
if self._state == _LAZY_CLOSED:
self._raise_error(ProgrammingError, 'cursor is closed')
if self._state == _LAZY_IDLE:
return []
if self._state == _LAZY_FETCHING:
status = self._cmd.ct_cancel(CS_CANCEL_CURRENT)
if status != CS_SUCCEED:
self._raise_error(Error, 'ct_cancel')
return self._start_results()
finally:
self._unlock()
def _start_results(self):
_ctx.debug_msg('_start_results\n')
self._array = []
self._array_pos = 0
while 1:
status, result = self._cmd.ct_results()
if status == CS_END_RESULTS:
if self._state != _LAZY_END_RESULT:
self._unlock()
self._set_state(_LAZY_IDLE)
return None
elif status != CS_SUCCEED:
self._raise_error(Error, 'ct_results')
if result in (CS_COMPUTE_RESULT, CS_CURSOR_RESULT,
CS_PARAM_RESULT, CS_ROW_RESULT, CS_STATUS_RESULT):
if self._arraysize > 0:
bufs = self._bufs = _row_bind(self._cmd, self._arraysize)
else:
bufs = self._bufs = _row_bind(self._cmd)
self._set_state(_LAZY_FETCHING)
return _bufs_description(bufs)
elif result in (CS_CMD_DONE, CS_CMD_SUCCEED):
status, self.rowcount = self._cmd.ct_res_info(CS_ROW_COUNT)
if status != CS_SUCCEED:
self._raise_error(Error, 'ct_res_info')
elif result == CS_CMD_FAIL:
status, self.rowcount = self._cmd.ct_res_info(CS_ROW_COUNT)
self._raise_error(Error, 'ct_results')
else:
self._raise_error(Error, 'ct_results')
def _fetch_rowcount(self):
_ctx.debug_msg('_fetch_rowcount\n')
while 1:
status, result = self._cmd.ct_results()
if status == CS_END_RESULTS:
self._set_state(_LAZY_IDLE)
self._unlock()
return
elif status != CS_SUCCEED:
self._raise_error(Error, 'ct_results')
if result == CS_PARAM_RESULT:
bufs = _row_bind(self._cmd)
while 1:
rows = []
_fetch_rows(self._cmd, bufs, rows)
if not rows:
break
elif result in (CS_CMD_DONE, CS_CMD_SUCCEED):
status, self.rowcount = self._cmd.ct_res_info(CS_ROW_COUNT)
if status != CS_SUCCEED:
self._raise_error(Error, 'ct_res_info')
return
else:
self._raise_error(Error, 'ct_results')
class Cursor:
def __init__(self, owner):
'''Implements DB-API Cursor object
'''
self.description = None # DB-API
self.rowcount = -1 # DB-API
self.arraysize = 1 # DB-API
self._owner = owner
self._fetcher = None
self._closed = 0
def _lock(self):
self._owner._lock()
def _unlock(self):
self._owner._unlock()
def callproc(self, name, params=()):
'''DB-API Cursor.callproc()
'''
_ctx.debug_msg('Cursor.callproc\n')
if self._closed:
raise ProgrammingError('cursor is closed')
self._lock()
try:
# Discard any previous results
self._fetcher = None
self.return_status = None
# Prepare to retrieve new results.
fetcher = self._fetcher = _FetchNowParams(self._owner)
cmd = fetcher._cmd
status = cmd.ct_command(CS_RPC_CMD, name)
if status != CS_SUCCEED:
fetcher._raise_error(Error, 'ct_command')
# Send parameters.
if type(params) is type({}):
out_params = {}
for name, value in params.items():
out_params[name] = value
if isinstance(value, DataBufType):
buf = value
else:
buf = DataBuf(value)
buf.name = name
status = cmd.ct_param(buf)
if status != CS_SUCCEED:
fetcher._raise_error(Error, 'ct_param')
else:
out_params = []
for value in params:
out_params.append(value)
if isinstance(value, DataBufType):
buf = value
else:
buf = DataBuf(value)
status = cmd.ct_param(buf)
if status != CS_SUCCEED:
fetcher._raise_error(Error, 'ct_param')
# Start retreiving results.
self.description = fetcher.start(self.arraysize, out_params)
self.rowcount = fetcher.rowcount
self.return_status = fetcher.return_status
return out_params
finally:
self._unlock()
def close(self):
'''DB-API Cursor.close()
'''
if self._closed:
raise ProgrammingError('cursor is closed')
self._fetcher = None
self._closed = 1
def execute(self, sql, params={}):
'''DB-API Cursor.execute()
'''
_ctx.debug_msg('Cursor.execute\n')
if self._closed:
raise ProgrammingError('cursor is closed')
self._lock()
try:
# Discard any previous results
self._fetcher = None
# Prepare to retrieve new results.
fetcher = self._fetcher = _FetchLazy(self._owner)
cmd = fetcher._cmd
cmd.ct_command(CS_LANG_CMD, sql)
for name, value in params.items():
buf = DataBuf(value)
buf.name = name
status = cmd.ct_param(buf)
if status != CS_SUCCEED:
fetcher._raise_error(Error, 'ct_param')
self.description = fetcher.start(self.arraysize)
self.rowcount = fetcher.rowcount
finally:
self._unlock()
def executemany(self, sql, params_seq=[]):
'''DB-API Cursor.executemany()
'''
_ctx.debug_msg('Cursor.executemany\n')
if self._closed:
raise ProgrammingError('cursor is closed')
self._lock()
try:
for params in params_seq:
self.execute(sql, params)
if not self._fetcher._is_idle():
self._fetcher._raise_error(ProgrammingError, 'fetchable results on cursor')
finally:
self._unlock()
def fetchone(self):
'''DB-API Cursor.fetchone()
'''
if self._closed:
raise ProgrammingError('cursor is closed')
if not self._fetcher:
raise ProgrammingError('query has not been executed')
res = self._fetcher.fetchone()
self.rowcount = self._fetcher.rowcount
return res
def fetchmany(self, num=-1):
'''DB-API Cursor.fetchmany()
'''
if self._closed:
raise ProgrammingError('cursor is closed')
if not self._fetcher:
raise ProgrammingError('query has not been executed')
if num < 0:
num = self.arraysize
res = self._fetcher.fetchmany(num)
self.rowcount = self._fetcher.rowcount
return res
def fetchall(self):
'''DB-API Cursor.fetchall()
'''
if self._closed:
raise ProgrammingError('cursor is closed')
if not self._fetcher:
raise ProgrammingError('query has not been executed')
res = self._fetcher.fetchall()
self.rowcount = self._fetcher.rowcount
return res
def nextset(self):
'''DB-API Cursor.nextset()
'''
if self._closed:
raise ProgrammingError('cursor is closed')
if not self._fetcher:
raise ProgrammingError('query has not been executed')
desc = self._fetcher.nextset()
self.rowcount = self._fetcher.rowcount
if desc:
self.description = desc
return 1
return 0
def setinputsizes(self, *sizes):
'''DB-API Cursor.setinputsizes()
'''
pass
def setoutputsize(self, size, column=None):
'''DB-API Cursor.setoutputsize()
'''
pass
class Connection:
def __init__(self, dsn, user, passwd, database=None,
strip=0, auto_commit=0, delay_connect=0, locking=1):
'''DB-API Sybase.Connect()
'''
self._conn = self._cmd = None
self.dsn = dsn
self.user = user
self.passwd = passwd
self.database = database
self.auto_commit = auto_commit
self._do_locking = locking
self._is_connected = 0
self.arraysize = 32
if locking:
self._connlock = threading.RLock()
# Do not lock in sybasect - we take care if locking in Python.
status, conn = _ctx.ct_con_alloc(0)
if status != CS_SUCCEED:
raise Error('ct_con_alloc')
self._conn = conn
conn.strip = strip
status = conn.ct_con_props(CS_SET, CS_USERNAME, user)
if status != CS_SUCCEED:
self._raise_error(Error, 'ct_con_props')
status = conn.ct_con_props(CS_SET, CS_PASSWORD, passwd)
if status != CS_SUCCEED:
self._raise_error(Error, 'ct_con_props')
if not delay_connect:
self.connect()
def _lock(self):
if self._do_locking:
self._connlock.acquire()
def _unlock(self):
if self._do_locking:
self._connlock.release()
def _raise_error(self, exc, text):
if self._is_connected:
self._conn.ct_cancel(CS_CANCEL_ALL)
raise exc(text)
def connect(self):
conn = self._conn
self._lock()
try:
status = conn.ct_connect(self.dsn)
if status != CS_SUCCEED:
self._raise_error(Error, 'ct_connect')
self._is_connected = 1
status = conn.ct_options(CS_SET, CS_OPT_CHAINXACTS, not self.auto_commit)
if status != CS_SUCCEED:
self._raise_error(Error, 'ct_options')
finally:
self._unlock()
if self.database:
self.execute('use %s' % self.database)
self._dyn_num = 0
def get_property(self, prop):
conn = self._conn
self._lock()
try:
status, value = conn.ct_con_props(CS_GET, prop)
if status != CS_SUCCEED:
self._raise_error(Error, 'ct_con_props')
finally:
self._unlock()
return value
def set_property(self, prop, value):
conn = self._conn
self._lock()
try:
status = conn.ct_con_props(CS_SET, prop, value)
if status != CS_SUCCEED:
self._raise_error(Error, 'ct_con_props')
finally:
self._unlock()
def set_output_hook(self, hook):
if hook is None:
if _output_hooks.has_key(self._conn):
del _output_hooks[self._conn]
else:
_output_hooks[self._conn] = hook
def get_output_hook(self):
return _output_hooks.get(self._conn)
def __del__(self):
if self._conn:
try:
self.close()
except:
pass
def close(self):
'''DBI-API Connection.close()
'''
conn = self._conn
self._lock()
try:
status, result = conn.ct_con_props(CS_GET, CS_CON_STATUS)
if status != CS_SUCCEED:
self._raise_error(Error, 'ct_con_props')
if not result & CS_CONSTAT_CONNECTED:
self._raise_error(ProgrammingError, 'Connection is already closed')
if self._cmd:
self._cmd = None
status = conn.ct_close(CS_FORCE_CLOSE)
if status != CS_SUCCEED:
self._raise_error(Error, 'ct_close')
self._is_connected = 0
finally:
self._unlock()
def begin(self, name=None):
'''Not in DB-API, but useful for Sybase
'''
if name:
self.execute('begin transaction %s' % name)
else:
self.execute('begin transaction')
def commit(self, name=None):
'''DB-API Connection.commit()
'''
if name:
self.execute('commit transaction %s' % name)
else:
self.execute('commit transaction')
def rollback(self, name=None):
'''DB-API Connection.rollback()
'''
if name:
self.execute('rollback transaction %s' % name)
else:
self.execute('rollback transaction')
def cursor(self):
'''DB-API Connection.cursor()
'''
return Cursor(self)
def execute(self, sql):
'''Backwards compatibility
'''
self._lock()
try:
fetcher = _FetchNow(self)
cmd = fetcher._cmd
status = cmd.ct_command(CS_LANG_CMD, sql)
if status != CS_SUCCEED:
self._raise_error(Error, 'ct_command')
fetcher.start(self.arraysize)
return fetcher.result_list()
finally:
self._unlock()
def connect(dsn, user, passwd, database=None,
strip=0, auto_commit=0, delay_connect=0, locking=1):
return Connection(dsn, user, passwd, database,
strip, auto_commit, delay_connect, locking)