Good news! I was able to reproduce the exception after modifying your test 
script.  Attached is my info and the script.

Below is also repeated at the beginning of the two files.

NOTE: You will need to edit connect_to_mssql()
I was able to get the following error using this script.

--------mssql_implicit_ret.py--------------

ERROR: test_ins (__main__.TestInsWTrigger)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "mssql_implicit_ret.py", line 56, in test_ins
    r = con.execute(self.t1.insert(), descr='there')
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", 
line 1450, in execute
    params)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", 
line 1583, in _execute_clauseelement
    compiled_sql, distilled_params
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", 
line 1709, in _execute_context
    context.post_exec()
  File 
"/usr/local/lib/python2.7/site-packages/sqlalchemy/dialects/mssql/pyodbc.py", 
line 199, in post_exec
    self._lastrowid = int(row[0])
TypeError: int() argument must be a string or a number, not 'NoneType'

------------my_info.txt---------------------

Note, I had to update to sqlalchemy version 0.7.6 to run your unit test 
because engine did not have the begin method in 0.7.3.  Below is my 
information prior to that single update.  Nothing else needed to be updated.

There are actually two potential bugs I'm seeing

1.) File 
"/usr/local/lib/python2.7/site-packages/sqlalchemy/dialects/mssql/pyodbc.py", 
line 199, in post_exec
    self._lastrowid = int(row[0])
2.) use_scope_identity=False appears to do nothing.

Thanks,

Derek


On Monday, April 2, 2012 5:37:35 PM UTC-5, Michael Bayer wrote:
>
> Also, attached is a test script based on our unit tests which illustrates 
> the feature working as expected - can you run this on a test database on 
> your end, and if it passes, try to modify the trigger/table def so that it 
> reproduces your output ?  the test creates/drops two tables and a trigger. 
>   thanks.
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/sqlalchemy/-/h9aqQCA-8WwJ.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.

Note, I had to update to sqlalchemy version 0.7.6 to run your unit test because 
engine did not have the begin method in 0.7.3.  Below is my information prior 
to that single update.  Nothing else needed to be updated.

There are actually two potential bugs I'm seeing

1.) File 
"/usr/local/lib/python2.7/site-packages/sqlalchemy/dialects/mssql/pyodbc.py", 
line 199, in post_exec
    self._lastrowid = int(row[0])
2.) use_scope_identity=False appears to do nothing.

---------INFO---------
Here is the query I'm seeing.

INFO:sqlalchemy.engine.base.Engine:INSERT INTO t1 (v1, v2, v3, v4) VALUES (?, 
?, ?, ?); select scope_identity()

The query is identical even while passing use_scope_identity=False to 
create_engine.

Python 2.7.2 (default, Oct 28 2011, 14:19:36) 
[GCC 4.6.1] on linux3
Type "help", "copyright", "credits" or "license" for more information.
>>> import sqlalchemy
>>> sqlalchemy.__version__
'0.7.3'
>>> 

$pip freeze
...
pyodbc==2.1.11
...

My connection string contains the following.

DRIVER={FreeTDS}
TDS_Version=8.0

/etc/odbcinst.ini has the following.

[FreeTDS]
Description = TDS driver (Sybase/MS SQL)
Driver = /usr/lib/odbc/libtdsodbc.so
Setup = /usr/lib/odbc/libtdsS.so
CPTimeout = 60
CPReuse = 60


I'm using packages provided for Ubuntu 11.10 information below from commandline.

apt-cache showpkg unixodbc unixodbc-dev tdsodbc

Package: unixodbc
Versions: 
2.2.14p2-2ubuntu1 
(/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_oneiric_main_binary-amd64_Packages)
 (/var/lib/dpkg/status)
 Description Language: en
                 File: 
/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_oneiric_main_i18n_Translation-en
                  MD5: 9159fbc3e0e2f0a80f88f9105f827a83
 Description Language: 
                 File: 
/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_oneiric_main_binary-amd64_Packages
                  MD5: 9159fbc3e0e2f0a80f88f9105f827a83


