Skip to content

dbname not set at cursor create time #16

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Neamat opened this issue Apr 10, 2017 · 13 comments
Open

dbname not set at cursor create time #16

Neamat opened this issue Apr 10, 2017 · 13 comments
Labels

Comments

@Neamat
Copy link

Neamat commented Apr 10, 2017

I followed all the steps that you mentioned in your docs but I always get the same error "dbname not set at cursor create time" when I run the project. I even sent a static database name inside the mapper just to try it and it returned the same error. It looks like it cannot initiate with the default database that I already added inside the settings. Any suggestions?

@stephane
Copy link
Collaborator

@Neamat
Copy link
Author

Neamat commented Apr 12, 2017

Thank you for your reply.
The following is the error trace:

Unhandled exception in thread started by <function wrapper at 0x0000000003F77AC8>
Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\django\utils\autoreload.py", line 226, in wrapper
    fn(*args, **kwargs)
  File "C:\Python27\lib\site-packages\django\core\management\commands\runserver.py", line 116, in inner_run
    self.check(display_num_errors=True)
  File "C:\Python27\lib\site-packages\django\core\management\base.py", line 426, in check
    include_deployment_checks=include_deployment_checks,
  File "C:\Python27\lib\site-packages\django\core\checks\registry.py", line 75, in run_checks
    new_errors = check(app_configs=app_configs)
  File "C:\Python27\lib\site-packages\django\core\checks\model_checks.py", line 28, in check_all_models
    errors.extend(model.check(**kwargs))
  File "C:\Python27\lib\site-packages\django\db\models\base.py", line 1170, in check
    errors.extend(cls._check_fields(**kwargs))
  File "C:\Python27\lib\site-packages\django\db\models\base.py", line 1247, in _check_fields
    errors.extend(field.check(**kwargs))
  File "C:\Python27\lib\site-packages\django\db\models\fields\__init__.py", line 925, in check
    errors = super(AutoField, self).check(**kwargs)
  File "C:\Python27\lib\site-packages\django\db\models\fields\__init__.py", line 208, in check
    errors.extend(self._check_backend_specific_checks(**kwargs))
  File "C:\Python27\lib\site-packages\django\db\models\fields\__init__.py", line 317, in _check_backend_specific_checks
    return connections[db].validation.check_field(self, **kwargs)
  File "C:\Python27\lib\site-packages\django\db\backends\mysql\validation.py", line 18, in check_field
    field_type = field.db_type(connection)
  File "C:\Python27\lib\site-packages\django\db\models\fields\__init__.py", line 625, in db_type
    return connection.data_types[self.get_internal_type()] % data
  File "C:\Python27\lib\site-packages\django\db\__init__.py", line 36, in __getattr__
    return getattr(connections[DEFAULT_DB_ALIAS], item)
  File "C:\Python27\lib\site-packages\django\utils\functional.py", line 33, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "C:\Python27\lib\site-packages\django\db\backends\mysql\base.py", line 184, in data_types
    if self.features.supports_microsecond_precision:
  File "C:\Python27\lib\site-packages\django\utils\functional.py", line 33, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "C:\Python27\lib\site-packages\django\db\backends\mysql\features.py", line 53, in supports_microsecond_precision
    return self.connection.mysql_version >= (5, 6, 4) and Database.version_info >= (1, 2, 5)
  File "C:\Python27\lib\site-packages\django\utils\functional.py", line 33, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "C:\Python27\lib\site-packages\django\db\backends\mysql\base.py", line 359, in mysql_version
    with self.temporary_connection():
  File "C:\Python27\lib\contextlib.py", line 17, in __enter__
    return self.gen.next()
  File "C:\Python27\lib\site-packages\django\db\backends\base\base.py", line 564, in temporary_connection
    cursor = self.cursor()
  File "C:\Python27\lib\site-packages\django\db\backends\base\base.py", line 231, in cursor
    cursor = self.make_debug_cursor(self._cursor())
  File "C:\Python27\lib\site-packages\db_multitenant\db\backends\mysql\base.py", line 56, in _cursor
    cursor = super(DatabaseWrapper, self)._cursor()
  File "C:\Python27\lib\site-packages\django\db\backends\base\base.py", line 204, in _cursor
    self.ensure_connection()
  File "C:\Python27\lib\site-packages\django\db\backends\base\base.py", line 199, in ensure_connection
    self.connect()
  File "C:\Python27\lib\site-packages\django\db\backends\base\base.py", line 173, in connect
    self.init_connection_state()
  File "C:\Python27\lib\site-packages\django\db\backends\mysql\base.py", line 270, in init_connection_state
    with self.cursor() as cursor:
  File "C:\Python27\lib\site-packages\django\db\backends\base\base.py", line 231, in cursor
    cursor = self.make_debug_cursor(self._cursor())
  File "C:\Python27\lib\site-packages\db_multitenant\db\backends\mysql\base.py", line 65, in _cursor
    raise ImproperlyConfigured('dbname not set at cursor create time')
