Repository: kayak/pypika (python)

Issue:
Invalid outer join for postgresql
Current join enum have only basic "OUTER" join, which is not supported by postgresql.
`how` parameter for joins should accept list of JoinType's, so join could be concatenated, or JoinType enum should be extended to have `LEFT OUTER' 'RIGHT OUTER' 'FULL OUTER'.

I can implement it, but would like to hear your opinion on this matter, may be I am missing something, how joins should be built with pypika 

Pull request description:
Fixes #95 Added left outer, right outer, and full outer as join types

Patch:
diff --git a/pypika/enums.py b/pypika/enums.py
index 9a4472d..e96a283 100644
--- a/pypika/enums.py
+++ b/pypika/enums.py
@@ -47,6 +47,9 @@ class JoinType(Enum):
     left = 'LEFT'
     right = 'RIGHT'
     outer = 'OUTER'
+    left_outer = 'LEFT OUTER'
+    right_outer = 'RIGHT OUTER'
+    full_outer = 'FULL OUTER'
 
 
 class UnionType(Enum):


Test patch:
diff --git a/pypika/tests/test_joins.py b/pypika/tests/test_joins.py
index 1465950..6cb41d5 100644
--- a/pypika/tests/test_joins.py
+++ b/pypika/tests/test_joins.py
@@ -2,16 +2,15 @@
 import unittest
 
 from pypika import (
+    Interval,
+    JoinException,
+    JoinType,
+    MySQLQuery,
     Query,
     Table,
     Tables,
-    JoinException,
-    functions as fn,
-    analytics as an,
-    JoinType,
     UnionException,
-    Interval,
-    MySQLQuery,
+    functions as fn,
 )
 
 __author__ = "Timothy Heys"
@@ -42,6 +41,30 @@ class JoinTypeTests(unittest.TestCase):
         self.assertEqual('SELECT * FROM "abc" JOIN "efg" ON "abc"."foo"="efg"."bar"', str(query))
         self.assertEqual('SELECT * FROM "abc" JOIN "efg" ON "abc"."foo"="efg"."bar"', str(query_explicit))
 
+    def test_outer_join(self):
+        q = Query.from_(self.table0).join(self.table1, how=JoinType.outer).on(
+              self.table0.foo == self.table1.bar).select('*')
+
+        self.assertEqual('SELECT * FROM "abc" OUTER JOIN "efg" ON "abc"."foo"="efg"."bar"', str(q))
+
+    def test_left_outer_join(self):
+        q = Query.from_(self.table0).join(self.table1, how=JoinType.left_outer).on(
+              self.table0.foo == self.table1.bar).select('*')
+
+        self.assertEqual('SELECT * FROM "abc" LEFT OUTER JOIN "efg" ON "abc"."foo"="efg"."bar"', str(q))
+
+    def test_right_outer_join(self):
+        q = Query.from_(self.table0).join(self.table1, how=JoinType.right_outer).on(
+              self.table0.foo == self.table1.bar).select('*')
+
+        self.assertEqual('SELECT * FROM "abc" RIGHT OUTER JOIN "efg" ON "abc"."foo"="efg"."bar"', str(q))
+
+    def test_full_outer_join(self):
+        q = Query.from_(self.table0).join(self.table1, how=JoinType.full_outer).on(
+              self.table0.foo == self.table1.bar).select('*')
+
+        self.assertEqual('SELECT * FROM "abc" FULL OUTER JOIN "efg" ON "abc"."foo"="efg"."bar"', str(q))
+
     def test_join_on_field_single(self):
         query = Query.from_(self.table0).join(self.table1).on_field("foo").select('*')
         self.assertEqual('SELECT * FROM "abc" JOIN "efg" ON "abc"."foo"="efg"."foo"', str(query))