diff --git a/pylegend/core/tds/tds_frame.py b/pylegend/core/tds/tds_frame.py index 0dfafb38..6f9f4f4a 100644 --- a/pylegend/core/tds/tds_frame.py +++ b/pylegend/core/tds/tds_frame.py @@ -27,6 +27,8 @@ postgres_ext = 'pylegend.extensions.database.vendors.postgres.postgres_sql_to_string' importlib.import_module(postgres_ext) +mysql_ext = 'pylegend.extensions.database.vendors.mysql.mysql_sql_to_string' +importlib.import_module(mysql_ext) __all__: PyLegendSequence[str] = [ "PyLegendTdsFrame", diff --git a/pylegend/extensions/database/vendors/mysql/__init__.py b/pylegend/extensions/database/vendors/mysql/__init__.py new file mode 100644 index 00000000..5757135b --- /dev/null +++ b/pylegend/extensions/database/vendors/mysql/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2023 Goldman Sachs +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/pylegend/extensions/database/vendors/mysql/mysql_sql_to_string.py b/pylegend/extensions/database/vendors/mysql/mysql_sql_to_string.py new file mode 100644 index 00000000..067536fb --- /dev/null +++ b/pylegend/extensions/database/vendors/mysql/mysql_sql_to_string.py @@ -0,0 +1,46 @@ +# Copyright 2023 Goldman Sachs +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from pylegend.core.databse.sql_to_string import ( + SqlToStringGenerator, + SqlToStringDbExtension, +) +from pylegend._typing import PyLegendSequence + + +__all__: PyLegendSequence[str] = [ + "MySQLSqlToStringGenerator" +] + + +class MySQLSqlToStringDbExtension(SqlToStringDbExtension): + + @classmethod + def quote_character(cls) -> str: + return "`" + + +class MySQLSqlToStringGenerator(SqlToStringGenerator): + __sql_to_string_db_extension: SqlToStringDbExtension = MySQLSqlToStringDbExtension() + + @classmethod + def database_type(cls) -> str: + return "MySQL" + + @classmethod + def create_sql_generator(cls) -> SqlToStringGenerator: + return MySQLSqlToStringGenerator() + + def get_db_extension(self) -> SqlToStringDbExtension: + return self.__sql_to_string_db_extension diff --git a/pyproject.toml b/pyproject.toml index c9ecad0e..61309d44 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,6 +34,8 @@ mockito = ">=1.0.0" testcontainers = ">=3.0.0" sqlalchemy = ">=2.0.0" pg8000 = ">=1.0.0" +pymysql = ">=1.0.0" +cryptography = ">=40.0.0" [build-system] requires = ["poetry-core"] diff --git a/tests/core/database/test_sql_gen_e2e.py b/tests/core/database/test_sql_gen_e2e.py index 297f344a..f74061a4 100644 --- a/tests/core/database/test_sql_gen_e2e.py +++ b/tests/core/database/test_sql_gen_e2e.py @@ -56,7 +56,7 @@ def test_literal(self, db_test): def wrap_and_execute_expression(self, db_test, expr): wrapped = QuerySpecification( select=Select( - selectItems=[SingleColumn(alias="res", expression=expr)], + selectItems=[SingleColumn(alias=self.db_extension().quote_identifier("res"), expression=expr)], distinct=False ), from_=[], diff --git a/tests/extensions/database/vendors/mysql/__init__.py b/tests/extensions/database/vendors/mysql/__init__.py new file mode 100644 index 00000000..5757135b --- /dev/null +++ b/tests/extensions/database/vendors/mysql/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2023 Goldman Sachs +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/tests/extensions/database/vendors/mysql/test_mysql_sql_gen_e2e.py b/tests/extensions/database/vendors/mysql/test_mysql_sql_gen_e2e.py new file mode 100644 index 00000000..f5221b77 --- /dev/null +++ b/tests/extensions/database/vendors/mysql/test_mysql_sql_gen_e2e.py @@ -0,0 +1,42 @@ +# Copyright 2023 Goldman Sachs +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# type: ignore +import pytest +import platform +import sqlalchemy +from testcontainers.mysql import MySqlContainer +from tests.core.database.test_sql_gen_e2e import E2EDbSpecificSqlGenerationTest +from pylegend.extensions.database.vendors.mysql.mysql_sql_to_string import MySQLSqlToStringGenerator + + +@pytest.mark.skipif(platform.system() in ("Windows", "Darwin"), reason="Skip on windows and macos") +class TestMySQLE2ESqlGeneration(E2EDbSpecificSqlGenerationTest): + extension = MySQLSqlToStringGenerator.create_sql_generator().get_db_extension() + + @pytest.fixture(scope='module') + def db_test(self): + with MySqlContainer() as c: + engine = sqlalchemy.create_engine(c.get_connection_url()) + yield { + "engine": engine + } + + def execute_sql(self, db_test, sql): + with db_test["engine"].connect() as c: + return c.execute(sqlalchemy.text(sql)) + + def db_extension(self): + return self.extension diff --git a/tests/extensions/database/vendors/mysql/test_mysql_sql_to_string.py b/tests/extensions/database/vendors/mysql/test_mysql_sql_to_string.py new file mode 100644 index 00000000..c5732f34 --- /dev/null +++ b/tests/extensions/database/vendors/mysql/test_mysql_sql_to_string.py @@ -0,0 +1,38 @@ +# Copyright 2023 Goldman Sachs +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import importlib +from pylegend.core.databse.sql_to_string import ( + SqlToStringGenerator, + SqlToStringConfig, + SqlToStringFormat, +) + +mysql_ext = 'pylegend.extensions.database.vendors.mysql.mysql_sql_to_string' +importlib.import_module(mysql_ext) + + +class TestMySQLSqlToString: + generator = SqlToStringGenerator.find_sql_to_string_generator_for_db_type("MySQL") + db_ext = generator.get_db_extension() + + def test_find_mysql_sql_generator(self) -> None: + assert self.generator is not None + assert (str(type(self.generator)) == + "") + + def test_process_identifier(self) -> None: + config = SqlToStringConfig(SqlToStringFormat(pretty=False)) + assert self.db_ext.process_identifier("A", config, True) == "`A`" diff --git a/tests/extensions/database/vendors/postgres/test_postgres_sql_to_string.py b/tests/extensions/database/vendors/postgres/test_postgres_sql_to_string.py new file mode 100644 index 00000000..33ad51fc --- /dev/null +++ b/tests/extensions/database/vendors/postgres/test_postgres_sql_to_string.py @@ -0,0 +1,33 @@ +# Copyright 2023 Goldman Sachs +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import importlib +from pylegend.core.databse.sql_to_string import ( + SqlToStringGenerator, +) + +postgres_ext = 'pylegend.extensions.database.vendors.postgres.postgres_sql_to_string' +importlib.import_module(postgres_ext) + + +class TestPostgresSqlToString: + generator = SqlToStringGenerator.find_sql_to_string_generator_for_db_type("Postgres") + db_ext = generator.get_db_extension() + + def test_find_postgres_sql_generator(self) -> None: + assert self.generator is not None + assert (str(type(self.generator)) == + (""))