django.core.exceptions.ImproperlyConfigured: dbname not set at cursor create time

I guess it doesn't go to the middleware but I added the middleware as the first one in the middleware section. The following is the middleware section:


MIDDLEWARE_CLASSES = [
    'db_multitenant.middleware.MultiTenantMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

The following also is the database:

DATABASES = {
    
    'default': {
        #'ENGINE': 'django.db.backends.mysql',
        'ENGINE': 'db_multitenant.db.backends.mysql', 
        'NAME': 'tenant',
        'USER': 'tenantuser',
        'PASSWORD': 'tenantpwd',
        'HOST': 'localhost',
        'PORT': '3306',
    }
}

Please advise what would be the issue.. Thanks alot @stephane

@stephane
Copy link
Collaborator

How do you access your application (hostname)?

@Neamat
Copy link
Author

Neamat commented Apr 27, 2017 via email

@andyhasit
Copy link

andyhasit commented May 19, 2017

I have been tearing my hair out with this issue too... Adding print statements I can see that the DatabaseWrapper._cursor() method gets called several times at 'bootup', i.e. before any requests are sent, during which time the middleware is not even loaded (and so db_name is not set on thread_local, hence the exception).
Funnily enough DatabaseWrapper._cursor() doesn't seem to be called at all on requests, so I have just removed the exception raising and it seems to works fine (in debug on local, not tried on prod), which makes me wonder if there's any point it being there at all?

Edit: sorry, the above is incorrect. DatabaseWrapper._cursor() does get called in requests (that's what placing print statements when pulling an all-nighter will do to you!) but during 'bootup' it won't find the db_name on threadlocal because the middleware only kicks in and sets that when it receives requests.

The db queries which run at boot up prior to any requests are SET SQL_AUTO_IS_NULL = 0 and such. And it seems that these are only called on MYSQL and people have asked for them to be removed as they are aparently unecessary, and this may be the case on newer versions of django (see this post) which would explain why some people see this error, but others don't.

If my understanding is correct:

  • These queries will only go to the default database.
  • These queries are not actually required in the case of MYSQL, but other backends may require load time queries, in which case there is a problem with the overall approach we are using.

I'm wondering if we should raise the ImproperlyConfigured() exception in MultiTenantMiddleware.process_request() instead, which would resolve this issue. And replace the exception in DatabaseWrapper._cursor() with a printed warning because that will only happen if we haven't set in ENV, which infers we're using it from a manage.py command. But perhaps I'm missing something?

Using django 1.9.5

@jsep
Copy link

jsep commented Jun 8, 2017

I've solve this issue setting the TENANT_DATABASE_NAME var to my main db. Nevertheless I'm not sure either why is not getting the correct database name.

@dinesh829269
Copy link

dinesh829269 commented Jul 3, 2017

I am also getting the same issue
raise ImproperlyConfigured('dbname not set at cursor create time').
Is there any solution.

@andyhasit
Copy link

I created a fork which I'm using as a workaround: https://github.com/andyhasit/django-db-multitenant

@esclkm
Copy link

esclkm commented Jul 7, 2017

image
having same error on django 1.9

@stephane
Copy link
Collaborator

@andyhasit that means you want to fallback to the default DB when not set?

@andyhasit
Copy link

andyhasit commented Nov 19, 2017

@stephane Yes, and that's what my fork does.

@stephane
Copy link
Collaborator

@andyhasit could you propose a PR against master, please?

@rg2019
Copy link

rg2019 commented Jun 19, 2019

I solve this problem adding:

'db_multitenant.middleware.MultiTenantMiddleware',

To the first MIDDLEWARE, as say the documentation:

MIDDLEWARE

Don't forget add in settings.py at the end file :

from db_multitenant.utils import update_from_env
update_from_env(database_settings=DATABASES['default'],
    cache_settings=CACHES['default'])

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants