WilliamRen / django-pyodbc

Automatically exported from code.google.com/p/django-pyodbc
BSD 3-Clause "New" or "Revised" License
0 stars 0 forks source link

Looks like django-pyodbc uses default database driver, somehow, when using DATABASES #72

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
What steps will reproduce the problem?
1. First, try this config:
DATABASES = {
    'notdefault': {
        'NAME': 'mysqldb',
        'ENGINE': 'mysql',
        'USER': 'user',
        'PASSWORD': 'pass',
    },
    'mssql': {
        'NAME': 'dbname',
        'ENGINE': 'sql_server.pyodbc',
        'HOST': 'host',
        'PORT': 'port',
        'USER': 'user',
        'PASSWORD': 'passwd',
        'OPTIONS': {
            'driver': 'FreeTDS',
            'dsn': 'dsn', # ODBC DSN name defined in your odbc.ini
        }
    },
    'default': {
        'NAME': 'dbname',
        'ENGINE': 'sql_server.pyodbc',
        'HOST': 'host',
        'PORT': 'port',
        'USER': 'user',
        'PASSWORD': 'passwd',
        'OPTIONS': {
            'driver': 'FreeTDS',
            'dsn': 'dsn', # ODBC DSN name defined in your odbc.ini
        }
    },
}

2. run python manage.py inspectdb --database=mssql
It works! 
3. Now, try this config:
DATABASES = {
    'default': {
        'NAME': 'mysqldb',
        'ENGINE': 'mysql',
        'USER': 'user',
        'PASSWORD': 'pass',
    },
    'mssql': {
        'NAME': 'dbname',
        'ENGINE': 'sql_server.pyodbc',
        'HOST': 'host',
        'PORT': 'port',
        'USER': 'user',
        'PASSWORD': 'passwd',
        'OPTIONS': {
            'driver': 'FreeTDS',
            'dsn': 'dsn', # ODBC DSN name defined in your odbc.ini
        }
    },
    'notdefault': {
        'NAME': 'dbname',
        'ENGINE': 'sql_server.pyodbc',
        'HOST': 'host',
        'PORT': 'port',
        'USER': 'user',
        'PASSWORD': 'passwd',
        'OPTIONS': {
            'driver': 'FreeTDS',
            'dsn': 'dsn', # ODBC DSN name defined in your odbc.ini
        }
    },
}

What is the expected output? What do you see instead?
Because in both cases you're referencing the database named 'mssql', you'd
expect the exact same output. However, when the 'default' database is a
mysql database rather than SQL server (as in second example), I get the
following error:
Traceback (most recent call last):
  File "manage.py", line 11, in <module>
    execute_manager(settings)
  File "PATH/TO/SITE-PACKAGES/django/core/management/__init__.py", line
438, in execute_manager
    utility.execute()
  File "PATH/TO/SITE-PACKAGES/django/core/management/__init__.py", line
379, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "PATH/TO/SITE-PACKAGES/django/core/management/base.py", line 195, in
run_from_argv
    self.execute(*args, **options.__dict__)
  File "PATH/TO/SITE-PACKAGES/django/core/management/base.py", line 222, in
execute
    output = self.handle(*args, **options)
  File "PATH/TO/SITE-PACKAGES/django/core/management/base.py", line 351, in
handle
    return self.handle_noargs(**options)
  File
"PATH/TO/SITE-PACKAGES/django/core/management/commands/inspectdb.py", line
22, in handle_noargs
    for line in self.handle_inspection(options):
  File
"PATH/TO/SITE-PACKAGES/django/core/management/commands/inspectdb.py", line
32, in handle_inspection
    cursor = connection.cursor()
  File "PATH/TO/SITE-PACKAGES/django/db/backends/__init__.py", line 75, in
cursor
    cursor = self._cursor()
  File "PATH/TO/SITE-PACKAGES/sql_server/pyodbc/base.py", line 235, in _cursor
    if self.ops.sql_server_ver < 2005:
  File "PATH/TO/SITE-PACKAGES/sql_server/pyodbc/operations.py", line 22, in
_get_sql_server_ver
    cur.execute("SELECT CAST(SERVERPROPERTY('ProductVersion') as varchar)")
  File "PATH/TO/SITE-PACKAGES/django/db/backends/util.py", line 19, in execute
    return self.cursor.execute(sql, params)
  File "PATH/TO/SITE-PACKAGES/django/db/backends/mysql/base.py", line 84,
in execute
    return self.cursor.execute(query, args)
  File "build/bdist.linux-x86_64/egg/MySQLdb/cursors.py", line 173, in execute
  File "build/bdist.linux-x86_64/egg/MySQLdb/connections.py", line 36, in
defaulterrorhandler
_mysql_exceptions.ProgrammingError: (1064, "You have an error in your SQL
syntax; check the manual that corresponds to your MySQL server version for
the right syntax to use near 'varchar)' at line 1")

What version of the product are you using? On what operating system?
I'm using revision 176 of django-pyodbc with latest development version of
Django (revision 12303). This is on RHEL5.

Please provide any additional information below.

Original issue reported on code.google.com by jordanth...@gmail.com on 27 Jan 2010 at 6:53

GoogleCodeExporter commented 8 years ago
The error is in sql_server/pyodbc/operations.py:
20:            from django.db import connection
here's where connection is defined:

django/db/__init__.py   
74: connection = connections[DEFAULT_DB_ALIAS]

So, the connection will *always* be whatever was set as the default alias.

I'm a relative newbie with python so I'm leery of writing a patch myself. It 
also
looks like operations.py currently depends on the existence of the global 
settings
variable, and I have no idea how it would get the desired connection object 
without
rewriting DatabaseOperations to take (self) in the init function (although, to 
be
fair, it looks like that is what has had to happen for all of the other similar 
objects).

Original comment by jordanth...@gmail.com on 27 Jan 2010 at 7:25

GoogleCodeExporter commented 8 years ago
Okay, patch attached. This is the FIRST TIME I have ever done a patch, and 
again I'm
not a Python whiz, so please check it.

Basically, I changed the call to DatabaseOperations so that it sends the alias 
name,
and then in DatabaseOperations instead of just pulling in 
db.backends.connection, I
pull in db.backends.connections and set connection to 
db.backends.connections[alias name]

I feel like sending the alias name is a bit odd and awkward, but due to when the
actual connection object is created, I can't actually send the connection 
object to
DatabaseOperations (as is done in the PostGres implementation). The connection 
object
has to be grabbed after the fact from db.backends.

Original comment by jordanth...@gmail.com on 27 Jan 2010 at 8:48

Attachments:

GoogleCodeExporter commented 8 years ago
Fixed in r177.

Original comment by vcc.ch...@gmail.com on 27 Jan 2010 at 1:50

GoogleCodeExporter commented 8 years ago
The r177 didn't correct the problem for me. That is because Django API obtains 
the version using the "sql_server_ver" property, not the function call and when 
that happens it gets the wrong connection.

I used the patch proposed here and THAT worked just fine.

Original comment by Kani...@gmail.com on 10 Jan 2011 at 9:56

Attachments:

GoogleCodeExporter commented 8 years ago
r186 should fixed it.

Original comment by vcc.ch...@gmail.com on 17 Apr 2011 at 4:03