Reverse Depends: 
  unixodbc:i386,unixodbc
  bibus,unixodbc
  slapd,unixodbc 2.2.11
  php5-odbc,unixodbc 2.2.11
  libreoffice-base,unixodbc
  libreoffice,unixodbc
  libqt4-sql-odbc,unixodbc 2.2.11
  tdsodbc:i386,unixodbc 2.1.1-2
  odbcinst1debian2:i386,unixodbc 2.1.1-2
  odbcinst:i386,unixodbc 2.1.1-2
  libodbcinstq1c2:i386,unixodbc 2.2.4-1
  libodbcinstq1c2:i386,unixodbc 2.2.4-1
  unixodbc-bin,unixodbc 2.2.11
  tclodbc,unixodbc 2.2.11
  swi-prolog-odbc,unixodbc 2.2.11
  ruby-odbc,unixodbc
  r-cran-rodbc,unixodbc 2.2.11
  python-pyodbc-dbg,unixodbc 2.2.11
  python-pyodbc,unixodbc 2.2.11
  proftpd-mod-odbc,unixodbc 2.2.11
  perdition-odbc,unixodbc 2.2.11
  odbc-postgresql,unixodbc
  libsqliteodbc,unixodbc
  libsimpledb2,unixodbc 2.2.11-1
  libpt2.10.2,unixodbc 2.2.11
  libpocoodbc9-dbg,unixodbc 2.2.11
  libpocoodbc9,unixodbc 2.2.11
  libmyodbc,unixodbc
  libgsmsd7,unixodbc 2.2.11
  libgnadeodbc2,unixodbc 2.2.11
  libgnadeodbc1-dev,unixodbc 2.2.11-16
  libghc-haskelldb-hdbc-odbc-dev,unixodbc 2.2.11
  libgdal1-1.7.0,unixodbc 2.2.11
  libdbd-odbc-perl,unixodbc 2.2.11
  libdballe4,unixodbc 2.2.11
  libccscript3-1.1-0,unixodbc 2.2.11-1
  libaprutil1-dbd-odbc,unixodbc 2.2.11
  libapache2-mod-shib2,unixodbc 2.2.11
  gretl,unixodbc 2.2.11
  grass,unixodbc 2.2.11
  globus-rls-server,unixodbc 2.2.11
  gambas2-gb-db-odbc,unixodbc 2.2.11
  freetds-bin,unixodbc 2.2.11
  cl-sql-tests,unixodbc
  bibus,unixodbc
  asterisk-voicemail-odbcstorage,unixodbc 2.2.11
  asterisk-modules,unixodbc 2.2.11
  unixodbc-dev,unixodbc 2.2.14p2-2ubuntu1
  tdsodbc,unixodbc 2.1.1-2
  tdsodbc,unixodbc
  slapd,unixodbc 2.2.11
  php5-odbc,unixodbc 2.2.11
  odbcinst1debian2,unixodbc 2.1.1-2
  odbcinst,unixodbc 2.1.1-2
  libreoffice-base,unixodbc
  libreoffice,unixodbc
  libqt4-sql-odbc,unixodbc 2.2.11
  libodbcinstq1c2,unixodbc 2.2.4-1
  libodbcinstq1c2,unixodbc 2.2.4-1
  libodbcinstq1c2,unixodbc 2.2.11
  erlang-odbc,unixodbc 2.2.11
Dependencies: 
2.2.14p2-2ubuntu1 - libc6 (2 2.7) libltdl7 (2 2.2.6b) libreadline6 (2 6.0) 
odbcinst1debian2 (2 2.2.11-3) libmyodbc (0 (null)) odbc-postgresql (0 (null)) 
tdsodbc (0 (null)) unixodbc-bin (0 (null)) unixodbc-bin (3 2.2.4-1) 
unixodbc-bin:i386 (3 2.2.4-1) unixodbc:i386 (0 (null)) 
Provides: 
2.2.14p2-2ubuntu1 - 
Reverse Provides: 
Package: unixodbc-dev
Versions: 
2.2.14p2-2ubuntu1 
(/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_oneiric_main_binary-amd64_Packages)
 (/var/lib/dpkg/status)
 Description Language: en
                 File: 
/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_oneiric_main_i18n_Translation-en
                  MD5: 810ff6350f7d3725bcea408feaf73610
 Description Language: 
                 File: 
/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_oneiric_main_binary-amd64_Packages
                  MD5: 810ff6350f7d3725bcea408feaf73610


Reverse Depends: 
  unixodbc-dev:i386,unixodbc-dev
  libqt4-dev,unixodbc-dev
  libpt-dev,unixodbc-dev
  libocamlodbc-ocaml-dev,unixodbc-dev
  libghc-hsql-odbc-dev,unixodbc-dev
  libghc-hdbc-odbc-dev,unixodbc-dev 2.2.11
  libgdal1-dev,unixodbc-dev
  cl-sql-odbc,unixodbc-dev
  libqt4-dev,unixodbc-dev
Dependencies: 
2.2.14p2-2ubuntu1 - unixodbc (5 2.2.14p2-2ubuntu1) odbcinst1debian2 (5 
2.2.14p2-2ubuntu1) libodbcinstq1c2 (5 2.2.14p2-2ubuntu1) libltdl3-dev (0 
(null)) libqt3-mt-dev (0 (null)) libiodbc2-dev (0 (null)) libiodbc2-dev:i386 (0 
(null)) remembrance-agent (3 2.11-4) remembrance-agent:i386 (3 2.11-4) 
unixodbc-dev:i386 (0 (null)) 
Provides: 
2.2.14p2-2ubuntu1 - 
Reverse Provides: 
Package: tdsodbc
Versions: 
0.82-7 
(/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_oneiric_main_binary-amd64_Packages)
 (/var/lib/dpkg/status)
 Description Language: en
                 File: 
