Skip to content

Commit

Permalink
Merge branch 'master' to 'orm': bugfix
Browse files Browse the repository at this point in the history
  • Loading branch information
kozlovsky committed Sep 14, 2016
2 parents 492072d + 29a07c9 commit 9fed601
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 3 deletions.
14 changes: 12 additions & 2 deletions pony/orm/sqltranslation.py
Original file line number Diff line number Diff line change
Expand Up @@ -869,6 +869,16 @@ def get_short_alias(subquery, name_path, entity_name):
alias = '%s-%d' % (name, i)
subquery.alias_counters[name] = i
return alias
def join_table(subquery, parent_alias, alias, table_name, join_cond):
new_item = [alias, 'TABLE', table_name, join_cond]
from_ast = subquery.from_ast
for i in xrange(1, len(from_ast)):
if from_ast[i][0] == parent_alias:
for j in xrange(i+1, len(from_ast)):
if len(from_ast[j]) < 4: # item without join condition
from_ast.insert(j, new_item)
return
from_ast.append(new_item)

class TableRef(object):
def __init__(tableref, subquery, name, entity):
Expand Down Expand Up @@ -945,7 +955,7 @@ def make_join(tableref, pk_only=False):
m2m_alias = subquery.get_short_alias(None, 't')
reverse_columns = attr.columns if attr.symmetric else attr.reverse.columns
m2m_join_cond = join_tables(parent_alias, m2m_alias, left_pk_columns, reverse_columns)
subquery.from_ast.append([ m2m_alias, 'TABLE', m2m_table, m2m_join_cond ])
subquery.join_table(parent_alias, m2m_alias, m2m_table, m2m_join_cond)
if pk_only:
tableref.alias = m2m_alias
tableref.pk_columns = right_m2m_columns
Expand All @@ -961,7 +971,7 @@ def make_join(tableref, pk_only=False):
discr_criteria = entity._construct_discriminator_criteria_(alias)
assert discr_criteria is not None
join_cond.append(discr_criteria)
subquery.from_ast.append([ alias, 'TABLE', entity._table_, join_cond ])
subquery.join_table(parent_alias, alias, entity._table_, join_cond)
tableref.alias = alias
tableref.pk_columns = pk_columns
tableref.optimized = False
Expand Down
2 changes: 1 addition & 1 deletion pony/orm/tests/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ def __enter__(self):

def __exit__(self, *exc_info):
self.Test.db.provider.json1_available = self.json1_available
return super(SqliteNoJson1, self).__exit__()
return super(SqliteNoJson1, self).__exit__(*exc_info)


@provider()
Expand Down
90 changes: 90 additions & 0 deletions pony/orm/tests/test_inner_join_syntax.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import unittest

from pony.orm import *
from pony import orm

import pony.orm.tests.fixtures

class TestJoin(unittest.TestCase):

exclude_fixtures = {'test': ['clear_tables']}

@classmethod
def setUpClass(cls):
db = cls.db = Database('sqlite', ':memory:')

class Genre(db.Entity):
name = orm.Optional(str) # TODO primary key
artists = orm.Set('Artist')
favorite = orm.Optional(bool)
index = orm.Optional(int)

class Hobby(db.Entity):
name = orm.Required(str)
artists = orm.Set('Artist')

class Artist(db.Entity):
name = orm.Required(str)
age = orm.Optional(int)
hobbies = orm.Set(Hobby)
genres = orm.Set(Genre)

db.generate_mapping(create_tables=True)

with orm.db_session:
pop = Genre(name='pop')
rock = Genre(name='rock')
Artist(name='Sia', age=40, genres=[pop, rock])
Artist(name='Lady GaGa', age=30, genres=[pop])

pony.options.INNER_JOIN_SYNTAX = True

@db_session
def test_join_1(self):
result = select(g.id for g in self.db.Genre for a in g.artists if a.name.startswith('S'))[:]
self.assertEqual(self.db.last_sql, """SELECT DISTINCT "g"."id"
FROM "Genre" "g"
INNER JOIN "Artist_Genre" "t-1"
ON "g"."id" = "t-1"."genre"
INNER JOIN "Artist" "a"
ON "t-1"."artist" = "a"."id"
WHERE "a"."name" LIKE 'S%'""")

@db_session
def test_join_2(self):
result = select(g.id for g in self.db.Genre for a in self.db.Artist
if JOIN(a in g.artists) and a.name.startswith('S'))[:]
self.assertEqual(self.db.last_sql, """SELECT DISTINCT "g"."id"
FROM "Genre" "g"
INNER JOIN "Artist_Genre" "t-1"
ON "g"."id" = "t-1"."genre", "Artist" "a"
WHERE "t-1"."artist" = "a"."id"
AND "a"."name" LIKE 'S%'""")


@db_session
def test_join_3(self):
result = select(g.id for g in self.db.Genre for x in self.db.Artist for a in self.db.Artist
if JOIN(a in g.artists) and a.name.startswith('S') and g.id == x.id)[:]
self.assertEqual(self.db.last_sql, '''SELECT DISTINCT "g"."id"
FROM "Genre" "g"
INNER JOIN "Artist_Genre" "t-1"
ON "g"."id" = "t-1"."genre", "Artist" "x", "Artist" "a"
WHERE "t-1"."artist" = "a"."id"
AND "a"."name" LIKE 'S%'
AND "g"."id" = "x"."id"''')

@db_session
def test_join_4(self):
result = select(g.id for g in self.db.Genre for a in self.db.Artist for x in self.db.Artist
if JOIN(a in g.artists) and a.name.startswith('S') and g.id == x.id)[:]
self.assertEqual(self.db.last_sql, '''SELECT DISTINCT "g"."id"
FROM "Genre" "g"
INNER JOIN "Artist_Genre" "t-1"
ON "g"."id" = "t-1"."genre", "Artist" "a", "Artist" "x"
WHERE "t-1"."artist" = "a"."id"
AND "a"."name" LIKE 'S%'
AND "g"."id" = "x"."id"''')

if __name__ == '__main__':
unittest.main()

0 comments on commit 9fed601

Please sign in to comment.