From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Fri Jan 13 11:13:17 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 11:13:17 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 11:13:17 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 11:13:17 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 11:13:17 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 11:13:17 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 11:13:17 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 11:13:17 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 11:13:17 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 11:13:17 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 11:13:17 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 11:13:17 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 11:13:17 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 11:13:17 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 11:13:17 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 11:13:17 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 11:13:17 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 11:13:17 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 11:13:17 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Fri Jan 13 15:13:50 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0001.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 15:13:50 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 15:13:50 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 15:13:50 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 15:13:50 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 15:13:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 15:13:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 15:13:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 15:13:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 15:13:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 15:13:50 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 15:13:50 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 15:13:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 15:13:50 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 15:13:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 15:13:50 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 15:13:50 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 15:13:50 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 15:13:50 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Fri Jan 13 15:21:12 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0002.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 15:21:12 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 15:21:12 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 15:21:12 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 15:21:12 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 15:21:12 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 15:21:12 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 15:21:13 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 15:21:13 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 15:21:13 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 15:21:13 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 15:21:13 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 15:21:13 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 15:21:13 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 15:21:13 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 15:21:13 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 15:21:13 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 15:21:13 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 15:21:13 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Fri Jan 13 16:00:45 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0003.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 16:00:45 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 16:00:45 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 16:00:45 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 16:00:45 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 16:00:45 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 16:00:45 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 16:00:45 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 16:00:45 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 16:00:45 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 16:00:45 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 16:00:45 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 16:00:45 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 16:00:45 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 16:00:45 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 16:00:45 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 16:00:45 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 16:00:45 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 16:00:45 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Fri Jan 13 20:01:30 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0004.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 20:01:31 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 20:01:31 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 20:01:31 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 20:01:31 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 20:01:31 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 20:01:31 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 20:01:31 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 20:01:31 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 20:01:31 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 20:01:31 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 20:01:31 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 20:01:31 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 20:01:31 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 20:01:31 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 20:01:31 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 20:01:31 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 13 20:01:31 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 13 20:01:31 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sat Jan 14 08:02:12 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0005.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 08:02:13 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 08:02:13 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 08:02:13 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 08:02:13 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 08:02:13 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 08:02:13 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 08:02:13 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 08:02:13 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 08:02:13 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 08:02:13 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 08:02:13 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 08:02:13 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 08:02:13 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 08:02:13 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 08:02:13 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 08:02:13 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 08:02:13 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 08:02:13 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sat Jan 14 12:00:42 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0006.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 12:00:42 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 12:00:42 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 12:00:42 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 12:00:42 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 12:00:42 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 12:00:42 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 12:00:42 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 12:00:42 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 12:00:42 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 12:00:42 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 12:00:42 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 12:00:42 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 12:00:42 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 12:00:42 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 12:00:42 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 12:00:42 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 12:00:42 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 12:00:42 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sat Jan 14 16:00:41 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0007.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 16:00:41 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 16:00:41 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 16:00:41 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 16:00:41 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 16:00:41 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 16:00:41 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 16:00:41 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 16:00:41 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 16:00:41 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 16:00:41 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 16:00:41 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 16:00:41 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 16:00:41 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 16:00:41 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 16:00:41 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 16:00:41 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 16:00:41 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 16:00:41 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sat Jan 14 20:00:37 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0008.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 20:00:37 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 20:00:37 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 20:00:37 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 20:00:37 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 20:00:37 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 20:00:37 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 20:00:37 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 20:00:37 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 20:00:37 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 20:00:37 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 20:00:37 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 20:00:37 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 20:00:37 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 20:00:37 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 20:00:37 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 20:00:37 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 14 20:00:37 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 14 20:00:37 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sun Jan 15 08:02:02 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0009.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 08:02:03 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 08:02:03 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 08:02:03 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 08:02:03 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 08:02:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 08:02:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 08:02:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 08:02:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 08:02:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 08:02:03 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 08:02:03 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 08:02:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 08:02:03 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 08:02:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 08:02:03 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 08:02:03 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 08:02:03 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 08:02:03 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sun Jan 15 12:00:48 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0010.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 12:00:48 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 12:00:48 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 12:00:48 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 12:00:48 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 12:00:48 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 12:00:48 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 12:00:48 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 12:00:48 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 12:00:48 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 12:00:48 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 12:00:48 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 12:00:48 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 12:00:48 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 12:00:48 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 12:00:48 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 12:00:48 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 12:00:48 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 12:00:48 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sun Jan 15 16:00:41 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0011.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 16:00:41 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 16:00:41 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 16:00:41 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 16:00:41 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 16:00:41 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 16:00:41 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 16:00:41 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 16:00:41 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 16:00:41 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 16:00:41 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 16:00:41 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 16:00:41 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 16:00:41 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 16:00:41 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 16:00:41 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 16:00:41 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 16:00:41 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 16:00:41 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sun Jan 15 20:00:37 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0012.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 20:00:37 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 20:00:37 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 20:00:37 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 20:00:37 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 20:00:37 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 20:00:37 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 20:00:37 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 20:00:37 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 20:00:37 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 20:00:37 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 20:00:37 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 20:00:37 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 20:00:37 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 20:00:37 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 20:00:37 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 20:00:37 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 15 20:00:37 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 15 20:00:37 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Mon Jan 16 08:02:25 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0013.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 08:02:25 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 08:02:25 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 08:02:26 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 08:02:26 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 08:02:26 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 08:02:26 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 08:02:26 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 08:02:26 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 08:02:26 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 08:02:26 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 08:02:26 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 08:02:26 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 08:02:26 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 08:02:26 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 08:02:26 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 08:02:26 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 08:02:26 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 08:02:26 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Mon Jan 16 12:00:45 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0014.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 12:00:45 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 12:00:45 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 12:00:45 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 12:00:45 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 12:00:45 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 12:00:45 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 12:00:45 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 12:00:45 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 12:00:45 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 12:00:45 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 12:00:45 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 12:00:45 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 12:00:45 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 12:00:45 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 12:00:45 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 12:00:45 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 12:00:45 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 12:00:45 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Mon Jan 16 16:00:45 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0015.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 16:00:45 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 16:00:45 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 16:00:45 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 16:00:45 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 16:00:45 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 16:00:45 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 16:00:45 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 16:00:45 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 16:00:45 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 16:00:45 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 16:00:45 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 16:00:45 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 16:00:45 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 16:00:45 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 16:00:45 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 16:00:45 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 16:00:45 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 16:00:45 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Mon Jan 16 20:00:36 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0016.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 20:00:36 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 20:00:36 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 20:00:37 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 20:00:37 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 20:00:37 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 20:00:37 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 20:00:37 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 20:00:37 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 20:00:37 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 20:00:39 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 20:00:39 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 20:00:39 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 20:00:39 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 20:00:39 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 20:00:39 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 20:00:39 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 16 20:00:39 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 16 20:00:39 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Tue Jan 17 08:02:26 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0017.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 08:02:26 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 08:02:26 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 08:02:26 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 08:02:26 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 08:02:26 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 08:02:26 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 08:02:26 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 08:02:27 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 08:02:27 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 08:02:27 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 08:02:27 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 08:02:27 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 08:02:27 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 08:02:27 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 08:02:27 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 08:02:27 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 08:02:27 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 08:02:27 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Tue Jan 17 12:00:54 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0018.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 12:00:54 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 12:00:54 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 12:00:54 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 12:00:54 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 12:00:54 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 12:00:54 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 12:00:54 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 12:00:54 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 12:00:54 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 12:00:54 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 12:00:54 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 12:00:54 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 12:00:54 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 12:00:54 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 12:00:54 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 12:00:54 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 12:00:54 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 12:00:54 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Tue Jan 17 16:00:46 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0019.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 16:00:46 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 16:00:46 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 16:00:46 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 16:00:46 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 16:00:46 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 16:00:46 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 16:00:46 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 16:00:46 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 16:00:46 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 16:00:46 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 16:00:46 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 16:00:46 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 16:00:46 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 16:00:46 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 16:00:46 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 16:00:46 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 16:00:46 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 16:00:46 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Tue Jan 17 20:00:48 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0020.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 20:00:48 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 20:00:48 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 20:00:48 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 20:00:48 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 20:00:48 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 20:00:48 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 20:00:48 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 20:00:48 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 20:00:48 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 20:00:48 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 20:00:48 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 20:00:48 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 20:00:48 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 20:00:48 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 20:00:48 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 20:00:48 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 17 20:00:48 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 17 20:00:48 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Wed Jan 18 08:04:09 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0021.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 08:04:10 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 08:04:10 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 08:04:10 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 08:04:10 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 08:04:10 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 08:04:10 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 08:04:10 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 08:04:10 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 08:04:10 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 08:04:10 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 08:04:10 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 08:04:10 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 08:04:10 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 08:04:10 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 08:04:10 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 08:04:10 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 08:04:10 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 08:04:10 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Wed Jan 18 12:00:58 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0022.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 12:00:58 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 12:00:58 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 12:00:58 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 12:00:58 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 12:00:58 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 12:00:58 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 12:00:58 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 12:00:58 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 12:00:58 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 12:00:58 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 12:00:58 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 12:00:58 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 12:00:58 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 12:00:58 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 12:00:58 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 12:00:58 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 12:00:58 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 12:00:58 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Wed Jan 18 16:01:21 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0023.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 16:01:21 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 16:01:21 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 16:01:21 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 16:01:21 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 16:01:21 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 16:01:21 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 16:01:21 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 16:01:21 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 16:01:21 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 16:01:21 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 16:01:21 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 16:01:21 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 16:01:21 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 16:01:21 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 16:01:21 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 16:01:21 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 16:01:21 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 16:01:21 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Wed Jan 18 20:00:47 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0024.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 20:00:47 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 20:00:47 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 20:00:47 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 20:00:48 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 20:00:48 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 20:00:48 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 20:00:48 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 20:00:48 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 20:00:48 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 20:00:48 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 20:00:48 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 20:00:48 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 20:00:48 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 20:00:48 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 20:00:48 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 20:00:48 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 18 20:00:48 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 18 20:00:48 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Thu Jan 19 08:04:31 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0025.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 08:04:31 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 08:04:31 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 08:04:31 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 08:04:31 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 08:04:31 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 08:04:31 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 08:04:31 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 08:04:31 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 08:04:31 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 08:04:31 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 08:04:31 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 08:04:31 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 08:04:31 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 08:04:31 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 08:04:31 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 08:04:31 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 08:04:31 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 08:04:31 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Thu Jan 19 12:00:56 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0026.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 12:00:56 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 12:00:56 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 12:00:56 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 12:00:56 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 12:00:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 12:00:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 12:00:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 12:00:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 12:00:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 12:00:56 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 12:00:56 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 12:00:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 12:00:56 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 12:00:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 12:00:56 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 12:00:56 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 12:00:56 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 12:00:56 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Thu Jan 19 16:02:39 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0027.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 16:02:39 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 16:02:39 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 16:02:39 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 16:02:39 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 16:02:40 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 16:02:40 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 16:02:40 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 16:02:40 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 16:02:40 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 16:02:40 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 16:02:40 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 16:02:40 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 16:02:40 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 16:02:40 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 16:02:40 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 16:02:40 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 16:02:41 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 16:02:41 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Thu Jan 19 20:00:44 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0028.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 20:00:44 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 20:00:44 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 20:00:44 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 20:00:44 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 20:00:44 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 20:00:44 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 20:00:44 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 20:00:44 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 20:00:44 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 20:00:44 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 20:00:44 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 20:00:44 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 20:00:44 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 20:00:44 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 20:00:44 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 20:00:44 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 19 20:00:44 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 19 20:00:44 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Fri Jan 20 08:06:24 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0029.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 08:06:25 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 08:06:25 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 08:06:25 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 08:06:25 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 08:06:25 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 08:06:25 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 08:06:25 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 08:06:25 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 08:06:25 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 08:06:25 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 08:06:25 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 08:06:25 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 08:06:25 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 08:06:25 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 08:06:25 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 08:06:25 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 08:06:25 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 08:06:25 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Fri Jan 20 12:01:52 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0030.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 12:01:53 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 12:01:53 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 12:01:53 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 12:01:53 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 12:01:53 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 12:01:53 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 12:01:53 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 12:01:53 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 12:01:53 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 12:01:53 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 12:01:53 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 12:01:53 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 12:01:53 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 12:01:53 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 12:01:53 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 12:01:53 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 12:01:53 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 12:01:53 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Fri Jan 20 16:00:47 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0031.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 16:00:47 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 16:00:47 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 16:00:47 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 16:00:47 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 16:00:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 16:00:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 16:00:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 16:00:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 16:00:48 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 16:00:48 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 16:00:48 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 16:00:48 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 16:00:48 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 16:00:48 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 16:00:48 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 16:00:48 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 16:00:48 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 16:00:48 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Fri Jan 20 20:00:43 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0032.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 20:00:43 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 20:00:43 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 20:00:43 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 20:00:43 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 20:00:43 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 20:00:43 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 20:00:43 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 20:00:44 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 20:00:44 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 20:00:44 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 20:00:44 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 20:00:44 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 20:00:44 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 20:00:44 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 20:00:44 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 20:00:44 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 20 20:00:44 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 20 20:00:44 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sat Jan 21 08:03:45 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0033.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 08:03:45 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 08:03:45 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 08:03:46 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 08:03:46 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 08:03:46 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 08:03:46 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 08:03:46 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 08:03:46 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 08:03:46 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 08:03:46 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 08:03:46 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 08:03:46 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 08:03:46 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 08:03:46 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 08:03:46 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 08:03:46 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 08:03:46 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 08:03:46 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sat Jan 21 12:00:58 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0034.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 12:00:58 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 12:00:58 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 12:00:58 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 12:00:58 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 12:00:58 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 12:00:58 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 12:00:58 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 12:00:58 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 12:00:58 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 12:00:58 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 12:00:58 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 12:00:58 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 12:00:58 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 12:00:58 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 12:00:58 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 12:00:58 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 12:00:58 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 12:00:58 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sat Jan 21 16:00:45 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0035.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 16:00:46 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 16:00:46 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 16:00:46 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 16:00:46 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 16:00:46 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 16:00:46 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 16:00:46 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 16:00:46 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 16:00:46 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 16:00:46 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 16:00:46 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 16:00:46 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 16:00:46 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 16:00:46 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 16:00:46 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 16:00:46 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 16:00:46 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 16:00:46 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sat Jan 21 20:00:46 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0036.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 20:00:46 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 20:00:46 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 20:00:46 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 20:00:46 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 20:00:46 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 20:00:46 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 20:00:46 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 20:00:46 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 20:00:46 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 20:00:46 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 20:00:46 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 20:00:46 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 20:00:46 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 20:00:46 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 20:00:47 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 20:00:47 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 21 20:00:47 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 21 20:00:47 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sun Jan 22 08:02:38 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0037.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 08:02:38 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 08:02:38 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 08:02:38 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 08:02:38 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 08:02:38 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 08:02:38 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 08:02:38 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 08:02:38 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 08:02:38 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 08:02:38 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 08:02:38 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 08:02:38 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 08:02:38 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 08:02:38 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 08:02:38 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 08:02:38 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 08:02:38 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 08:02:38 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sun Jan 22 12:00:47 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0038.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 12:00:47 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 12:00:47 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 12:00:47 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 12:00:47 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 12:00:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 12:00:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 12:00:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 12:00:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 12:00:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 12:00:47 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 12:00:47 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 12:00:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 12:00:47 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 12:00:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 12:00:47 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 12:00:47 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 12:00:47 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 12:00:47 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sun Jan 22 16:01:11 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0039.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 16:01:11 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 16:01:11 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 16:01:11 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 16:01:11 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 16:01:11 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 16:01:11 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 16:01:11 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 16:01:11 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 16:01:11 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 16:01:11 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 16:01:11 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 16:01:11 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 16:01:11 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 16:01:12 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 16:01:12 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 16:01:12 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 16:01:12 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 16:01:12 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sun Jan 22 20:01:08 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0040.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 20:01:08 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 20:01:08 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 20:01:08 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 20:01:08 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 20:01:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 20:01:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 20:01:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 20:01:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 20:01:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 20:01:08 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 20:01:08 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 20:01:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 20:01:08 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 20:01:09 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 20:01:09 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 20:01:09 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 22 20:01:09 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 22 20:01:09 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Mon Jan 23 08:02:30 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0041.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 08:02:30 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 08:02:30 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 08:02:30 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 08:02:30 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 08:02:30 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 08:02:30 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 08:02:30 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 08:02:30 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 08:02:30 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 08:02:30 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 08:02:30 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 08:02:30 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 08:02:30 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 08:02:30 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 08:02:30 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 08:02:30 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 08:02:30 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 08:02:30 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Mon Jan 23 12:00:50 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0042.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 12:00:50 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 12:00:50 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 12:00:50 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 12:00:50 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 12:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 12:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 12:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 12:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 12:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 12:00:50 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 12:00:50 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 12:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 12:00:50 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 12:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 12:00:50 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 12:00:50 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 12:00:50 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 12:00:50 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Mon Jan 23 16:01:36 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0043.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 16:01:36 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 16:01:36 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 16:01:36 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 16:01:36 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 16:01:36 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 16:01:36 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 16:01:36 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 16:01:36 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 16:01:36 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 16:01:37 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 16:01:37 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 16:01:37 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 16:01:37 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 16:01:37 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 16:01:37 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 16:01:37 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 16:01:37 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 16:01:37 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Mon Jan 23 20:00:47 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0044.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 20:00:47 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 20:00:47 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 20:00:47 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 20:00:47 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 20:00:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 20:00:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 20:00:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 20:00:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 20:00:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 20:00:47 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 20:00:47 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 20:00:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 20:00:47 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 20:00:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 20:00:47 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 20:00:47 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 23 20:00:47 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 23 20:00:48 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Tue Jan 24 08:03:02 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0045.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 08:03:02 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 08:03:02 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 08:03:02 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 08:03:02 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 08:03:02 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 08:03:02 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 08:03:02 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 08:03:02 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 08:03:02 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 08:03:02 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 08:03:02 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 08:03:02 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 08:03:02 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 08:03:02 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 08:03:02 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 08:03:02 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 08:03:02 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 08:03:02 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Tue Jan 24 12:02:36 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0046.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 12:02:37 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 12:02:37 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 12:02:37 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 12:02:37 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 12:02:37 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 12:02:37 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 12:02:37 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 12:02:37 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 12:02:37 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 12:02:38 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 12:02:38 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 12:02:38 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 12:02:38 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 12:02:38 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 12:02:38 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 12:02:38 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 12:02:38 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 12:02:38 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Tue Jan 24 16:01:14 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0047.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 16:01:14 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 16:01:14 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 16:01:14 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 16:01:15 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 16:01:15 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 16:01:15 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 16:01:15 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 16:01:15 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 16:01:15 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 16:01:15 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 16:01:15 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 16:01:15 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 16:01:15 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 16:01:15 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 16:01:15 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 16:01:15 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 16:01:15 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 16:01:15 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Tue Jan 24 20:01:47 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0048.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 20:01:47 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 20:01:47 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 20:01:47 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 20:01:47 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 20:01:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 20:01:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 20:01:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 20:01:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 20:01:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 20:01:47 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 20:01:47 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 20:01:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 20:01:47 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 20:01:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 20:01:47 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 20:01:47 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 24 20:01:47 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 24 20:01:47 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Wed Jan 25 08:01:55 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0049.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 08:01:55 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 08:01:55 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 08:01:55 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 08:01:55 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 08:01:55 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 08:01:55 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 08:01:55 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 08:01:55 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 08:01:55 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 08:01:55 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 08:01:55 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 08:01:55 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 08:01:55 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 08:01:55 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 08:01:55 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 08:01:55 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 08:01:55 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 08:01:55 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Wed Jan 25 12:00:56 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0050.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 12:00:57 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 12:00:57 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 12:00:57 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 12:00:57 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 12:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 12:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 12:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 12:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 12:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 12:00:57 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 12:00:57 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 12:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 12:00:57 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 12:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 12:00:57 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 12:00:57 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 12:00:58 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 12:00:58 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Wed Jan 25 16:00:56 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0051.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 16:00:56 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 16:00:56 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 16:00:56 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 16:00:56 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 16:00:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 16:00:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 16:00:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 16:00:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 16:00:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 16:00:56 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 16:00:57 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 16:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 16:00:57 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 16:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 16:00:57 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 16:00:57 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 16:00:57 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 16:00:57 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Wed Jan 25 20:00:50 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0052.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 20:00:50 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 20:00:50 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 20:00:50 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 20:00:50 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 20:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 20:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 20:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 20:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 20:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 20:00:50 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 20:00:50 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 20:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 20:00:50 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 20:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 20:00:50 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 20:00:50 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Jan 25 20:00:50 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Jan 25 20:00:50 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Thu Jan 26 08:05:20 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0053.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 08:05:20 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 08:05:20 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 08:05:20 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 08:05:20 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 08:05:20 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 08:05:20 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 08:05:20 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 08:05:20 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 08:05:20 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 08:05:20 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 08:05:20 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 08:05:20 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 08:05:20 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 08:05:21 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 08:05:21 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 08:05:21 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 08:05:21 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 08:05:21 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Thu Jan 26 12:01:00 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0054.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 12:01:00 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 12:01:00 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 12:01:00 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 12:01:00 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 12:01:00 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 12:01:00 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 12:01:00 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 12:01:00 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 12:01:00 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 12:01:00 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 12:01:00 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 12:01:00 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 12:01:00 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 12:01:00 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 12:01:00 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 12:01:00 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 12:01:00 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 12:01:00 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Thu Jan 26 16:00:47 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0055.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 16:00:47 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 16:00:47 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 16:00:47 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 16:00:47 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 16:00:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 16:00:49 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 16:00:49 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 16:00:49 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 16:00:49 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 16:00:49 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 16:00:49 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 16:00:49 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 16:00:49 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 16:00:49 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 16:00:49 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 16:00:49 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 16:00:50 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 16:00:50 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Thu Jan 26 20:00:44 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0056.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 20:00:44 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 20:00:44 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 20:00:44 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 20:00:44 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 20:00:44 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 20:00:44 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 20:00:44 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 20:00:44 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 20:00:44 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 20:00:44 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 20:00:44 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 20:00:44 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 20:00:44 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 20:00:44 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 20:00:44 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 20:00:44 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Jan 26 20:00:44 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Jan 26 20:00:44 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Fri Jan 27 08:06:15 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0057.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 08:06:16 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 08:06:16 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 08:06:16 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 08:06:16 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 08:06:16 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 08:06:16 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 08:06:16 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 08:06:16 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 08:06:16 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 08:06:16 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 08:06:16 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 08:06:16 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 08:06:16 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 08:06:16 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 08:06:16 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 08:06:16 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 08:06:16 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 08:06:16 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Fri Jan 27 12:02:04 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0058.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 12:02:04 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 12:02:04 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 12:02:04 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 12:02:04 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 12:02:04 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 12:02:04 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 12:02:04 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 12:02:04 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 12:02:04 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 12:02:04 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 12:02:04 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 12:02:04 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 12:02:04 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 12:02:04 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 12:02:04 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 12:02:04 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 12:02:04 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 12:02:04 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Fri Jan 27 16:01:00 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0059.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 16:01:00 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 16:01:00 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 16:01:00 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 16:01:00 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 16:01:00 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 16:01:00 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 16:01:00 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 16:01:00 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 16:01:00 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 16:01:00 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 16:01:00 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 16:01:00 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 16:01:00 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 16:01:00 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 16:01:00 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 16:01:00 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 16:01:00 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 16:01:00 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Fri Jan 27 20:00:51 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0060.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 20:00:51 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 20:00:51 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 20:00:51 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 20:00:51 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 20:00:51 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 20:00:51 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 20:00:51 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 20:00:51 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 20:00:51 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 20:00:51 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 20:00:51 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 20:00:51 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 20:00:51 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 20:00:51 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 20:00:51 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 20:00:51 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Jan 27 20:00:51 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Jan 27 20:00:51 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sat Jan 28 08:05:23 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0061.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 08:05:23 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 08:05:23 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 08:05:23 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 08:05:23 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 08:05:23 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 08:05:23 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 08:05:23 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 08:05:23 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 08:05:23 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 08:05:23 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 08:05:23 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 08:05:23 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 08:05:23 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 08:05:23 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 08:05:23 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 08:05:23 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 08:05:23 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 08:05:23 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sat Jan 28 12:01:50 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0062.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 12:01:50 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 12:01:50 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 12:01:50 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 12:01:50 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 12:01:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 12:01:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 12:01:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 12:01:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 12:01:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 12:01:50 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 12:01:50 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 12:01:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 12:01:50 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 12:01:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 12:01:50 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 12:01:50 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 12:01:50 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 12:01:50 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sat Jan 28 16:00:50 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0063.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 16:00:50 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 16:00:50 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 16:00:50 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 16:00:50 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 16:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 16:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 16:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 16:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 16:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 16:00:50 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 16:00:50 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 16:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 16:00:50 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 16:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 16:00:50 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 16:00:50 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 16:00:50 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 16:00:50 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sat Jan 28 20:00:50 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0064.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 20:00:50 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 20:00:50 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 20:00:50 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 20:00:50 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 20:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 20:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 20:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 20:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 20:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 20:00:50 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 20:00:50 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 20:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 20:00:50 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 20:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 20:00:50 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 20:00:50 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Jan 28 20:00:51 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Jan 28 20:00:51 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sun Jan 29 08:07:07 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0065.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 08:07:08 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 08:07:08 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 08:07:08 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 08:07:08 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 08:07:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 08:07:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 08:07:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 08:07:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 08:07:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 08:07:08 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 08:07:08 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 08:07:09 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 08:07:09 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 08:07:09 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 08:07:09 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 08:07:09 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 08:07:09 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 08:07:09 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sun Jan 29 12:00:57 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0066.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 12:00:57 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 12:00:57 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 12:00:57 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 12:00:57 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 12:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 12:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 12:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 12:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 12:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 12:00:57 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 12:00:57 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 12:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 12:00:57 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 12:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 12:00:57 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 12:00:57 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 12:00:57 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 12:00:57 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sun Jan 29 16:00:48 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0067.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 16:00:48 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 16:00:48 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 16:00:48 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 16:00:48 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 16:00:48 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 16:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 16:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 16:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 16:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 16:00:50 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 16:00:50 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 16:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 16:00:50 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 16:00:51 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 16:00:51 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 16:00:51 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 16:00:51 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 16:00:51 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sun Jan 29 20:00:49 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0068.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 20:00:49 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 20:00:49 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 20:00:49 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 20:00:49 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 20:00:49 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 20:00:49 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 20:00:49 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 20:00:49 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 20:00:49 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 20:00:50 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 20:00:50 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 20:00:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 20:00:50 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 20:00:51 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 20:00:51 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 20:00:51 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Jan 29 20:00:51 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Jan 29 20:00:51 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Mon Jan 30 08:07:53 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0069.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 08:07:54 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 08:07:54 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 08:07:54 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 08:07:54 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 08:07:54 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 08:07:54 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 08:07:55 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 08:07:55 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 08:07:55 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 08:07:55 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 08:07:57 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 08:07:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 08:07:57 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 08:07:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 08:07:58 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 08:07:58 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 08:07:58 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 08:07:58 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Mon Jan 30 12:03:42 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0070.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 12:03:42 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 12:03:42 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 12:03:42 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 12:03:43 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 12:03:43 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 12:03:43 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 12:03:43 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 12:03:43 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 12:03:43 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 12:03:43 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 12:03:43 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 12:03:43 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 12:03:43 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 12:03:43 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 12:03:43 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 12:03:43 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 12:03:43 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 12:03:43 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Mon Jan 30 16:03:57 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0071.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 16:03:58 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 16:03:58 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 16:03:58 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 16:03:58 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 16:03:58 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 16:03:58 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 16:03:58 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 16:03:58 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 16:03:58 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 16:03:58 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 16:03:58 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 16:03:58 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 16:03:58 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 16:03:58 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 16:03:58 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 16:03:58 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 16:03:58 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 16:03:58 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Mon Jan 30 20:02:04 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0072.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 20:02:04 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 20:02:04 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 20:02:04 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 20:02:04 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 20:02:04 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 20:02:04 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 20:02:04 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 20:02:04 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 20:02:04 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 20:02:04 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 20:02:04 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 20:02:04 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 20:02:04 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 20:02:04 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 20:02:04 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 20:02:04 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Jan 30 20:02:04 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Jan 30 20:02:04 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Tue Jan 31 08:07:34 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0073.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 08:07:34 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 08:07:34 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 08:07:34 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 08:07:34 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 08:07:34 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 08:07:34 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 08:07:34 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 08:07:34 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 08:07:34 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 08:07:34 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 08:07:35 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 08:07:35 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 08:07:35 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 08:07:35 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 08:07:35 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 08:07:35 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 08:07:35 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 08:07:35 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Tue Jan 31 12:04:05 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0074.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 12:04:05 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 12:04:05 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 12:04:05 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 12:04:05 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 12:04:05 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 12:04:05 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 12:04:05 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 12:04:05 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 12:04:05 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 12:04:05 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 12:04:05 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 12:04:05 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 12:04:05 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 12:04:05 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 12:04:05 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 12:04:05 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 12:04:05 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 12:04:05 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Tue Jan 31 16:02:08 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0075.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 16:02:08 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 16:02:08 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 16:02:08 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 16:02:08 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 16:02:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 16:02:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 16:02:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 16:02:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 16:02:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 16:02:08 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 16:02:08 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 16:02:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 16:02:08 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 16:02:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 16:02:08 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 16:02:08 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 16:02:08 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 16:02:08 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Tue Jan 31 20:01:01 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0076.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 20:01:01 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 20:01:01 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 20:01:01 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 20:01:01 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 20:01:01 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 20:01:01 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 20:01:01 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 20:01:01 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 20:01:02 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 20:01:02 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 20:01:02 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 20:01:02 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 20:01:02 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 20:01:02 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 20:01:02 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 20:01:02 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Jan 31 20:01:02 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Jan 31 20:01:02 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Wed Feb 1 08:09:18 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0077.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 08:09:18 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 08:09:18 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 08:09:18 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 08:09:18 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 08:09:18 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 08:09:18 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 08:09:18 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 08:09:18 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 08:09:18 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 08:09:18 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 08:09:18 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 08:09:18 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 08:09:18 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 08:09:18 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 08:09:18 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 08:09:18 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 08:09:18 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 08:09:18 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Wed Feb 1 12:02:32 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0078.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 12:02:33 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 12:02:33 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 12:02:33 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 12:02:33 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 12:02:33 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 12:02:33 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 12:02:33 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 12:02:33 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 12:02:33 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 12:02:33 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 12:02:33 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 12:02:33 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 12:02:33 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 12:02:33 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 12:02:33 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 12:02:33 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 12:02:33 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 12:02:33 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Wed Feb 1 16:00:57 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0079.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 16:00:57 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 16:00:57 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 16:00:57 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 16:00:57 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 16:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 16:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 16:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 16:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 16:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 16:00:57 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 16:00:57 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 16:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 16:00:57 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 16:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 16:00:57 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 16:00:57 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 16:00:57 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 16:00:57 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Wed Feb 1 20:00:48 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0080.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 20:00:48 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 20:00:48 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 20:00:48 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 20:00:51 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 20:00:52 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 20:00:54 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 20:00:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 20:00:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 20:00:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 20:00:56 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 20:00:56 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 20:00:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 20:00:56 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 20:00:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 20:00:56 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 20:00:56 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 1 20:00:56 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 1 20:00:56 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Thu Feb 2 08:11:41 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0081.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 08:11:41 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 08:11:41 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 08:11:41 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 08:11:41 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 08:11:41 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 08:11:41 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 08:11:41 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 08:11:41 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 08:11:41 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 08:11:41 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 08:11:41 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 08:11:42 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 08:11:42 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 08:11:42 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 08:11:42 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 08:11:42 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 08:11:42 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 08:11:42 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Thu Feb 2 12:02:39 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0082.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 12:02:39 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 12:02:39 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 12:02:39 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 12:02:39 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 12:02:39 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 12:02:39 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 12:02:39 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 12:02:39 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 12:02:39 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 12:02:39 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 12:02:39 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 12:02:39 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 12:02:39 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 12:02:39 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 12:02:39 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 12:02:39 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 12:02:39 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 12:02:39 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Thu Feb 2 16:01:05 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0083.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 16:01:05 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 16:01:05 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 16:01:05 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 16:01:05 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 16:01:05 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 16:01:05 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 16:01:05 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 16:01:05 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 16:01:05 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 16:01:05 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 16:01:05 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 16:01:05 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 16:01:05 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 16:01:05 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 16:01:05 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 16:01:05 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 16:01:05 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 16:01:05 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Thu Feb 2 20:00:55 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0084.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 20:00:55 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 20:00:55 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 20:00:55 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 20:00:55 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 20:00:55 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 20:00:55 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 20:00:55 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 20:00:55 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 20:00:55 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 20:00:55 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 20:00:55 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 20:00:55 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 20:00:55 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 20:00:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 20:00:56 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 20:00:56 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 2 20:00:56 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 2 20:00:56 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Fri Feb 3 08:11:17 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0085.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 08:11:17 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 08:11:18 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 08:11:18 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 08:11:18 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 08:11:18 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 08:11:18 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 08:11:18 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 08:11:18 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 08:11:18 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 08:11:18 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 08:11:19 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 08:11:19 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 08:11:19 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 08:11:19 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 08:11:19 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 08:11:19 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 08:11:19 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 08:11:19 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Fri Feb 3 12:02:28 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0086.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 12:02:28 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 12:02:28 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 12:02:28 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 12:02:28 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 12:02:28 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 12:02:28 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 12:02:28 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 12:02:28 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 12:02:28 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 12:02:28 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 12:02:28 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 12:02:28 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 12:02:28 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 12:02:28 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 12:02:28 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 12:02:28 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 12:02:28 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 12:02:28 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Fri Feb 3 16:00:53 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0087.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 16:00:53 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 16:00:53 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 16:00:53 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 16:00:53 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 16:00:53 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 16:00:53 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 16:00:53 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 16:00:53 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 16:00:53 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 16:00:53 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 16:00:53 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 16:00:53 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 16:00:53 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 16:00:53 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 16:00:53 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 16:00:53 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 16:00:53 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 16:00:53 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Fri Feb 3 20:00:57 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0088.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 20:00:57 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 20:00:57 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 20:00:57 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 20:00:57 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 20:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 20:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 20:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 20:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 20:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 20:00:57 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 20:00:57 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 20:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 20:00:57 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 20:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 20:00:58 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 20:00:58 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 3 20:00:58 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 3 20:00:58 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sat Feb 4 08:07:11 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0089.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 08:07:11 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 08:07:11 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 08:07:11 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 08:07:11 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 08:07:11 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 08:07:11 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 08:07:11 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 08:07:11 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 08:07:11 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 08:07:11 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 08:07:11 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 08:07:11 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 08:07:11 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 08:07:11 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 08:07:12 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 08:07:12 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 08:07:12 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 08:07:12 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sat Feb 4 12:02:29 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0090.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 12:02:29 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 12:02:29 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 12:02:29 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 12:02:29 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 12:02:29 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 12:02:29 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 12:02:30 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 12:02:30 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 12:02:30 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 12:02:30 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 12:02:30 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 12:02:30 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 12:02:30 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 12:02:30 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 12:02:30 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 12:02:30 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 12:02:30 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 12:02:30 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sat Feb 4 16:01:07 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0091.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 16:01:07 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 16:01:07 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 16:01:07 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 16:01:07 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 16:01:07 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 16:01:07 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 16:01:07 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 16:01:07 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 16:01:07 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 16:01:07 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 16:01:07 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 16:01:07 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 16:01:07 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 16:01:07 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 16:01:07 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 16:01:07 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 16:01:07 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 16:01:07 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sat Feb 4 20:00:59 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0092.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 20:00:59 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 20:00:59 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 20:00:59 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 20:00:59 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 20:00:59 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 20:00:59 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 20:00:59 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 20:00:59 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 20:00:59 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 20:00:59 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 20:00:59 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 20:00:59 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 20:00:59 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 20:00:59 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 20:00:59 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 20:00:59 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 4 20:00:59 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 4 20:00:59 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sun Feb 5 08:07:30 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0093.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 08:07:30 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 08:07:31 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 08:07:31 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 08:07:31 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 08:07:31 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 08:07:31 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 08:07:31 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 08:07:31 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 08:07:31 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 08:07:31 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 08:07:31 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 08:07:31 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 08:07:31 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 08:07:31 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 08:07:31 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 08:07:31 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 08:07:31 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 08:07:31 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sun Feb 5 12:02:32 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0094.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 12:02:32 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 12:02:32 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 12:02:32 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 12:02:32 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 12:02:32 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 12:02:32 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 12:02:32 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 12:02:33 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 12:02:33 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 12:02:33 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 12:02:33 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 12:02:33 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 12:02:33 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 12:02:33 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 12:02:33 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 12:02:33 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 12:02:33 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 12:02:33 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sun Feb 5 16:01:01 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0095.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 16:01:01 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 16:01:01 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 16:01:01 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 16:01:01 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 16:01:01 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 16:01:01 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 16:01:01 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 16:01:02 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 16:01:02 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 16:01:02 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 16:01:02 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 16:01:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 16:01:03 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 16:01:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 16:01:03 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 16:01:03 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 16:01:03 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 16:01:03 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sun Feb 5 20:00:56 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0096.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 20:00:56 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 20:00:56 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 20:00:56 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 20:00:56 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 20:00:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 20:00:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 20:00:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 20:00:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 20:00:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 20:00:56 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 20:00:56 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 20:00:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 20:00:56 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 20:00:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 20:00:56 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 20:00:56 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 5 20:00:56 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 5 20:00:56 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Mon Feb 6 08:13:09 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0097.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 08:13:10 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 08:13:10 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 08:13:10 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 08:13:10 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 08:13:10 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 08:13:10 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 08:13:10 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 08:13:10 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 08:13:10 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 08:13:11 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 08:13:11 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 08:13:11 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 08:13:11 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 08:13:11 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 08:13:12 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 08:13:12 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 08:13:12 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 08:13:12 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Mon Feb 6 12:02:30 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0098.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 12:02:30 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 12:02:30 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 12:02:30 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 12:02:30 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 12:02:30 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 12:02:30 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 12:02:30 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 12:02:30 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 12:02:30 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 12:02:30 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 12:02:30 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 12:02:30 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 12:02:30 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 12:02:30 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 12:02:30 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 12:02:30 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 12:02:30 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 12:02:30 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Mon Feb 6 16:01:01 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0099.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 16:01:01 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 16:01:01 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 16:01:01 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 16:01:01 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 16:01:01 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 16:01:01 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 16:01:01 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 16:01:01 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 16:01:01 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 16:01:01 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 16:01:01 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 16:01:01 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 16:01:01 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 16:01:01 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 16:01:01 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 16:01:02 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 16:01:02 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 16:01:02 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Mon Feb 6 20:00:55 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0100.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 20:00:55 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 20:00:55 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 20:00:55 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 20:00:55 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 20:00:55 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 20:00:55 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 20:00:55 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 20:00:55 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 20:00:55 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 20:00:55 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 20:00:55 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 20:00:55 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 20:00:55 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 20:00:55 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 20:00:55 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 20:00:55 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 6 20:00:55 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 6 20:00:55 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Tue Feb 7 08:20:41 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0101.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 08:20:43 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 08:20:43 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 08:20:43 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 08:20:43 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 08:20:44 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 08:20:44 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 08:20:44 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 08:20:46 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 08:20:46 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 08:20:47 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 08:20:47 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 08:20:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 08:20:48 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 08:20:48 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 08:20:48 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 08:20:49 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 08:20:49 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 08:20:50 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Tue Feb 7 12:03:05 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0102.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 12:03:06 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 12:03:06 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 12:03:06 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 12:03:06 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 12:03:06 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 12:03:06 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 12:03:06 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 12:03:06 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 12:03:06 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 12:03:06 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 12:03:06 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 12:03:06 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 12:03:06 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 12:03:06 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 12:03:06 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 12:03:06 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 12:03:06 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 12:03:06 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Tue Feb 7 16:01:05 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0103.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 16:01:05 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 16:01:05 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 16:01:05 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 16:01:05 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 16:01:05 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 16:01:05 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 16:01:05 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 16:01:05 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 16:01:05 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 16:01:05 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 16:01:05 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 16:01:05 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 16:01:05 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 16:01:05 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 16:01:05 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 16:01:05 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 16:01:05 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 16:01:05 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Tue Feb 7 20:01:00 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0104.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 20:01:00 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 20:01:00 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 20:01:00 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 20:01:00 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 20:01:00 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 20:01:00 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 20:01:00 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 20:01:00 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 20:01:00 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 20:01:00 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 20:01:00 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 20:01:00 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 20:01:00 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 20:01:00 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 20:01:00 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 20:01:00 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 7 20:01:00 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 7 20:01:00 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Wed Feb 8 08:20:46 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0105.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 08:20:47 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 08:20:47 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 08:20:47 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 08:20:47 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 08:20:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 08:20:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 08:20:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 08:20:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 08:20:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 08:20:47 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 08:20:47 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 08:20:47 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 08:20:47 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 08:20:48 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 08:20:48 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 08:20:48 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 08:20:48 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 08:20:48 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Wed Feb 8 12:02:59 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0106.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 12:02:59 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 12:02:59 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 12:02:59 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 12:02:59 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 12:02:59 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 12:02:59 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 12:02:59 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 12:02:59 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 12:02:59 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 12:02:59 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 12:02:59 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 12:02:59 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 12:02:59 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 12:02:59 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 12:02:59 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 12:02:59 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 12:02:59 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 12:03:00 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Wed Feb 8 16:01:08 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0107.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 16:01:08 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 16:01:08 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 16:01:08 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 16:01:08 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 16:01:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 16:01:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 16:01:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 16:01:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 16:01:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 16:01:09 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 16:01:09 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 16:01:09 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 16:01:09 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 16:01:09 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 16:01:09 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 16:01:09 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 16:01:09 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 16:01:09 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Wed Feb 8 20:00:56 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0108.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 20:00:56 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 20:00:56 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 20:00:56 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 20:00:56 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 20:00:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 20:00:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 20:00:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 20:00:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 20:00:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 20:00:56 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 20:00:56 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 20:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 20:00:57 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 20:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 20:00:57 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 20:00:57 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 8 20:00:58 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 8 20:00:58 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Thu Feb 9 08:08:27 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0109.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 08:08:27 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 08:08:27 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 08:08:27 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 08:08:27 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 08:08:27 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 08:08:28 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 08:08:28 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 08:08:28 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 08:08:28 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 08:08:28 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 08:08:28 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 08:08:29 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 08:08:29 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 08:08:30 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 08:08:30 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 08:08:31 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 08:08:31 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 08:08:31 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Thu Feb 9 12:02:45 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0110.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 12:02:45 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 12:02:45 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 12:02:45 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 12:02:45 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 12:02:45 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 12:02:45 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 12:02:45 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 12:02:45 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 12:02:45 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 12:02:45 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 12:02:45 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 12:02:45 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 12:02:45 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 12:02:45 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 12:02:45 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 12:02:45 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 12:02:45 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 12:02:45 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Thu Feb 9 16:01:10 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0111.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 16:01:10 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 16:01:10 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 16:01:10 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 16:01:10 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 16:01:10 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 16:01:10 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 16:01:10 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 16:01:10 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 16:01:10 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 16:01:10 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 16:01:10 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 16:01:10 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 16:01:10 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 16:01:10 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 16:01:10 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 16:01:10 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 16:01:10 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 16:01:10 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Thu Feb 9 20:01:03 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0112.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 20:01:03 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 20:01:03 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 20:01:03 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 20:01:03 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 20:01:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 20:01:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 20:01:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 20:01:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 20:01:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 20:01:03 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 20:01:03 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 20:01:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 20:01:03 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 20:01:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 20:01:03 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 20:01:03 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 9 20:01:03 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 9 20:01:03 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Fri Feb 10 08:17:38 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0113.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 08:17:39 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 08:17:39 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 08:17:39 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 08:17:39 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 08:17:40 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 08:17:40 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 08:17:40 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 08:17:40 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 08:17:40 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 08:17:40 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 08:17:40 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 08:17:40 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 08:17:40 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 08:17:41 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 08:17:41 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 08:17:41 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 08:17:41 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 08:17:41 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Fri Feb 10 12:03:25 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0114.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 12:03:25 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 12:03:25 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 12:03:25 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 12:03:25 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 12:03:25 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 12:03:25 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 12:03:25 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 12:03:25 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 12:03:25 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 12:03:25 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 12:03:25 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 12:03:25 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 12:03:25 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 12:03:25 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 12:03:25 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 12:03:25 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 12:03:26 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 12:03:26 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Fri Feb 10 16:01:03 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0115.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 16:01:03 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 16:01:03 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 16:01:03 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 16:01:03 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 16:01:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 16:01:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 16:01:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 16:01:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 16:01:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 16:01:03 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 16:01:03 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 16:01:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 16:01:03 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 16:01:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 16:01:03 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 16:01:03 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 16:01:03 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 16:01:03 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Fri Feb 10 20:01:06 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0116.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 20:01:07 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 20:01:07 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 20:01:07 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 20:01:07 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 20:01:07 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 20:01:07 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 20:01:07 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 20:01:07 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 20:01:07 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 20:01:07 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 20:01:07 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 20:01:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 20:01:08 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 20:01:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 20:01:08 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 20:01:08 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Feb 10 20:01:08 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Feb 10 20:01:08 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sat Feb 11 08:12:18 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0117.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 08:12:18 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 08:12:18 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 08:12:18 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 08:12:19 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 08:12:19 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 08:12:19 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 08:12:19 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 08:12:19 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 08:12:19 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 08:12:19 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 08:12:19 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 08:12:19 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 08:12:19 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 08:12:19 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 08:12:19 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 08:12:19 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 08:12:19 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 08:12:19 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sat Feb 11 12:02:27 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0118.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 12:02:27 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 12:02:27 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 12:02:27 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 12:02:27 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 12:02:27 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 12:02:27 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 12:02:27 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 12:02:27 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 12:02:27 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 12:02:27 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 12:02:27 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 12:02:27 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 12:02:27 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 12:02:27 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 12:02:28 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 12:02:28 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 12:02:28 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 12:02:28 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sat Feb 11 16:00:58 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0119.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 16:00:59 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 16:00:59 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 16:00:59 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 16:01:00 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 16:01:00 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 16:01:00 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 16:01:00 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 16:01:00 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 16:01:00 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 16:01:00 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 16:01:00 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 16:01:00 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 16:01:00 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 16:01:00 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 16:01:00 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 16:01:00 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 16:01:00 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 16:01:00 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sat Feb 11 20:00:54 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0120.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 20:00:54 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 20:00:54 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 20:00:54 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 20:00:54 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 20:00:54 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 20:00:54 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 20:00:54 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 20:00:54 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 20:00:54 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 20:00:54 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 20:00:54 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 20:00:54 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 20:00:54 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 20:00:54 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 20:00:54 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 20:00:54 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sat Feb 11 20:00:54 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sat Feb 11 20:00:54 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sun Feb 12 08:08:43 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0121.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 08:08:44 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 08:08:44 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 08:08:44 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 08:08:44 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 08:08:44 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 08:08:44 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 08:08:44 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 08:08:44 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 08:08:44 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 08:08:44 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 08:08:44 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 08:08:44 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 08:08:45 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 08:08:45 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 08:08:45 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 08:08:45 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 08:08:45 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 08:08:45 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sun Feb 12 12:02:34 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0122.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 12:02:35 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 12:02:35 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 12:02:35 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 12:02:35 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 12:02:35 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 12:02:35 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 12:02:35 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 12:02:35 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 12:02:35 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 12:02:35 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 12:02:35 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 12:02:35 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 12:02:35 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 12:02:35 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 12:02:35 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 12:02:35 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 12:02:35 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 12:02:35 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sun Feb 12 16:01:02 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0123.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 16:01:02 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 16:01:02 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 16:01:02 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 16:01:02 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 16:01:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 16:01:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 16:01:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 16:01:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 16:01:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 16:01:03 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 16:01:03 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 16:01:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 16:01:03 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 16:01:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 16:01:03 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 16:01:03 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 16:01:03 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 16:01:03 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Sun Feb 12 20:00:57 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0124.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 20:00:57 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 20:00:57 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 20:00:57 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 20:00:57 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 20:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 20:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 20:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 20:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 20:00:58 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 20:00:58 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 20:00:58 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 20:00:58 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 20:00:58 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 20:00:58 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 20:00:58 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 20:00:58 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Sun Feb 12 20:00:58 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Sun Feb 12 20:00:58 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Mon Feb 13 08:16:07 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0125.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 08:16:07 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 08:16:07 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 08:16:07 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 08:16:07 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 08:16:07 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 08:16:07 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 08:16:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 08:16:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 08:16:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 08:16:08 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 08:16:08 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 08:16:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 08:16:08 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 08:16:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 08:16:08 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 08:16:08 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 08:16:08 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 08:16:08 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Mon Feb 13 12:02:50 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0126.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 12:02:50 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 12:02:50 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 12:02:50 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 12:02:50 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 12:02:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 12:02:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 12:02:50 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 12:02:51 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 12:02:51 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 12:02:51 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 12:02:51 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 12:02:51 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 12:02:51 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 12:02:51 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 12:02:51 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 12:02:51 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 12:02:51 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 12:02:51 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Mon Feb 13 16:01:16 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0127.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 16:01:16 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 16:01:16 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 16:01:16 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 16:01:16 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 16:01:16 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 16:01:16 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 16:01:16 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 16:01:16 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 16:01:16 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 16:01:16 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 16:01:16 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 16:01:16 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 16:01:16 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 16:01:16 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 16:01:16 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 16:01:16 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 16:01:16 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 16:01:16 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Mon Feb 13 20:00:57 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0128.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 20:00:57 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 20:00:57 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 20:00:57 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 20:00:57 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 20:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 20:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 20:00:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 20:00:58 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 20:00:58 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 20:00:58 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 20:00:58 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 20:00:58 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 20:00:58 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 20:00:58 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 20:00:58 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 20:00:58 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Mon Feb 13 20:00:58 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Mon Feb 13 20:00:58 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Tue Feb 14 08:18:08 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0129.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 08:18:08 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 08:18:08 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 08:18:09 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 08:18:09 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 08:18:09 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 08:18:09 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 08:18:09 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 08:18:09 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 08:18:09 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 08:18:09 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 08:18:09 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 08:18:09 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 08:18:10 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 08:18:10 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 08:18:10 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 08:18:10 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 08:18:10 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 08:18:10 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Tue Feb 14 12:03:08 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0130.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 12:03:08 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 12:03:08 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 12:03:08 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 12:03:08 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 12:03:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 12:03:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 12:03:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 12:03:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 12:03:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 12:03:08 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 12:03:08 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 12:03:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 12:03:08 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 12:03:08 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 12:03:08 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 12:03:08 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 12:03:08 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 12:03:08 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Tue Feb 14 16:01:20 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0131.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 16:01:20 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 16:01:20 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 16:01:20 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 16:01:20 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 16:01:20 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 16:01:20 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 16:01:20 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 16:01:20 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 16:01:20 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 16:01:20 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 16:01:20 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 16:01:20 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 16:01:20 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 16:01:20 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 16:01:20 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 16:01:20 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 16:01:20 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 16:01:20 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Tue Feb 14 20:01:02 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0132.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 20:01:02 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 20:01:02 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 20:01:02 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 20:01:02 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 20:01:02 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 20:01:02 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 20:01:02 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 20:01:02 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 20:01:02 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 20:01:02 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 20:01:03 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 20:01:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 20:01:03 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 20:01:03 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 20:01:03 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 20:01:03 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Tue Feb 14 20:01:03 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Tue Feb 14 20:01:03 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Wed Feb 15 08:24:54 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0133.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 08:24:55 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 08:24:55 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 08:24:55 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 08:24:56 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 08:24:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 08:24:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 08:24:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 08:24:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 08:24:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 08:24:57 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 08:24:57 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 08:24:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 08:24:59 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 08:24:59 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 08:24:59 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 08:25:00 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 08:25:00 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 08:25:00 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Wed Feb 15 12:05:01 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0134.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 12:05:01 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 12:05:01 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 12:05:01 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 12:05:01 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 12:05:02 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 12:05:02 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 12:05:02 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 12:05:02 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 12:05:02 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 12:05:02 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 12:05:02 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 12:05:02 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 12:05:02 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 12:05:02 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 12:05:02 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 12:05:02 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 12:05:02 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 12:05:02 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Wed Feb 15 16:01:26 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0135.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 16:01:26 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 16:01:26 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 16:01:26 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 16:01:26 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 16:01:26 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 16:01:26 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 16:01:27 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 16:01:27 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 16:01:27 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 16:01:27 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 16:01:27 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 16:01:27 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 16:01:27 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 16:01:27 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 16:01:27 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 16:01:27 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 16:01:27 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 16:01:27 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Wed Feb 15 19:27:59 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0136.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 19:27:59 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 19:27:59 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 19:27:59 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 19:27:59 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 19:27:59 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 19:27:59 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 19:27:59 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 19:27:59 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 19:27:59 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 19:27:59 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 19:27:59 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 19:27:59 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 19:27:59 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 19:27:59 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 19:27:59 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 19:27:59 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 19:27:59 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 19:27:59 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Wed Feb 15 20:12:41 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0137.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 20:12:41 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 20:12:41 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 20:12:41 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 20:12:41 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 20:12:41 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 20:12:41 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 20:12:41 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 20:12:42 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 20:12:42 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 20:12:42 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 20:12:42 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 20:12:42 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 20:12:42 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 20:12:42 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 20:12:42 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 20:12:42 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Wed Feb 15 20:12:42 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Wed Feb 15 20:12:42 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Thu Feb 16 08:43:52 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0138.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 16 08:43:55 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 16 08:43:55 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 16 08:43:56 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 16 08:43:56 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 16 08:43:56 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 16 08:43:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 16 08:43:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 16 08:43:57 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 16 08:43:58 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 16 08:43:58 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 16 08:43:58 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 16 08:43:58 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 16 08:43:58 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 16 08:43:58 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 16 08:43:59 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 16 08:43:59 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Thu Feb 16 08:43:59 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Thu Feb 16 08:43:59 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael From howard at eegsoftware.com Tue Dec 10 12:36:32 2002 From: howard at eegsoftware.com (howard@eegsoftware.com) Date: Fri Mar 31 16:33:23 2006 Subject: [egenix-users] Windows debug builds (again) Message-ID: <3DF5DFD0.6387.10056B1@localhost> A non-text attachment was scrubbed... Name: not available Type: text/enriched Size: 2489 bytes Desc: not available Url : /mailman-archives/egenix-users/attachments/20021210/cd5ff424/attachment-0139.bin From mal at lemburg.com Tue Dec 10 22:11:15 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Mar 31 16:33:24 2006 Subject: [egenix-users] Windows debug builds (again) References: <3DF5DFD0.6387.10056B1@localhost> Message-ID: <3DF65873.7060301@lemburg.com> howard@eegsoftware.com wrote: > > > > After running the above build command both with and without the --debug > > flag, then "python setup.py install" installed both the release _and_ > debug > > .pyd's to the correct destination. There's no problem of overwriting the > > installation with a debug build because the filenames are different; > > mxDateTime_d.pyd gets used if you're running python_d.exe and > mxDateTime.pyd > > gets used if you're running python.exe. They live happily side by side. > I followed this logic (from the August archives) but I get a page fault > when trying to import mx.DateTime from python_d. The problem reports as > an access violation on the line marked below: > > static > void mxDateTime_Free(mxDateTimeObject *datetime) > { > Py_XDECREF(datetime->argument); > #ifdef MXDATETIME_FREELIST > /* Append mxDateTime objects to free list */ > # ifdef WANT_SUBCLASSABLE_TYPES > if (!_mxDateTime_CheckExact(datetime)) > PyObject_Del(datetime); > else > # endif { > *(mxDateTimeObject **)datetime = mxDateTime_FreeList; > mxDateTime_FreeList = datetime; <=========access violation > _Py_ForgetReference(datetime); ^^^^ this call has to be removed to fix the problem (the same needs to be done for mxDateTimeDelta_Free()). > } > #else PyObject_Del(datetime); > #endif > } > > So, what am I doing wrong ?? This is 2.0.4 and python2.2.2 That's a know bug which will get fixed in 2.1.0. For 2.0.4 you have to disable the free lists: Edit the mxDateTime.c and comment out the two lines /* Define these to have the module use free lists (saves malloc calls) */ #define MXDATETIME_FREELIST #define MXDATETIMEDELTA_FREELIST This should fix the problem for 2.0.4 as well (free lists are a performance improvement which is normally not needed for debugging). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 23 19:49:23 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Mar 31 16:33:24 2006 Subject: [egenix-users] Merry Christmas and a Happy New Year Message-ID: <3E075AB3.1060706@lemburg.com> Hello everybody, I hope you have enjoyed this year with eGenix software and services. We will start off into the new year with exiting new releases of our software including new versions of mxODBC, a Zope database adapter built on top of mxODBC and many updates to our open source packages. Plus there's more to come in the web services arena: the Siena Web Services Architecture will be launched and we're looking into wrapping up more mx-style packages to make your Python experience an even better one. All the best. Thanks, -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 10:18:20 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Mar 31 16:33:24 2006 Subject: [egenix-users] table description? Message-ID: <3E0C6F3C.3000103@holly-springs.nc.us> I'm trying to use the surcor.columns function to get a description of a table's columns. For example: cursor.columns(table="NameAndAddr") ... I'm then looking for a result set. This seems to be what the ODBC docs say I should do, but there's not a result set available. Does anyone have some example code I can try? Thanks, Michael From rothwell at holly-springs.nc.us Fri Dec 27 10:22:38 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Mar 31 16:33:24 2006 Subject: [egenix-users] table description? References: <3E0C6F3C.3000103@holly-springs.nc.us> Message-ID: <3E0C703E.9020507@holly-springs.nc.us> Um... never mind. :) Michael Rothwell wrote: > I'm trying to use the surcor.columns function to get a description of a > table's columns. > > For example: > cursor.columns(table="NameAndAddr") > > ... I'm then looking for a result set. This seems to be what the ODBC > docs say I should do, but there's not a result set available. Does > anyone have some example code I can try? > > Thanks, > > Michael > > > _______________________________________________________________________ > eGenix.com User Mailing List http://www.egenix.com/ > http://lists.egenix.com/mailman/listinfo/egenix-users From rothwell at holly-springs.nc.us Fri Dec 27 15:42:50 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Mar 31 16:33:24 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? Message-ID: <3E0CBB4A.5060701@holly-springs.nc.us> I'm trying to achieve the following: * INSERT a blank record into a table. * update a result set with that inserted row's data (which may have default values and identity fields filled in, now, by the database) * edit the result set * UPDATE the row with the new data ... the trick is selecting the newly inserted row. Does anyone know if there is a way to do this without resorting to a database- and table-specific method (such as using identity fields and slecting @@IDENTITY)? -Michael From mal at lemburg.com Fri Dec 27 22:07:33 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Mar 31 16:33:24 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> Message-ID: <3E0CC115.9060809@lemburg.com> Michael Rothwell wrote: > I'm trying to achieve the following: > > * INSERT a blank record into a table. > > * update a result set with that inserted row's data (which may have > default values and identity fields filled in, now, by the database) > > * edit the result set > > * UPDATE the row with the new data > > > ... the trick is selecting the newly inserted row. Does anyone know if > there is a way to do this without resorting to a database- and > table-specific method (such as using identity fields and slecting > @@IDENTITY)? The best way to do this in a database independent way is to add an ID column to all tables you are using (+ a timestamp column if you want to edit them with MS Access). ODBC only allows you to query the table for "special" columns which are best suited for e.g. identifying rows (see cursor. specialcolumns()). Another method is using database cursors for this task. Note that mxODBC does not support updateable result sets; however you can achieve the same effect with server side cursors. See you DBs docs for details. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Fri Dec 27 16:39:11 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Mar 31 16:33:24 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> Message-ID: <3E0CC87F.8020601@holly-springs.nc.us> M.-A. Lemburg wrote: > The best way to do this in a database independent way is to add > an ID column to all tables you are using (+ a timestamp column if > you want to edit them with MS Access). > > ODBC only allows you to query the table for "special" columns > which are best suited for e.g. identifying rows (see cursor. > specialcolumns()). Thanks. I decided to see how ADO does this, because it seems to work there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not update the in-memory object if there is not an identity field in the table, although the insert works. If there's a timestamp field (or an identity field), then a second .Update() of the new record works. If there's not, ADO botches the update and returns this error message: "Key column information is insufficient or incorrect. Too many rows were affected by update." So it seems that ADO relies on "special columns" too. It would be nice if a standard part of ODBC (and database APIs in general) was a method to get at just-inserted rows. Inside a trigger, one can just look at the "inserted" table (on SQL Server, anyway). I'll look at specialcolumns()... From mal at lemburg.com Sat Dec 28 22:09:11 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Mar 31 16:33:24 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> Message-ID: <3E0E12F7.1010601@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> The best way to do this in a database independent way is to add >> an ID column to all tables you are using (+ a timestamp column if >> you want to edit them with MS Access). >> >> ODBC only allows you to query the table for "special" columns >> which are best suited for e.g. identifying rows (see cursor. >> specialcolumns()). > > > > Thanks. I decided to see how ADO does this, because it seems to work > there. Upon investigation, ADO's RecordSet.AddNew() + .Update() does not > update the in-memory object if there is not an identity field in the > table, although the insert works. If there's a timestamp field (or an > identity field), then a second .Update() of the new record works. If > there's not, ADO botches the update and returns this error message: > > "Key column information is insufficient or incorrect. Too many rows were > affected by update." > > So it seems that ADO relies on "special columns" too. > > It would be nice if a standard part of ODBC (and database APIs in > general) was a method to get at just-inserted rows. Inside a trigger, > one can just look at the "inserted" table (on SQL Server, anyway). The DB-API lists a standard extension for this purpose: Cursor Attribute .lastrowid This read-only attribute provides the rowid of the last modified row (most databases return a rowid only when a single INSERT operation is performed). If the operation does not set a rowid or if the database does not support rowids, this attribute should be set to None. The semantics of .lastrowid are undefined in case the last executed statement modified more than one row, e.g. when using INSERT with .executemany(). However, only few databases provide this information to the application. What I'd suggest is to use a database sequence generator to create unique IDs and then use these during the INSERT. Most database provide something along these lines or can simulate such a generator using auto-increment columns. That way you know the identity of the row *before* inserting it -- usually much better if you plan to use contraints and the like on the table. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Sun Dec 29 12:00:32 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Mar 31 16:33:24 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> Message-ID: <3E0F2A30.4080001@holly-springs.nc.us> M.-A. Lemburg wrote: > > The DB-API lists a standard extension for this purpose: > > Cursor Attribute .lastrowid It doesn't look like mx.ODBC supports it -- "attribute error," and a search through the .py files produces no matches for "lastrowid." > > That way you know the identity of the row *before* inserting > it -- usually much better if you plan to use contraints and > the like on the table. > Yeah, but that doesn't do me any good when working with a pre-existing database schema. Thanks, -Michael From rothwell at holly-springs.nc.us Mon Dec 30 10:04:25 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Mar 31 16:33:24 2006 Subject: [egenix-users] cursor.specialcolumns Message-ID: <3E106079.4010402@holly-springs.nc.us> I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I can't seem to get cursor.specialcolumns() to yield a result set. I'm trying it against a table with a primary key, and an identity field. The default arguments are as follows: specialcolumns(qualifier=None,owner=None,table=None, coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, nullable=SQL.NO_NULLS) Unfortunately, the ODBC docs say this: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp When requesting row identifiers (IdentifierType SQL_BEST_ROWID), SQLSpecialColumns returns an empty result set (no data rows) for any requested scope other than SQL_SCOPE_CURROW. The generated result set indicates that the columns are only valid within this scope. So, I do this: cursor.specialcolumns (table="MyTable", scope=0) I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". No results. I tried running a query that selects a single column, and then run specialcolumns. No result set. How might I get specialcolumns() to tell me what the special columns for a table are? From mal at lemburg.com Mon Dec 30 19:07:06 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Mar 31 16:33:24 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E106079.4010402@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> Message-ID: <3E108B4A.7020708@lemburg.com> Michael Rothwell wrote: > I've been reading the mxODBC docs, and the ODBC docs (at MSDN), and I > can't seem to get cursor.specialcolumns() to yield a result set. I'm > trying it against a table with a primary key, and an identity field. The > default arguments are as follows: > > specialcolumns(qualifier=None,owner=None,table=None, > coltype=SQL.BEST_ROWID,scope=SQL.SCOPE_SESSION, > nullable=SQL.NO_NULLS) > > Unfortunately, the ODBC docs say this: > http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbcsql/od_odbc_s_8q2b.asp > > When requesting row identifiers (IdentifierType SQL_BEST_ROWID), > SQLSpecialColumns returns an empty result set (no data rows) for any > requested scope other than SQL_SCOPE_CURROW. The generated result set > indicates that the columns are only valid within this scope. > > So, I do this: > cursor.specialcolumns (table="MyTable", scope=0) > > I use zero because I'm not sure how to get access to "SQL.SCOPE_CURROW". The SQL singleton object is defined at mxODBC subpackage level, e.g. on Windows you'd write: mx.ODBC.Windows.SQL.SCOPE_CURROW > No results. I tried running a query that selects a single column, and > then run specialcolumns. No result set. > > How might I get specialcolumns() to tell me what the special columns for > a table are? This could be caused by the defaults for qualifier and owner. When set to None these are translated to SQL NULL values and should result in a match-any query. However, some drivers require different values to result in this meaning, e.g. an empty string or '%'. I'd suggest to first get a feeling for how to specify a table in the database using e.g. cursor.columns() before trying to find the right parameters for .specialcolumns(). -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From mal at lemburg.com Mon Dec 30 19:09:58 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Mar 31 16:33:24 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? In-Reply-To: <3E0F2A30.4080001@holly-springs.nc.us> References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> Message-ID: <3E108BF6.8070609@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> >> The DB-API lists a standard extension for this purpose: >> >> Cursor Attribute .lastrowid > > > It doesn't look like mx.ODBC supports it -- "attribute error," and a > search through the .py files produces no matches for "lastrowid." Right. That's because ODBC doesn't allow querying this information (at least not to my knowledge). >> That way you know the identity of the row *before* inserting >> it -- usually much better if you plan to use contraints and >> the like on the table. >> > Yeah, but that doesn't do me any good when working with a pre-existing > database schema. In that case you'll have to figure out a set of columns using .specialcolumns(). I still don't understand how you would identify a newly inserted row like this, though. If the database provides defaults and maybe uses a trigger to fill in an ID column, then the knowledge of such a column wouldn't get you any further. Maybe I'm missing something ? -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 13:25:30 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Mar 31 16:33:24 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> Message-ID: <3E108F9A.1030001@holly-springs.nc.us> M.-A. Lemburg wrote: > I'd suggest to first get a feeling for how to specify a > table in the database using e.g. cursor.columns() before > trying to find the right parameters for .specialcolumns(). cursor.columns(table="mytable") works. Also specifying the qualifier and owner as the database name and owner works. Neither works with specialcolumns(). From rothwell at holly-springs.nc.us Mon Dec 30 13:30:14 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Mar 31 16:33:24 2006 Subject: [egenix-users] how to insert new row, update in-memory object with same row from database? References: <3E0CBB4A.5060701@holly-springs.nc.us> <3E0CC115.9060809@lemburg.com> <3E0CC87F.8020601@holly-springs.nc.us> <3E0E12F7.1010601@lemburg.com> <3E0F2A30.4080001@holly-springs.nc.us> <3E108BF6.8070609@lemburg.com> Message-ID: <3E1090B6.2060001@holly-springs.nc.us> M.-A. Lemburg wrote: > In that case you'll have to figure out a set of columns using > .specialcolumns(). I still don't understand how you would > identify a newly inserted row like this, though. If the database > provides defaults and maybe uses a trigger to fill in an ID > column, then the knowledge of such a column wouldn't get you > any further. Maybe I'm missing something ? Well, it would be a sub-optimal solution. I'd have to coax the last insert ID out of the database, somehow, and then select using that key. On SQL Server, I would run "select @@IDENTITY," for instance, right after the insert of a single row. Then, query for that row to get all of the default values. There's really no clean way to do it, as far as I can tell. Seems like a hole in the RDBMS concept -- one has to know the key to get the key. The best option is the one you mentioned -- create the unique IDs myself and store them in the tables, rather than using identity fields or equivalents. Still not very clean, but workable with a new scheme, at least. Thanks, -M From mal at lemburg.com Mon Dec 30 20:22:57 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Mar 31 16:33:24 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E108F9A.1030001@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> Message-ID: <3E109D11.4080508@lemburg.com> Michael Rothwell wrote: > M.-A. Lemburg wrote: > >> I'd suggest to first get a feeling for how to specify a >> table in the database using e.g. cursor.columns() before >> trying to find the right parameters for .specialcolumns(). > > > cursor.columns(table="mytable") works. Also specifying the qualifier and > owner as the database name and owner works. Neither works with > specialcolumns(). Strange. Perhaps this has something to do with nullable ?! ... """ Nullable [Input] Determines whether to return special columns that can have a NULL value. Must be one of the following: SQL_NO_NULLS: Exclude special columns that can have NULL values. Some drivers cannot support SQL_NO_NULLS, and these drivers will return an empty result set if SQL_NO_NULLS was specified. Applications should be prepared for this case and request SQL_NO_NULLS only if it is absolutely required. SQL_NULLABLE: Return special columns even if they can have NULL values. """ and there's also other possibilities: """ If there are no columns that uniquely identify each row in the table, SQLSpecialColumns returns a rowset with no rows; a subsequent call to SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. If the IdentifierType, Scope, or Nullable arguments specify characteristics that are not supported by the data source, SQLSpecialColumns returns an empty result set. """ Hmm, looking at the C code: there's a typo which seems to cause keyword arguments to not work properly. This could be the cause for the empty result sets. Please try the argument in the order given in the documentation and pass them in without argument names. I just .specialcolumns() with SAP DB and did get some results this way: >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, SQL.SCOPE_TRANSACTION) 1 >>> c.fetchall() [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >>> c.execute('select SYSKEY from EGENIX_VISITORS') >>> c.fetchall() [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] This seems to be an internal row identifying key used by the database internally. It is not defined in the table schema. OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 16:39:40 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Mar 31 16:33:24 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> Message-ID: <3E10BD1C.5060603@holly-springs.nc.us> Well, passing the arguments all in the right order worked: x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) It didn't matter if I used NO_NULLS or NULLABLE. -Michael M.-A. Lemburg wrote: > Michael Rothwell wrote: > >> M.-A. Lemburg wrote: >> >>> I'd suggest to first get a feeling for how to specify a >>> table in the database using e.g. cursor.columns() before >>> trying to find the right parameters for .specialcolumns(). >> >> >> >> cursor.columns(table="mytable") works. Also specifying the qualifier >> and owner as the database name and owner works. Neither works with >> specialcolumns(). > > > Strange. Perhaps this has something to do with nullable ?! ... > > """ > Nullable > [Input] > Determines whether to return special columns that can have a NULL > value. Must be one of the following: > > SQL_NO_NULLS: Exclude special columns that can have NULL values. > Some drivers cannot support SQL_NO_NULLS, and these drivers will return > an empty result set if SQL_NO_NULLS was specified. Applications should > be prepared for this case and request SQL_NO_NULLS only if it is > absolutely required. > > SQL_NULLABLE: Return special columns even if they can have NULL values. > """ > > and there's also other possibilities: > > """ > If there are no columns that uniquely identify each row in the table, > SQLSpecialColumns returns a rowset with no rows; a subsequent call to > SQLFetch or SQLFetchScroll on the statement returns SQL_NO_DATA. > > If the IdentifierType, Scope, or Nullable arguments specify > characteristics that are not supported by the data source, > SQLSpecialColumns returns an empty result set. > """ > > Hmm, looking at the C code: there's a typo which seems to cause keyword > arguments to not work properly. This could be the cause for the empty > result sets. > > Please try the argument in the order given in the documentation > and pass them in without argument names. > > I just .specialcolumns() with SAP DB and did get some results this > way: > > >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, > SQL.SCOPE_TRANSACTION) > 1 > >>> c.fetchall() > [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] > >>> c.execute('select SYSKEY from EGENIX_VISITORS') > >>> c.fetchall() > [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] > > This seems to be an internal row identifying key used by the database > internally. It is not defined in the table schema. > > OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. > From mal at lemburg.com Mon Dec 30 23:34:04 2002 From: mal at lemburg.com (M.-A. Lemburg) Date: Fri Mar 31 16:33:24 2006 Subject: [egenix-users] cursor.specialcolumns In-Reply-To: <3E10BD1C.5060603@holly-springs.nc.us> References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> Message-ID: <3E10C9DC.8000309@lemburg.com> Michael Rothwell wrote: > Well, passing the arguments all in the right order worked: > > x.cursor.specialcolumns(None,None,"NameAndAddr",mx.ODBC.Windows.SQL.BEST_ROWID, > mx.ODBC.Windows.SQL.SCOPE_CURROW, mx.ODBC.Windows.SQL.NO_NULLS) > > It didn't matter if I used NO_NULLS or NULLABLE. Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most secure way of dealing with your particular problem. >> Hmm, looking at the C code: there's a typo which seems to cause keyword >> arguments to not work properly. This could be the cause for the empty >> result sets. >> >> Please try the argument in the order given in the documentation >> and pass them in without argument names. >> >> I just .specialcolumns() with SAP DB and did get some results this >> way: >> >> >>> c.specialcolumns(None, None, 'EGENIX_VISITORS', SQL.BEST_ROWID, >> SQL.SCOPE_TRANSACTION) >> 1 >> >>> c.fetchall() >> [(1, 'SYSKEY', -2, 'CHAR() BYTE', 8, 8, None, 2, 'BYTE')] >> >>> c.execute('select SYSKEY from EGENIX_VISITORS') >> >>> c.fetchall() >> [('\xff\xfe\x00\x00\x00\x00\x00\x01',),] >> >> This seems to be an internal row identifying key used by the database >> internally. It is not defined in the table schema. >> >> OTOH, SQL.ROWVER doesn't seem to be supported by SAP DB at all. -- Marc-Andre Lemburg CEO eGenix.com Software GmbH _______________________________________________________________________ eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,... Python Consulting: http://www.egenix.com/ Python Software: http://www.egenix.com/files/python/ From rothwell at holly-springs.nc.us Mon Dec 30 23:12:37 2002 From: rothwell at holly-springs.nc.us (Michael Rothwell) Date: Fri Mar 31 16:33:24 2006 Subject: [egenix-users] cursor.specialcolumns References: <3E106079.4010402@holly-springs.nc.us> <3E108B4A.7020708@lemburg.com> <3E108F9A.1030001@holly-springs.nc.us> <3E109D11.4080508@lemburg.com> <3E10BD1C.5060603@holly-springs.nc.us> <3E10C9DC.8000309@lemburg.com> Message-ID: <3E111935.5050906@holly-springs.nc.us> M.-A. Lemburg wrote: > > Does SQL.SCOPE_TRANSACTION also work ? I'd take that as most > secure way of dealing with your particular problem. No. I'm using SQL Server, and the MSDN docs indicate that only CURROW will yeild results with SQL Server. I tried it anyway, and didn't get anything. -Michael