[python-sybase] Re: Your test program (sp_test.py) output
Bradley Feldman
bradley at relevantevidence.com
Thu, 17 Mar 2005 23:09:10 -0800
That patch worked for me. I'm getting the output parm back now! =
Hooray!
*Bradley
-----Original Message-----
From: python-sybase-admin@www.object-craft.com.au
[mailto:python-sybase-admin@www.object-craft.com.au] On Behalf Of Dave =
Cole
Sent: Thursday, March 17, 2005 10:38 PM
To: python-sybase@object-craft.com.au
Subject: [python-sybase] Re: Your test program (sp_test.py) output
I keep forgetting to send to the mailing list :-(.
Bradley Feldman wrote:
> Dave:
>=20
> If I run your test program (slightly modded for my environment) on=20
> FreeTDS/MS SQL, here's what I get as output:
>=20
> {'@num': 12345, '@result': <DataBufType object at 0x2a95596770>}=20
> [54321, <DataBufType object at 0x2a95596940>]
>=20
> Attached is the debug trace. Let me know what you discover.
Extremely odd.
The parts of the log to do with calling the stored procedure are:
Cursor.callproc
ct_cmd_alloc(conn0, &cmd) -> CS_SUCCEED, cmd3
Allocated a command structure to send a command to the server.
ct_command(cmd3, CS_RPC_CMD, "sp_test_output", CS_NULLTERM, CS_UNUSED)
-> CS_SUCCEED
Start constructing the command; use an RPC command telling the server to
execute a stored procedure.
ct_param(cmd3, &databuf0->fmt=3D[name:"@result" type:CS_INT_TYPE
status:CS_RETURN format:CS_FMT_UNUSED count:1 maxlength:4 scale:0
precision:0], databuf0->buff, 4, 0) -> CS_SUCCEED
Tell the command that we want to bind a buffer to receive a return =
parameter
(status =3D=3D CS_RETURN) called @result.
ct_param(cmd3, &databuf1->fmt=3D[name:"@num" type:CS_INT_TYPE
status:CS_INPUTVALUE format:CS_FMT_UNUSED count:1 maxlength:4 scale:0
precision:0], databuf1->buff, 4, 0) -> CS_SUCCEED
Tell the command that we have an input parameter called '@num'. The =
value
is already in the associated buffer.
ct_send(cmd3) -> CS_SUCCEED
Send the command to the server.
ct_results(cmd3, &result) -> CS_SUCCEED, CS_STATUS_RESULT
Server says that there is some status returned. We fetch this and =
discard
it.
ct_res_info(cmd3, CS_NUMDATA, &value, CS_UNUSED, NULL) -> CS_SUCCEED, 1
ct_describe(cmd3, 1, &fmt) -> CS_SUCCEED, datafmt0=3D[name:"" =
type:CS_INT_TYPE
status:CS_FALSE format:CS_FMT_UNUSED count:1 maxlength:4 scale:0
precision:0] ct_bind(cmd3, 1, &datafmt0->fmt=3D[name:"" type:CS_INT_TYPE
status:CS_FALSE format:CS_FMT_UNUSED count:1 maxlength:4 scale:0
precision:0], databuf2->buff,
databuf2->copied, databuf2->indicator) -> CS_SUCCEED, databuf2
_fetch_rows
ct_fetch(cmd3, CS_UNUSED, CS_UNUSED, CS_UNUSED, &rows_read) -> =
CS_SUCCEED, 1
_fetch_rows ct_fetch(cmd3, CS_UNUSED, CS_UNUSED, CS_UNUSED, &rows_read) =
->
CS_END_DATA, 0
Status result has been fetched. The next logs are where we get the
parameter results.
ct_results(cmd3, &result) -> CS_SUCCEED, CS_PARAM_RESULT
Server tells us to begin fetching the parameter result set.
ct_res_info(cmd3, CS_NUMDATA, &value, CS_UNUSED, NULL) -> CS_SUCCEED, 1
There is one return parameter.
ct_describe(cmd3, 1, &fmt) -> CS_SUCCEED, datafmt1=3D[name:"@result"
type:CS_INT_TYPE status:CS_FALSE format:CS_FMT_UNUSED count:1 =
maxlength:4
scale:0 precision:0]
It is called '@result' (which is what we expected). The *really* =
strange
thing here is that the status is not CS_RETURN!!! When I run it here =
the
status *is* CS_RETURN. The upshot of this is that the result is ignored =
by
the code in Sybase.py
I think that a fix for this that should work all of the time is to =
change
_FetchNowParams._param_result():
def _param_result(self):
bufs =3D _row_bind(self._cmd, 1)
while 1:
status, rows_read =3D self._cmd.ct_fetch()
if status =3D=3D CS_SUCCEED:
pass
elif status =3D=3D CS_END_DATA:
break
elif status in (CS_ROW_FAIL, CS_FAIL, CS_CANCELED):
self._raise_error(Error, 'ct_fetch')
pos =3D -1
for buf in bufs:
if buf.status & CS_RETURN:
if type(self._params) is type({}):
self._params[buf.name] =3D =
_column_value(buf[0])
else:
while 1:
pos +=3D 1
param =3D self._params[pos]
if (type(param) is DataBufType
and param.status & CS_RETURN):
break
self._params[pos] =3D _column_value(buf[0])
If you just remove the test for buf.status & CS_RETURN it should do the
right thing.
def _param_result(self):
bufs =3D _row_bind(self._cmd, 1)
while 1:
status, rows_read =3D self._cmd.ct_fetch()
if status =3D=3D CS_SUCCEED:
pass
elif status =3D=3D CS_END_DATA:
break
elif status in (CS_ROW_FAIL, CS_FAIL, CS_CANCELED):
self._raise_error(Error, 'ct_fetch')
pos =3D -1
for buf in bufs:
if type(self._params) is type({}):
self._params[buf.name] =3D _column_value(buf[0])
else:
while 1:
pos +=3D 1
param =3D self._params[pos]
if (type(param) is DataBufType
and param.status & CS_RETURN):
break
self._params[pos] =3D _column_value(buf[0])
Let me know how it goes.
- Dave
--=20
http://www.object-craft.com.au
_______________________________________________
Python-sybase mailing list Python-sybase@www.object-craft.com.au
https://www.object-craft.com.au/cgi-bin/mailman/listinfo/python-sybase