summaryrefslogtreecommitdiff
path: root/test/sql/test_functions.py
diff options
context:
space:
mode:
authorAdrien Berchet <adrien.berchet@gmail.com>2019-04-15 13:59:18 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2019-04-29 17:24:32 -0400
commita10a4ea1248902349d789de7f5470bb8e437a584 (patch)
tree536acae15894ae8f60ac2aedd784e37575ccba39 /test/sql/test_functions.py
parent64865304051b2af1ee4f90c6bf5e93378d4f302c (diff)
downloadsqlalchemy-a10a4ea1248902349d789de7f5470bb8e437a584.tar.gz
Add case insensitivity feature to GenericFunction.
The :class:`.GenericFunction` namespace is being migrated so that function names are looked up in a case-insensitive manner, as SQL functions do not collide on case sensitive differences nor is this something which would occur with user-defined functions or stored procedures. Lookups for functions declared with :class:`.GenericFunction` now use a case insensitive scheme, however a deprecation case is supported which allows two or more :class:`.GenericFunction` objects with the same name of different cases to exist, which will cause case sensitive lookups to occur for that particular name, while emitting a warning at function registration time. Thanks to Adrien Berchet for a lot of work on this complicated feature. Fixes: #4569 Closes: #4570 Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/4570 Pull-request-sha: 37d4f3322b6bace88c99b959cb1916dbbc57610e Change-Id: Ief07c6eb55bf398f6aad85b60ef13ee6d1173109
Diffstat (limited to 'test/sql/test_functions.py')
-rw-r--r--test/sql/test_functions.py58
1 files changed, 55 insertions, 3 deletions
diff --git a/test/sql/test_functions.py b/test/sql/test_functions.py
index 5fb4bc2e4..b03b156bc 100644
--- a/test/sql/test_functions.py
+++ b/test/sql/test_functions.py
@@ -1,3 +1,4 @@
+from copy import deepcopy
import datetime
import decimal
@@ -39,6 +40,7 @@ from sqlalchemy.testing import engines
from sqlalchemy.testing import eq_
from sqlalchemy.testing import fixtures
from sqlalchemy.testing import is_
+from sqlalchemy.testing.assertions import expect_warnings
from sqlalchemy.testing.engines import all_dialects
@@ -53,8 +55,14 @@ table1 = table(
class CompileTest(fixtures.TestBase, AssertsCompiledSQL):
__dialect__ = "default"
- def tear_down(self):
- functions._registry.clear()
+ def setup(self):
+ self._registry = deepcopy(functions._registry)
+ self._case_sensitive_registry = deepcopy(
+ functions._case_sensitive_registry)
+
+ def teardown(self):
+ functions._registry = self._registry
+ functions._case_sensitive_registry = self._case_sensitive_registry
def test_compile(self):
for dialect in all_dialects(exclude=("sybase",)):
@@ -87,6 +95,9 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL):
dialect=dialect,
)
+ functions._registry['_default'].pop('fake_func')
+ functions._case_sensitive_registry['_default'].pop('fake_func')
+
def test_use_labels(self):
self.assert_compile(
select([func.foo()], use_labels=True), "SELECT foo() AS foo_1"
@@ -100,7 +111,7 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL):
def test_uppercase(self):
# for now, we need to keep case insensitivity
- self.assert_compile(func.NOW(), "NOW()")
+ self.assert_compile(func.UNREGISTERED_FN(), "UNREGISTERED_FN()")
def test_uppercase_packages(self):
# for now, we need to keep case insensitivity
@@ -219,6 +230,37 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL):
assert isinstance(func.myfunc().type, DateTime)
+ def test_case_sensitive(self):
+ class MYFUNC(GenericFunction):
+ type = DateTime
+
+ assert isinstance(func.MYFUNC().type, DateTime)
+ assert isinstance(func.MyFunc().type, DateTime)
+ assert isinstance(func.mYfUnC().type, DateTime)
+ assert isinstance(func.myfunc().type, DateTime)
+
+ def test_replace_function(self):
+ class replaceable_func(GenericFunction):
+ type = Integer
+ identifier = 'replaceable_func'
+
+ assert isinstance(func.Replaceable_Func().type, Integer)
+ assert isinstance(func.RePlAcEaBlE_fUnC().type, Integer)
+ assert isinstance(func.replaceable_func().type, Integer)
+
+ with expect_warnings(
+ "The GenericFunction 'replaceable_func' is already registered and "
+ "is going to be overriden.",
+ regex=False
+ ):
+ class replaceable_func_override(GenericFunction):
+ type = DateTime
+ identifier = 'replaceable_func'
+
+ assert isinstance(func.Replaceable_Func().type, DateTime)
+ assert isinstance(func.RePlAcEaBlE_fUnC().type, DateTime)
+ assert isinstance(func.replaceable_func().type, DateTime)
+
def test_custom_w_custom_name(self):
class myfunc(GenericFunction):
name = "notmyfunc"
@@ -267,9 +309,19 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL):
type = Integer
identifier = "buf3"
+ class GeoBufferFour(GenericFunction):
+ type = Integer
+ name = "BufferFour"
+ identifier = "Buf4"
+
self.assert_compile(func.geo.buf1(), "BufferOne()")
self.assert_compile(func.buf2(), "BufferTwo()")
self.assert_compile(func.buf3(), "BufferThree()")
+ self.assert_compile(func.Buf4(), "BufferFour()")
+ self.assert_compile(func.BuF4(), "BufferFour()")
+ self.assert_compile(func.bUf4(), "BufferFour()")
+ self.assert_compile(func.bUf4_(), "BufferFour()")
+ self.assert_compile(func.buf4(), "BufferFour()")
def test_custom_args(self):
class myfunc(GenericFunction):