diff --git a/clickhouse_sqlalchemy/drivers/compilers/sqlcompiler.py b/clickhouse_sqlalchemy/drivers/compilers/sqlcompiler.py index 465b3331..ad4c6ec4 100644 --- a/clickhouse_sqlalchemy/drivers/compilers/sqlcompiler.py +++ b/clickhouse_sqlalchemy/drivers/compilers/sqlcompiler.py @@ -146,7 +146,10 @@ def visit_join(self, join, asfrom=False, **kwargs): flags = join.full if not isinstance(flags, dict): - flags = {'full': flags} + if isinstance(flags, str): + flags = {'full': flags} + else: + flags = dict(flags) # need to make a variable to prevent leaks in some debuggers join_type = flags.get('type') if join_type is None: diff --git a/clickhouse_sqlalchemy/orm/query.py b/clickhouse_sqlalchemy/orm/query.py index 3b486e2f..c4c082d4 100644 --- a/clickhouse_sqlalchemy/orm/query.py +++ b/clickhouse_sqlalchemy/orm/query.py @@ -110,7 +110,7 @@ def join(self, *props, **kwargs): x_spec = dict(spec) # use 'full' key to pass extra flags x_spec['full'] = x[-1]['full'] - x[-1]['full'] = x_spec + x[-1]['full'] = tuple(x_spec.items()) return rv diff --git a/clickhouse_sqlalchemy/sql/schema.py b/clickhouse_sqlalchemy/sql/schema.py index 89ddad43..fbc72886 100644 --- a/clickhouse_sqlalchemy/sql/schema.py +++ b/clickhouse_sqlalchemy/sql/schema.py @@ -20,12 +20,12 @@ def drop(self, bind=None, checkfirst=False, if_exists=False): def join(self, right, onclause=None, isouter=False, full=False, type=None, strictness=None, distribution=None): - flags = { + flags = tuple({ 'full': full, 'type': type, 'strictness': strictness, 'distribution': distribution - } + }.items()) return Join(self, right, onclause=onclause, isouter=isouter, full=flags) diff --git a/clickhouse_sqlalchemy/sql/selectable.py b/clickhouse_sqlalchemy/sql/selectable.py index 35b77404..6b1ed9ae 100644 --- a/clickhouse_sqlalchemy/sql/selectable.py +++ b/clickhouse_sqlalchemy/sql/selectable.py @@ -63,12 +63,12 @@ def left_array_join(self, *columns): def join(self, right, onclause=None, isouter=False, full=False, type=None, strictness=None, distribution=None): - flags = { + flags = tuple({ 'full': full, 'type': type, 'strictness': strictness, 'distribution': distribution - } + }.items()) return Join(self, right, onclause=onclause, isouter=isouter, full=flags) diff --git a/tests/orm/test_select.py b/tests/orm/test_select.py index ef21d391..675266c0 100644 --- a/tests/orm/test_select.py +++ b/tests/orm/test_select.py @@ -394,6 +394,29 @@ def test_multiple_joins(self): ) +class JoinExecuteTestCase(NativeSessionTestCase): + def test_execute_full_join(self): + numbers = Table( + 'numbers', self.metadata(), + Column('number', types.UInt64, primary_key=True), + schema='system' + ) + + sub_query1 = self.session.query(numbers.c.number.label('x')) \ + .limit(1) \ + .subquery() + + sub_query2 = self.session.query(numbers.c.number.label('x')) \ + .limit(1) \ + .subquery() + + query = self.session.query(sub_query1.c.x, sub_query2.c.x) \ + .outerjoin(sub_query2, (sub_query1.c.x == sub_query2.c.x)) + + self.assertEqual(query.all(), [(0, 0)]) + + + class YieldTest(NativeSessionTestCase): def test_yield_per_and_execution_options(self): numbers = Table(