/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_oneiric_main_i18n_Translation-en
                  MD5: 0fecf9617c4dc2509f73a437bea0f895
 Description Language: 
                 File: 
/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_oneiric_main_binary-amd64_Packages
                  MD5: 0fecf9617c4dc2509f73a437bea0f895


Reverse Depends: 
  tdsodbc:i386,tdsodbc
  libreoffice-base,tdsodbc
  unixodbc,tdsodbc
  libreoffice-base,tdsodbc
Dependencies: 
0.82-7 - libc6 (2 2.8) odbcinst1debian2 (2 2.2.11-3) debconf (18 0.5) 
debconf-2.0 (0 (null)) freetds-common (0 (null)) libiodbc2 (16 (null)) unixodbc 
(0 (null)) freetds0 (0 (null)) freetds0:i386 (0 (null)) libct0 (0 (null)) 
libct0:i386 (0 (null)) unixodbc (3 2.1.1-2) unixodbc:i386 (3 2.1.1-2) freetds0 
(0 (null)) freetds0:i386 (0 (null)) libct0 (0 (null)) libct0:i386 (0 (null)) 
libct1 (0 (null)) libct1:i386 (0 (null)) tdsodbc:i386 (0 (null)) 
Provides: 
0.82-7 - 
Reverse Provides: 

"""
NOTE: You will need to edit connect_to_mssql()
I was able to get the following error using this script.

ERROR: test_ins (__main__.TestInsWTrigger)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "mssql_implicit_ret.py", line 56, in test_ins
    r = con.execute(self.t1.insert(), descr='there')
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1450, in execute
    params)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1583, in _execute_clauseelement
    compiled_sql, distilled_params
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1709, in _execute_context
    context.post_exec()
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/dialects/mssql/pyodbc.py", line 199, in post_exec
    self._lastrowid = int(row[0])
TypeError: int() argument must be a string or a number, not 'NoneType'"""


from sqlalchemy import create_engine, MetaData, Table, Column, \
    Sequence, Integer,String,DateTime, event, DDL
import unittest
import logging
import pyodbc

logging.basicConfig(filename='alc_test.log', level=logging.DEBUG)
logging.getLogger('sqlalchemy.engine').setLevel(logging.DEBUG)

def connect_to_mssql():
    return pyodbc.connect('DRIVER={FreeTDS};SERVER=your_server;DATABASE=your_database;UID=your_uid;PWD=your_pw;TDS_Version=8.0')

class TestInsWTrigger(unittest.TestCase):

    def setUp(self):
        self.engine = create_engine("mssql+pyodbc://", echo=True, creator=connect_to_mssql)
        self.meta = meta = MetaData()
        self.t1 = Table('t1', meta,
                Column('id', Integer, Sequence('fred', 100, 1),
                                primary_key=True),
                Column('descr', String(200)),
		Column('date', DateTime()),
                implicit_returning = False 
        )
        self.t2 = Table('t2', meta,
                Column('id', Integer, Sequence('fred', 200, 1),
                                primary_key=True),
                Column('descr', String(200)))

        event.listen(meta, "after_create", 
            DDL("""\
        create trigger paj on t1 instead of insert as
	BEGIN
            SET IDENTITY_INSERT t1 ON
	    INSERT INTO t1(id, descr, date)
	    SELECT
		ISNULL((SELECT MAX(id) FROM t1) + 1, 1) AS id,
		descr,
		GETDATE() AS date
	    FROM inserted
	    SET IDENTITY_INSERT t1 OFF
        END""")
        )
        event.listen(meta, "before_drop", 
            DDL("drop trigger paj")
        )
        meta.create_all(self.engine)

    def tearDown(self):
        self.meta.drop_all(self.engine)

    def test_ins(self):
        with self.engine.begin() as con:
            r = con.execute(self.t2.insert(), descr='hello')
            self.assert_(r.inserted_primary_key == [200])
            r = con.execute(self.t1.insert(), descr='there')
            self.assert_(r.inserted_primary_key == [100])
            logging.info('>>>>>>>>>' + str(con.execute(self.t2.select()).fetchall()))
            #self.assert_(
            #    con.execute(self.t2.select()).fetchall() == 
            #    [(200, 'hello'), (201, 'there')]
            #)
            logging.info('>>>>>>>>>' + str(con.execute(self.t1.select()).fetchall()))
            #self.assert_(
            #    con.execute(self.t1.select()).fetchall() == 
            #    [(100, 'there')]
            #)
            
if __name__ == '__main__':
    unittest.main()

Reply via email to