You can update the SQLCompiler
within your Dialect
to support the necessary functionality as shown below.
I doubt this would be a reasonable solution for most practical use-cases, but it does carry some educational value, I believe.
from sqlalchemy.dialects.sqlite import base
class MySQLiteCompiler(base.SQLiteCompiler):
# Update the visit_join method to support a hypothetical
# MAGIC keyword.
#
# For that we copy the code over from
# https://github.com/sqlalchemy/sqlalchemy/blob/e7aabd54c4defe237cecfa80863f0d7fa5a48035/lib/sqlalchemy/sql/compiler.py#L4987
# and add a small modification (marked below).
#
# The borrowed piece of code is subject to:
# Copyright (C) 2005-2023 the SQLAlchemy authors and contributors.
# Released under the MIT license.
def visit_join(self, join, asfrom=False, from_linter=None, **kwargs):
if from_linter:
from_linter.edges.update(
itertools.product(
join.left._from_objects, join.right._from_objects
)
)
if join.full:
join_type = " FULL OUTER JOIN "
elif join.isouter:
join_type = " LEFT OUTER JOIN "
# --- Start of modification ---
if join.ismagic:
join_type = " LEFT MAGIC JOIN "
# --- End of modification ---
else:
join_type = " JOIN "
return (
join.left._compiler_dispatch(
self, asfrom=True, from_linter=from_linter, **kwargs
)
+ join_type
+ join.right._compiler_dispatch(
self, asfrom=True, from_linter=from_linter, **kwargs
)
+ " ON "
# TODO: likely need asfrom=True here?
+ join.onclause._compiler_dispatch(
self, from_linter=from_linter, **kwargs
)
)
class MyDialect(base.SQLiteDialect):
statement_compiler = MySQLiteCompiler
Example usage:
import sqlalchemy as sa
my_join = sa.join(sa.select("a"), sa.select("b"),
sa.text("whatever"), isouter=True)
my_join.ismagic = True
print(my_join.compile(dialect=MyDialect()))