Commit 4957c6d4 authored by Nicola Spanti's avatar Nicola Spanti
Browse files

feat: drop MySQL and SQLServer support

see https://forge.extranet.logilab.fr/cubicweb/cubicweb/-/jobs/269972
for !229

--HG--
branch : 3.29
parent ab75487c3672
Pipeline #68205 failed with stages
in 33 minutes and 57 seconds
......@@ -1298,7 +1298,7 @@ def register_stored_procedures():
class GROUP_CONCAT(CONCAT_STRINGS):
supported_backends = ('mysql', 'postgres', 'sqlite',)
supported_backends = ('postgres', 'sqlite',)
register_function(GROUP_CONCAT)
......@@ -1315,7 +1315,7 @@ def register_stored_procedures():
class TEXT_LIMIT_SIZE(LIMIT_SIZE):
supported_backends = ('mysql', 'postgres', 'sqlite',)
supported_backends = ('postgres', 'sqlite',)
minargs = maxargs = 2
register_function(TEXT_LIMIT_SIZE)
......
......@@ -727,21 +727,6 @@ class PostgresTestDataBaseHandler(TestDataBaseHandler):
self.dbcnx.commit()
# sqlserver2005 test database handling #########################################
class SQLServerTestDataBaseHandler(TestDataBaseHandler):
DRIVER = 'sqlserver'
# XXX complete me
def init_test_database(self):
"""initialize a fresh sqlserver databse used for testing purpose"""
if self.config.init_repository:
from cubicweb.server import init_repository
init_repository(self.config, interactive=False, drop=True,
init_config=self.init_config)
# sqlite test database handling ################################################
class SQLiteTestDataBaseHandler(TestDataBaseHandler):
......@@ -824,12 +809,12 @@ def register_handler(handlerkls, overwrite=False):
"(existing handler class is %r)"
raise ValueError(msg % (handlerkls.DRIVER, HANDLERS[handlerkls.DRIVER]))
register_handler(PostgresTestDataBaseHandler)
register_handler(SQLiteTestDataBaseHandler)
register_handler(SQLServerTestDataBaseHandler)
class HCache(object):
class HCache():
"""Handler cache object: store database handler for a given configuration.
We only keep one repo in cache to prevent too much objects to stay alive
......@@ -847,13 +832,13 @@ class HCache(object):
def get(self, config):
if config is self.config:
return self.handler
else:
return None
return None
def set(self, config, handler):
self.config = config
self.handler = handler
HCACHE = HCache()
# XXX a class method on Test ?
......
......@@ -1004,8 +1004,7 @@ class Entity(AppObject):
for term, order in sort_terms:
# Add a relation for sorting only if it is not only retrieved
# (e.g. modification_date) instead of adding another variable
# for sorting. This should not be problematic, but it is with
# sqlserver, see ticket #694445.
# for sorting. This should not be problematic.
rel = sorting_relations.get(term)
if rel is None:
mdvar = select.make_variable()
......
......@@ -55,7 +55,7 @@ For instance they can serve the following purposes:
It is functionally equivalent to a `database trigger`_, except that database
triggers definition languages are not standardized, hence not portable (for
instance, PL/SQL works with Oracle and PostgreSQL but not SqlServer nor Sqlite).
instance, PL/SQL works with Oracle and PostgreSQL but not Sqlite).
.. _`database trigger`: http://en.wikipedia.org/wiki/Database_trigger
......
......@@ -265,7 +265,7 @@ class NativeSQLSource(SQLAdapterMixIn, AbstractSource):
{'type': 'string',
'default': 'postgres',
# XXX use choice type
'help': 'database driver (postgres, sqlite, sqlserver2005)',
'help': 'database driver (postgres, sqlite)',
'group': 'native-source', 'level': 0,
}),
('db-host',
......@@ -725,7 +725,7 @@ class NativeSQLSource(SQLAdapterMixIn, AbstractSource):
if cls.__name__ == 'IntegrityError'):
# need string comparison because of various backends
for arg in ex.args:
# postgres, sqlserver
# postgres
mo = re.search("unique_[a-z0-9]{32}", arg)
if mo is not None:
raise UniqueTogetherError(cnx, cstrname=mo.group(0))
......
......@@ -39,7 +39,7 @@ _orig_check_permissions = ExecutionPlan._check_permissions
# add a dumb registered procedure
class stockproc(FunctionDescr):
supported_backends = ('postgres', 'sqlite', 'mysql')
supported_backends = ('postgres', 'sqlite')
try:
register_function(stockproc)
......@@ -1834,192 +1834,6 @@ ORDER BY 1'''),
self._check('Any 5 % 2', '''SELECT (5 % 2)''')
class SqlServer2005SQLGeneratorTC(PostgresSQLGeneratorTC):
backend = 'sqlserver2005'
def _norm_sql(self, sql):
return sql.strip().replace(' SUBSTR', ' SUBSTRING').replace(' || ', ' + ').replace(' ILIKE ', ' LIKE ')
def test_has_text(self):
for rql, sql in HAS_TEXT_LG_INDEXER:
with self.subTest(rql=rql):
self._check(rql, sql)
def test_regexp(self):
self.skipTest('regexp-based pattern matching not implemented in sqlserver')
def test_or_having_fake_terms_base(self):
self._check('Any X WHERE X is CWUser, X creation_date D HAVING YEAR(D) = "2010" OR D = NULL',
'''SELECT _X.cw_eid
FROM cw_CWUser AS _X
WHERE ((DATEPART(YEAR, _X.cw_creation_date)=2010) OR (_X.cw_creation_date IS NULL))''')
def test_date_extraction(self):
self._check("Any MONTH(D) WHERE P is Personne, P creation_date D",
'''SELECT DATEPART(MONTH, _P.cw_creation_date)
FROM cw_Personne AS _P''')
def test_weekday_extraction(self):
self._check("Any WEEKDAY(D) WHERE P is Personne, P creation_date D",
'''SELECT DATEPART(WEEKDAY, _P.cw_creation_date)
FROM cw_Personne AS _P''')
def test_basic_parse(self):
for rql, sql in BASIC:# + BASIC_WITH_LIMIT):
with self.subTest(rql=rql):
self._check(rql, sql)
def test_advanced_parse(self):
for rql, sql in ADVANCED:# + ADVANCED_WITH_LIMIT_OR_ORDERBY):
with self.subTest(rql=rql):
self._check(rql, sql)
def test_limit_offset(self):
WITH_LIMIT = [
("Personne P LIMIT 20 OFFSET 10",
'''WITH orderedrows AS (
SELECT
_L01
, ROW_NUMBER() OVER (ORDER BY _L01) AS __RowNumber
FROM (
SELECT _P.cw_eid AS _L01 FROM cw_Personne AS _P
) AS _SQ1 )
SELECT
_L01
FROM orderedrows WHERE
__RowNumber <= 30 AND __RowNumber > 10
'''),
('Any COUNT(S),CS GROUPBY CS ORDERBY 1 DESC LIMIT 10 WHERE S is Affaire, C is Societe, S concerne C, C nom CS, (EXISTS(S owned_by 1)) OR (EXISTS(S documented_by N, N title "published"))',
'''WITH orderedrows AS (
SELECT
_L01, _L02
, ROW_NUMBER() OVER (ORDER BY _L01 DESC) AS __RowNumber
FROM (
SELECT COUNT(rel_concerne0.eid_from) AS _L01, _C.cw_nom AS _L02 FROM concerne_relation AS rel_concerne0, cw_Societe AS _C
WHERE rel_concerne0.eid_to=_C.cw_eid AND ((EXISTS(SELECT 1 FROM owned_by_relation AS rel_owned_by1 WHERE rel_concerne0.eid_from=rel_owned_by1.eid_from AND rel_owned_by1.eid_to=1)) OR (EXISTS(SELECT 1 FROM cw_Card AS _N, documented_by_relation AS rel_documented_by2 WHERE rel_concerne0.eid_from=rel_documented_by2.eid_from AND rel_documented_by2.eid_to=_N.cw_eid AND _N.cw_title=published)))
GROUP BY _C.cw_nom
) AS _SQ1 )
SELECT
_L01, _L02
FROM orderedrows WHERE
__RowNumber <= 10
'''),
('DISTINCT Any MAX(X)+MIN(LENGTH(D)), N GROUPBY N ORDERBY 2, DF WHERE X data_name N, X data D, X data_format DF;',
'''SELECT T1.C0,T1.C1 FROM (SELECT DISTINCT (MAX(_X.cw_eid) + MIN(LENGTH(_X.cw_data))) AS C0, _X.cw_data_name AS C1, _X.cw_data_format AS C2
FROM cw_File AS _X
GROUP BY _X.cw_data_name,_X.cw_data_format) AS T1
ORDER BY T1.C1,T1.C2
'''),
('DISTINCT Any X ORDERBY Y WHERE B bookmarked_by X, X login Y',
'''SELECT T1.C0 FROM (SELECT DISTINCT _X.cw_eid AS C0, _X.cw_login AS C1
FROM bookmarked_by_relation AS rel_bookmarked_by0, cw_CWUser AS _X
WHERE rel_bookmarked_by0.eid_to=_X.cw_eid) AS T1
ORDER BY T1.C1
'''),
('DISTINCT Any X ORDERBY SN WHERE X in_state S, S name SN',
'''SELECT T1.C0 FROM (SELECT DISTINCT _X.cw_eid AS C0, _S.cw_name AS C1
FROM cw_Affaire AS _X, cw_State AS _S
WHERE _X.cw_in_state=_S.cw_eid
UNION
SELECT DISTINCT _X.cw_eid AS C0, _S.cw_name AS C1
FROM cw_CWUser AS _X, cw_State AS _S
WHERE _X.cw_in_state=_S.cw_eid
UNION
SELECT DISTINCT _X.cw_eid AS C0, _S.cw_name AS C1
FROM cw_Note AS _X, cw_State AS _S
WHERE _X.cw_in_state=_S.cw_eid) AS T1
ORDER BY T1.C1'''),
('Any O,AA,AB,AC ORDERBY AC DESC '
'WHERE NOT S use_email O, S eid 1, O is EmailAddress, O address AA, O alias AB, O modification_date AC, '
'EXISTS(A use_email O, EXISTS(A identity B, NOT B in_group D, D name "guests", D is CWGroup), A is CWUser), B eid 2',
'''
SELECT _O.cw_eid, _O.cw_address, _O.cw_alias, _O.cw_modification_date
FROM cw_EmailAddress AS _O
WHERE NOT (EXISTS(SELECT 1 FROM use_email_relation AS rel_use_email0 WHERE rel_use_email0.eid_from=1 AND rel_use_email0.eid_to=_O.cw_eid)) AND EXISTS(SELECT 1 FROM use_email_relation AS rel_use_email1 WHERE rel_use_email1.eid_to=_O.cw_eid AND EXISTS(SELECT 1 FROM cw_CWGroup AS _D WHERE rel_use_email1.eid_from=2 AND NOT (EXISTS(SELECT 1 FROM in_group_relation AS rel_in_group2 WHERE rel_in_group2.eid_from=2 AND rel_in_group2.eid_to=_D.cw_eid)) AND _D.cw_name=guests))
ORDER BY 4 DESC'''),
("Any P ORDERBY N LIMIT 1 WHERE P is Personne, P travaille S, S eid %(eid)s, P nom N, P nom %(text)s",
'''WITH orderedrows AS (
SELECT
_L01
, ROW_NUMBER() OVER (ORDER BY _L01) AS __RowNumber
FROM (
SELECT _P.cw_eid AS _L01 FROM cw_Personne AS _P, travaille_relation AS rel_travaille0
WHERE rel_travaille0.eid_from=_P.cw_eid AND rel_travaille0.eid_to=12345 AND _P.cw_nom=hip hop momo
) AS _SQ1 )
SELECT
_L01
FROM orderedrows WHERE
__RowNumber <= 1'''),
("Any P ORDERBY N LIMIT 1 WHERE P is Personne, P nom N",
'''WITH orderedrows AS (
SELECT
_L01
, ROW_NUMBER() OVER (ORDER BY _L01) AS __RowNumber
FROM (
SELECT _P.cw_eid AS _L01 FROM cw_Personne AS _P
) AS _SQ1 )
SELECT
_L01
FROM orderedrows WHERE
__RowNumber <= 1
'''),
("Any PN, N, P ORDERBY N LIMIT 1 WHERE P is Personne, P nom N, P prenom PN",
'''WITH orderedrows AS (
SELECT
_L01, _L02, _L03
, ROW_NUMBER() OVER (ORDER BY _L02) AS __RowNumber
FROM (
SELECT _P.cw_prenom AS _L01, _P.cw_nom AS _L02, _P.cw_eid AS _L03 FROM cw_Personne AS _P
) AS _SQ1 )
SELECT
_L01, _L02, _L03
FROM orderedrows WHERE
__RowNumber <= 1
'''),
]
for rql, sql in WITH_LIMIT:# + ADVANCED_WITH_LIMIT_OR_ORDERBY):
with self.subTest(rql=rql):
self._check(rql, sql)
def test_cast(self):
self._check("Any CAST(String, P) WHERE P is Personne",
'''SELECT CAST(_P.cw_eid AS nvarchar(max))
FROM cw_Personne AS _P''')
def test_groupby_orderby_insertion_dont_modify_intention(self):
self._check('Any YEAR(XECT)*100+MONTH(XECT), COUNT(X),SUM(XCE),AVG(XSCT-XECT) '
'GROUPBY YEAR(XECT),MONTH(XECT) ORDERBY 1 '
'WHERE X creation_date XSCT, X modification_date XECT, '
'X ordernum XCE, X is CWAttribute',
'''SELECT ((DATEPART(YEAR, _X.cw_modification_date) * 100) + DATEPART(MONTH, _X.cw_modification_date)), COUNT(_X.cw_eid), SUM(_X.cw_ordernum), AVG((_X.cw_creation_date - _X.cw_modification_date))
FROM cw_CWAttribute AS _X
GROUP BY DATEPART(YEAR, _X.cw_modification_date),DATEPART(MONTH, _X.cw_modification_date)
ORDER BY 1''')
def test_today(self):
for rql, sql in [
("Any X WHERE X creation_date TODAY, X is Affaire",
'''SELECT _X.cw_eid
FROM cw_Affaire AS _X
WHERE DATE(_X.cw_creation_date)=%s''' % self.dbhelper.sql_current_date()),
("Personne P where not P datenaiss TODAY",
'''SELECT _P.cw_eid
FROM cw_Personne AS _P
WHERE NOT (DATE(_P.cw_datenaiss)=%s)''' % self.dbhelper.sql_current_date()),
]:
with self.subTest(rql=rql):
self._check(rql, sql)
class SqliteSQLGeneratorTC(PostgresSQLGeneratorTC):
backend = 'sqlite'
......@@ -2189,144 +2003,7 @@ WHERE NOT (DATE(_P.cw_datenaiss)=CURRENT_DATE)'''),
self._check(rql, sql)
class MySQLGenerator(PostgresSQLGeneratorTC):
backend = 'mysql'
def _norm_sql(self, sql):
sql = sql.strip().replace(' ILIKE ', ' LIKE ')
newsql = []
latest = None
for line in sql.splitlines(False):
firstword = line.split(None, 1)[0]
if firstword == 'WHERE' and latest == 'SELECT':
newsql.append('FROM (SELECT 1) AS _T')
newsql.append(line)
latest = firstword
return '\n'.join(newsql)
def test_date_extraction(self):
self._check("Any MONTH(D) WHERE P is Personne, P creation_date D",
'''SELECT EXTRACT(MONTH from _P.cw_creation_date)
FROM cw_Personne AS _P''')
def test_weekday_extraction(self):
self._check("Any WEEKDAY(D) WHERE P is Personne, P creation_date D",
'''SELECT DAYOFWEEK(_P.cw_creation_date)
FROM cw_Personne AS _P''')
def test_cast(self):
self._check("Any CAST(String, P) WHERE P is Personne",
'''SELECT CAST(_P.cw_eid AS mediumtext)
FROM cw_Personne AS _P''')
def test_regexp(self):
self._check("Any X WHERE X login REGEXP '[0-9].*'",
'''SELECT _X.cw_eid
FROM cw_CWUser AS _X
WHERE _X.cw_login REGEXP [0-9].*
''')
def test_from_clause_needed(self):
queries = [("Any 1 WHERE EXISTS(T is CWGroup, T name 'managers')",
'''SELECT 1
FROM (SELECT 1) AS _T
WHERE EXISTS(SELECT 1 FROM cw_CWGroup AS _T WHERE _T.cw_name=managers)'''),
('Any X,Y WHERE NOT X created_by Y, X eid 5, Y eid 6',
'''SELECT 5, 6
FROM (SELECT 1) AS _T
WHERE NOT (EXISTS(SELECT 1 FROM created_by_relation AS rel_created_by0 WHERE rel_created_by0.eid_from=5 AND rel_created_by0.eid_to=6))'''),
]
for rql, sql in queries:
with self.subTest(rql=rql):
self._check(rql, sql)
def test_has_text(self):
queries = [
('Any X WHERE X has_text "toto tata"',
"""SELECT appears0.uid
FROM appears AS appears0
WHERE MATCH (appears0.words) AGAINST ('toto tata' IN BOOLEAN MODE)"""),
('Personne X WHERE X has_text "toto tata"',
"""SELECT _X.cw_eid
FROM appears AS appears0, cw_Personne AS _X
WHERE MATCH (appears0.words) AGAINST ('toto tata' IN BOOLEAN MODE) AND appears0.uid=_X.cw_eid"""),
('Personne X WHERE X has_text %(text)s',
"""SELECT _X.cw_eid
FROM appears AS appears0, cw_Personne AS _X
WHERE MATCH (appears0.words) AGAINST ('hip hop momo' IN BOOLEAN MODE) AND appears0.uid=_X.cw_eid"""),
('Any X WHERE X has_text "toto tata", X name "tutu", X is IN (Basket,Folder)',
"""SELECT _X.cw_eid
FROM appears AS appears0, cw_Basket AS _X
WHERE MATCH (appears0.words) AGAINST ('toto tata' IN BOOLEAN MODE) AND appears0.uid=_X.cw_eid AND _X.cw_name=tutu
UNION ALL
SELECT _X.cw_eid
FROM appears AS appears0, cw_Folder AS _X
WHERE MATCH (appears0.words) AGAINST ('toto tata' IN BOOLEAN MODE) AND appears0.uid=_X.cw_eid AND _X.cw_name=tutu
""")
]
for rql, sql in queries:
with self.subTest(rql=rql):
self._check(rql, sql)
def test_ambigous_exists_no_from_clause(self):
self._check('Any COUNT(U) WHERE U eid 1, EXISTS (P owned_by U, P is IN (Note, Affaire))',
'''SELECT COUNT(1)
FROM (SELECT 1) AS _T
WHERE EXISTS(SELECT 1 FROM cw_Affaire AS _P, owned_by_relation AS rel_owned_by0 WHERE rel_owned_by0.eid_from=_P.cw_eid AND rel_owned_by0.eid_to=1 UNION SELECT 1 FROM cw_Note AS _P, owned_by_relation AS rel_owned_by1 WHERE rel_owned_by1.eid_from=_P.cw_eid AND rel_owned_by1.eid_to=1)''')
def test_groupby_multiple_outerjoins(self):
self._check('Any A,U,P,group_concat(TN) GROUPBY A,U,P WHERE A is Affaire, A concerne N, N todo_by U?, T? tags A, T name TN, A todo_by P?',
'''SELECT _A.cw_eid, rel_todo_by1.eid_to, rel_todo_by3.eid_to, GROUP_CONCAT(_T.cw_name)
FROM concerne_relation AS rel_concerne0, cw_Affaire AS _A LEFT OUTER JOIN tags_relation AS rel_tags2 ON (rel_tags2.eid_to=_A.cw_eid) LEFT OUTER JOIN cw_Tag AS _T ON (rel_tags2.eid_from=_T.cw_eid) LEFT OUTER JOIN todo_by_relation AS rel_todo_by3 ON (rel_todo_by3.eid_from=_A.cw_eid), cw_Note AS _N LEFT OUTER JOIN todo_by_relation AS rel_todo_by1 ON (rel_todo_by1.eid_from=_N.cw_eid)
WHERE rel_concerne0.eid_from=_A.cw_eid AND rel_concerne0.eid_to=_N.cw_eid
GROUP BY _A.cw_eid,rel_todo_by1.eid_to,rel_todo_by3.eid_to''')
def test_substring(self):
self._check("Any SUBSTRING(N, 1, 1) WHERE P nom N, P is Personne",
'''SELECT SUBSTRING(_P.cw_nom, 1, 1)
FROM cw_Personne AS _P''')
def test_or_having_fake_terms_base(self):
self._check('Any X WHERE X is CWUser, X creation_date D HAVING YEAR(D) = "2010" OR D = NULL',
'''SELECT _X.cw_eid
FROM cw_CWUser AS _X
WHERE ((EXTRACT(YEAR from _X.cw_creation_date)=2010) OR (_X.cw_creation_date IS NULL))''')
def test_not_no_where(self):
self._check('Any 1 WHERE NOT X in_group G, X is CWUser',
'''SELECT 1
FROM (SELECT 1) AS _T
WHERE NOT (EXISTS(SELECT 1 FROM in_group_relation AS rel_in_group0))''')
def test_groupby_orderby_insertion_dont_modify_intention(self):
self._check('Any YEAR(XECT)*100+MONTH(XECT), COUNT(X),SUM(XCE),AVG(XSCT-XECT) '
'GROUPBY YEAR(XECT),MONTH(XECT) ORDERBY 1 '
'WHERE X creation_date XSCT, X modification_date XECT, '
'X ordernum XCE, X is CWAttribute',
'''SELECT ((EXTRACT(YEAR from _X.cw_modification_date) * 100) + EXTRACT(MONTH from _X.cw_modification_date)), COUNT(_X.cw_eid), SUM(_X.cw_ordernum), AVG((_X.cw_creation_date - _X.cw_modification_date))
FROM cw_CWAttribute AS _X
GROUP BY EXTRACT(YEAR from _X.cw_modification_date),EXTRACT(MONTH from _X.cw_modification_date)
ORDER BY 1'''),
def test_today(self):
for rql, sql in [
("Any X WHERE X creation_date TODAY, X is Affaire",
'''SELECT _X.cw_eid
FROM cw_Affaire AS _X
WHERE DATE(_X.cw_creation_date)=CURRENT_DATE'''),
("Personne P where not P datenaiss TODAY",
'''SELECT _P.cw_eid
FROM cw_Personne AS _P
WHERE NOT (DATE(_P.cw_datenaiss)=CURRENT_DATE)'''),
]:
with self.subTest(rql=rql):
self._check(rql, sql)
class removeUnsusedSolutionsTC(unittest.TestCase):
class RemoveUnsusedSolutionsTC(unittest.TestCase):
def test_invariant_not_varying(self):
rqlst = mock_object(defined_vars={})
rqlst.defined_vars['A'] = mock_object(scope=rqlst, stinfo={}, _q_invariant=True)
......
......@@ -67,7 +67,7 @@ password=admin
[system]
# database driver (postgres, sqlite, sqlserver2005)
# database driver (postgres, sqlite)
db-driver=postgres
# database host
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment