Compare commits

...

20 Commits

Author SHA1 Message Date
Frédéric Péters 7abe3cfb0b use old index retrieval code
This reverts changes to the index introspection done in
https://github.com/bernardopires/django-tenant-schemas/pull/385
2018-01-10 20:31:36 +01:00
Frédéric Péters d05d6603ff setup: also consider lightweight tags to create version number 2017-08-27 09:41:09 +02:00
Frédéric Péters 76f2058c33 Merge remote-tracking branch 'github/master' 2017-08-27 00:10:26 +02:00
Benjamin Dauvergne 35b4473e65 setup.py: use our own get_version() 2016-03-16 13:42:24 +01:00
Frédéric Péters 09175cc6d7 fix custom content type cache __get__ method (#10308) 2016-03-16 11:15:57 +01:00
Frédéric Péters e2d86034c2 import ContentType, ContentTypeManager from contenttypes module (#10308) 2016-03-16 11:15:41 +01:00
Benjamin Dauvergne e0c423e1f2 clear ContentType on each schema change (fixes #9891)
Also replace the cache dictionnary by a thread local variable to make it safe to
use multitenancy with threads.
2016-03-15 16:01:07 +01:00
Frédéric Péters d3ea3659e8 doc: update link of postgresql schema documentation to latest version 2016-03-15 15:17:07 +01:00
Frédéric Péters 26fd495cf6 Merge remote-tracking branch 'github/master' 2016-03-14 14:06:28 +01:00
Benjamin Dauvergne db84e52e8f Add 'debian/' from commit 'b502e23454b3124c9f7b6e25374cd9406074bbf9'
git-subtree-dir: debian
git-subtree-mainline: 8bd62ee84f
git-subtree-split: b502e23454
2016-02-06 14:52:50 +01:00
Benjamin Dauvergne 8bd62ee84f Merge branch 'wip/schema-aware-introspection' into eo-master
Conflicts:
	tenant_schemas/postgresql_backend/introspection.py
2015-04-24 11:08:21 +02:00
Benjamin Dauvergne b14f784a3a introspection: finish support for schema aware introspection
Query to pg_catalog tables are joined with pg_namespace.name =
self.connection.schema_name and queries to the information_schema schema get
the clause table_schema = self.connectin.schema_name.
2015-04-24 11:06:54 +02:00
Benjamin Dauvergne 553e580306 Merge branch 'wip/schema-aware-introspection' into eo-master 2015-04-24 10:34:51 +02:00
Benjamin Dauvergne 7312faa747 introspection: finish support for schema aware introspection
Query to pg_catalog tables are joined with pg_namespace.name =
self.connection.schema_name and queries to the information_schema schema get
the clause table_schema = self.connectin.schema_name.
2015-04-23 15:50:54 +02:00
Thomas NOËL 21ab3f2a36 Merge branch 'master' of https://github.com/bernardopires/django-tenant-schemas 2015-02-04 12:54:41 +01:00
Thomas NOËL c523006c61 Merge remote-tracking branch 'github/master'
Conflicts:
	tenant_schemas/postgresql_backend/base.py
2015-01-30 16:44:56 +01:00
Jérôme Schneider c430fde305 postgresql_backend: catch exception from django.db.utils and not from the backend 2014-10-20 11:06:50 +02:00
Benjamin Dauvergne db1875b90f Hide database errors when setting the search path
It's needed to allow ROLLBACK to be executed on the DB. It resolves
issue #191.
2014-10-20 11:06:50 +02:00
Benjamin Dauvergne b502e23454 Only build for python3 2014-10-16 15:33:30 +02:00
Jérôme Schneider 4a8fb48ea4 initial import 2014-10-14 11:46:35 +02:00
16 changed files with 127 additions and 37 deletions

5
debian/changelog vendored Normal file
View File

@ -0,0 +1,5 @@
django-tenant-schemas (1.4.8-1) unstable; urgency=low
* source package automatically created by stdeb 0.8.2
-- Jérôme Schneider <jschneider@entrouvert.com> Tue, 14 Oct 2014 11:39:16 +0200

1
debian/compat vendored Normal file
View File

@ -0,0 +1 @@
7

11
debian/control vendored Normal file
View File

@ -0,0 +1,11 @@
Source: django-tenant-schemas
Maintainer: Jérôme Schneider <jschneider@entrouvert.com>
Section: python
Priority: optional
Build-Depends: python-setuptools (>= 0.6b3), python-all (>= 2.6.6-3), debhelper (>= 7)
Standards-Version: 3.9.1
Package: python-django-tenant-schemas
Architecture: all
Depends: ${misc:Depends}, ${python:Depends}
Description: Tenant support for Django using PostgreSQL schemas.

2
debian/files vendored Normal file
View File

@ -0,0 +1,2 @@
python-django-tenant-schemas_1.4.8-10-ga5f144a-1_all.deb python optional
python3-django-tenant-schemas_1.4.8-10-ga5f144a-1_all.deb python optional

View File

@ -0,0 +1,7 @@
# Automatically added by dh_python2:
if which pycompile >/dev/null 2>&1; then
pycompile -p python-django-tenant-schemas
fi
# End automatically added section

View File

@ -0,0 +1,12 @@
# Automatically added by dh_python2:
if which pyclean >/dev/null 2>&1; then
pyclean -p python-django-tenant-schemas
else
dpkg -L python-django-tenant-schemas | grep \.py$ | while read file
do
rm -f "${file}"[co] >/dev/null
done
fi
# End automatically added section

View File

@ -0,0 +1,4 @@
python:Versions=2.7
python:Provides=python2.7-django-tenant-schemas
python:Depends=python (>= 2.7), python (<< 2.8), python:any (>= 2.6.6-7~), python-django, python-psycopg2
misc:Depends=

View File

@ -0,0 +1,7 @@
# Automatically added by dhpython:
if which py3compile >/dev/null 2>&1; then
py3compile -p python3-django-tenant-schemas
fi
# End automatically added section

View File

@ -0,0 +1,10 @@
# Automatically added by dhpython:
if which py3clean >/dev/null 2>&1; then
py3clean -p python3-django-tenant-schemas
else
dpkg -L python3-django-tenant-schemas | perl -ne 's,/([^/]*)\.py$,/__pycache__/\1.*, or next; unlink $_ or die $! foreach glob($_)'
find /usr/lib/python3/dist-packages/ -type d -name __pycache__ -empty -print0 | xargs --null --no-run-if-empty rmdir
fi
# End automatically added section

View File

@ -0,0 +1,2 @@
python3:Depends=python3-psycopg2, python3-django, python3:any (>= 3.3.2-2~)
misc:Depends=

7
debian/rules vendored Executable file
View File

@ -0,0 +1,7 @@
#!/usr/bin/make -f
# This file was automatically generated by stdeb 0.8.2 at
# Tue, 14 Oct 2014 11:39:16 +0200
%:
dh $@ --with python2

1
debian/source/format vendored Normal file
View File

@ -0,0 +1 @@
3.0 (quilt)

1
debian/source/options vendored Normal file
View File

@ -0,0 +1 @@
extend-diff-ignore="\.egg-info$"

View File

@ -1,17 +1,36 @@
#!/usr/bin/env python
import os
import subprocess
from os.path import exists
from version import get_git_version
try:
from setuptools import setup
except ImportError:
from distutils.core import setup
def get_version():
'''Use the VERSION, if absent generates a version with git describe, if not
tag exists, take 0.0.0- and add the length of the commit log.
'''
if os.path.exists('VERSION'):
with open('VERSION', 'r') as v:
return v.read()
if os.path.exists('.git'):
p = subprocess.Popen(['git', 'describe', '--dirty', '--tags', '--match=v*'], stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
result = p.communicate()[0]
if p.returncode == 0:
result = result.split()[0][1:]
else:
result = '0.0.0-%s' % len(subprocess.check_output(
['git', 'rev-list', 'HEAD']).splitlines())
return result.replace('-', '.').replace('.g', '+g')
return '0.0.0'
setup(
name='django-tenant-schemas',
version=get_git_version(),
version=get_version(),
author='Bernardo Pires Carneiro',
author_email='carneiro.be@gmail.com',
packages=[

View File

@ -1,9 +1,11 @@
import re
import warnings
import threading
import psycopg2
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured, ValidationError
from django.contrib.contenttypes.models import ContentType, ContentTypeManager
import django.db.utils
from tenant_schemas.utils import get_public_schema_name, get_limit_set_calls
@ -72,6 +74,7 @@ class DatabaseWrapper(original_backend.DatabaseWrapper):
self.include_public_schema = include_public
self.set_settings_schema(self.schema_name)
self.search_path_set = False
ContentType.objects.clear_cache()
def set_schema(self, schema_name, include_public=True):
"""
@ -83,6 +86,7 @@ class DatabaseWrapper(original_backend.DatabaseWrapper):
self.include_public_schema = include_public
self.set_settings_schema(schema_name)
self.search_path_set = False
ContentType.objects.clear_cache()
def set_schema_to_public(self):
"""
@ -92,6 +96,7 @@ class DatabaseWrapper(original_backend.DatabaseWrapper):
self.schema_name = get_public_schema_name()
self.set_settings_schema(self.schema_name)
self.search_path_set = False
ContentType.objects.clear_cache()
def set_settings_schema(self, schema_name):
self.settings_dict['SCHEMA'] = schema_name
@ -170,3 +175,13 @@ class FakeTenant:
"""
def __init__(self, schema_name):
self.schema_name = schema_name
# Make the ContentType cache tenant and thread safe
ContentTypeManager._thread_local_cache = threading.local()
class ContentTypeCacheDescriptor(object):
def __get__(self, obj, owner):
if not hasattr(owner._thread_local_cache, '_cache'):
owner._thread_local_cache._cache = {}
return owner._thread_local_cache._cache
ContentTypeManager._cache = ContentTypeCacheDescriptor()

View File

@ -135,35 +135,24 @@ class DatabaseSchemaIntrospection(BaseDatabaseIntrospection):
_get_index_constraints_query = """
SELECT
indexname, array_agg(attname), indisunique, indisprimary,
array_agg(ordering), amname, exprdef
FROM (
SELECT
c2.relname as indexname, idx.*, attr.attname, am.amname,
CASE
WHEN idx.indexprs IS NOT NULL THEN
pg_get_indexdef(idx.indexrelid)
END AS exprdef,
CASE am.amname
WHEN 'btree' THEN
CASE (option & 1)
WHEN 1 THEN 'DESC' ELSE 'ASC'
END
END as ordering
FROM (
SELECT
*, unnest(i.indkey) as key, unnest(i.indoption) as option
FROM pg_index i
) idx
LEFT JOIN pg_class c ON idx.indrelid = c.oid
LEFT JOIN pg_class c2 ON idx.indexrelid = c2.oid
LEFT JOIN pg_am am ON c2.relam = am.oid
LEFT JOIN pg_attribute attr ON attr.attrelid = c.oid AND attr.attnum = idx.key
LEFT JOIN pg_namespace n ON c.relnamespace = n.oid
WHERE c.relname = %(table)s
AND n.nspname = %(schema)s
) s2
GROUP BY indexname, indisunique, indisprimary, amname, exprdef;
c2.relname,
ARRAY(
SELECT (
SELECT attname
FROM pg_catalog.pg_attribute
WHERE attnum = i AND attrelid = c.oid
)
FROM unnest(idx.indkey) i
),
idx.indisunique,
idx.indisprimary
FROM pg_catalog.pg_class c, pg_catalog.pg_class c2,
pg_catalog.pg_index idx, pg_catalog.pg_namespace n
WHERE c.oid = idx.indrelid
AND idx.indexrelid = c2.oid
AND n.oid = c.relnamespace
AND c.relname = %(table)s
AND n.nspname = %(schema)s
"""
def get_field_type(self, data_type, description):
@ -291,17 +280,14 @@ class DatabaseSchemaIntrospection(BaseDatabaseIntrospection):
'table': table_name,
})
for index, columns, unique, primary, orders, type_, definition in cursor.fetchall():
for index, columns, unique, primary in cursor.fetchall():
if index not in constraints:
constraints[index] = {
"columns": columns if columns != [None] else [],
"orders": orders if orders != [None] else [],
"columns": list(columns),
"primary_key": primary,
"unique": unique,
"foreign_key": None,
"check": False,
"index": True,
"type": type_,
"definition": definition,
}
return constraints