Issue: Join "on" clause does not accept a conjunction or disjunction.
Author: rammie
State: closed
Created: 2013-09-05 18:45:49

I ran into this issue while trying to do a left join which requires multiple conditions in the on clause. Here is a traceback of the issue:

```
Traceback (most recent call last):
  ...
  File "python2.7/site-packages/peewee.py", line 1650, in __iter__
    return iter(self.execute())
  File "python2.7/site-packages/peewee.py", line 1643, in execute
    self._qr = ResultWrapper(self.model_class, self._execute(), query_meta)
  File "python2.7/site-packages/peewee.py", line 1190, in __init__
    self.column_map, self.join_map = self.prepare()
  File "python2.7/site-packages/peewee.py", line 1226, in prepare
    fk_name = join.on._alias or join.on.lhs.name
AttributeError: 'Expr' object has no attribute 'name'
```


Try adding a `.alias('foo')` to your expression.


Sweet, that works! Thanks once again, peewee rulz.


Probably needs a better error message, glad you're liking peewee!


@rammie -- Do you mind sharing the join that caused this error?


``` python
from peewee import *

class T2(Model):
    f2 = CharField()

class T3(Model):
    f3 = CharField()

class T(Model):
    f2 = ForeignKeyField(T2)
    f3 = ForeignKeyField(T3)

class TAccessLog(Model):
    t = ForeignKeyField(T)
    u = ForeignKeyField(T3)

u = T3.select().get()
T.select(T, T.f2, T.f3, TAccessLog).switch(T).join(T3).switch(T).join(T2).switch(T).join(
    TAccessLog, JOIN_LEFT_OUTER, on=(
        (TAccessLog.u == u) & (TAccessLog.t == T.id)
    ).alias("taccesslog")
).switch(T)
```

I haven't tested it after  simplifying it and extracting it from the codebase. Also, I'm not sure if the initial joins matter. If you remove the alias from the query, something like this should do the trick.


Hi question when you writing a join you end up with query like this

exp.
SELECT t1.\* FROM blog AS t1
INNER JOIN user AS t2
    ON t1.user_id = t2.id
WHERE
    t1.status = ? AND
    t2.is_staff = ?

Now , can you control how output query look like , so "INNER JOIN user AS t2"  can be changed with
"INNER JOIN user AS USER", 

it would be great if we can control how table is aliased in class construction

class User(Model):
       class Meta:
            table_alias = 'USER'


@stanegit -- currently that is not controllable...what's your use-case?


In company there are "conventions" when you do joins (could be a lot of them) that table aliases are  always the same (it is easier to grok the huge query).


hi i have those models

``` python
class Category(BaseModel):
    category_id = BigIntegerField(primary_key=True)
    category_name = CharField(max_length=255)

    class Meta:
        db_table = 'category'

class ItemCategory(BaseModel):
    added_date = DateTimeField(null=True)
    category_id = BigIntegerField()
    item_id = BigIntegerField()
    item_type_id = PrimaryKeyField()

    class Meta:
        db_table = 'item_category'
```

i run this sql

``` python
query = Category.select(Category, ItemCategory)
query = query.join( ItemCategory, JOIN_LEFT_OUTER, on=(
        (Category.category_id==ItemCategory.category_id ) & ( ItemCategory.item_type_id==2 )
    )
)
```

when i try to get rows with foreach it throws that error
**target_attr = self.on.lhs.name . AttributeError: 'Expression' object has no attribute 'name'**

``` python
for c in query:
    print c
```

is it bug or i am doing something wrong?

i put console screenshoot below
![screen shot 2014-10-21 at 19 23 43](https://cloud.githubusercontent.com/assets/1669906/4722253/ad6b5b90-593e-11e4-8e31-6f1fc1e80d96.png)


Fixed in https://github.com/coleifer/peewee/commit/9f27f1b05dfb67ffce2bcc0e43943aa9833b8a0e


Thanks.
is it fixed when we install by pip ? or we will fix manually?


I'll need to issue a new release. You can work around by filtering on `ItemCategory.item_type_id == 2` in the WHERE clause instead of the join predicate.


Or use `naive()` query, it seems to work fine.