Skip to content

Commit

Permalink
Fixes kayak#299 Add database object and added attribute references fo…
Browse files Browse the repository at this point in the history
…r database->schema and schema->table
  • Loading branch information
twheys committed Aug 21, 2019
1 parent d9b3768 commit 46604d7
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 9 deletions.
48 changes: 40 additions & 8 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Installation

.. _installation_start:

|Brand| supports python ``3.3+``. It may also work on pypy, cython, and jython, but is not being tested for these versions.
|Brand| supports python ``3.4+``. It may also work on pypy, cython, and jython, but is not being tested for these versions.

To install |Brand| run the following command:

Expand Down Expand Up @@ -79,10 +79,18 @@ Alternatively, you can use the `Query.get_sql()` function:
q.get_sql()
Using ``pypika.Table``
Tables, Columns, Schemas, and Databases
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

In simple queries like the above example, columns in the "from" table can be referenced by passing string names into
the ``select`` query builder function. In more complex examples, the ``pypika.Table`` class should be used. Columns can be
referenced as attributes on instances of ``pypika.Table``.

.. code-block:: python
from pypika import Table, Query
customers = Table('customers')
q = Query.from_(customers).select(customers.id, customers.fname, customers.lname, customers.phone)
Expand All @@ -92,18 +100,42 @@ Both of the above examples result in the following SQL:
SELECT id,fname,lname,phone FROM customers
Using ``pypika.Table`` based select alias
An alias for the table can be given using the ``.as_`` function on ``pypika.Table``

.. code-block:: python
.. code-block:: sql
customers = Table('customers')
q = customers.select(customers.id, customers.fname)
Table('x_view_customers').as_('customers')
q = Query.from_(customers).select(customers.id, customers.phone)
.. code-block:: sql
SELECT id,phone FROM x_view_customers customers
A schema can also be specified. Tables can be referenced as attributes on the schema.

.. code-block:: sql
from pypika import Table, Query, Schema
views = Schema('views')
q = Query.from_(views.customers).select(customers.id, customers.phone)
.. code-block:: sql
SELECT id,phone FROM views.customers
Also references to databases can be used. Schemas can be referenced as attributes on the database.

.. code-block:: sql
from pypika import Table, Query, Database
query will return in the following SQL:
my_db = Database('my_db')
q = Query.from_(my_db.analytics.customers).select(customers.id, customers.phone)
.. code-block:: sql
SELECT id, fname FROM customers
SELECT id,phone FROM my_db.analytics.customers
Results can be ordered by using the following syntax:
Expand Down
1 change: 1 addition & 0 deletions pypika/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
Query,
Schema,
Table,
Database,
make_tables as Tables,
)
# noinspection PyUnresolvedReferences
Expand Down
12 changes: 12 additions & 0 deletions pypika/queries.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ class Selectable:
def __init__(self, alias):
self.alias = alias

@builder
def as_(self, alias):
self.alias = alias

def field(self, name):
return Field(name, table=self)

Expand Down Expand Up @@ -79,6 +83,9 @@ def __eq__(self, other):
def __ne__(self, other):
return not self.__eq__(other)

def __getattr__(self, item):
return Table(item, schema=self)

def get_sql(self, quote_char=None, **kwargs):
# FIXME escape
schema_sql = format_quotes(self._name, quote_char)
Expand All @@ -91,6 +98,11 @@ def get_sql(self, quote_char=None, **kwargs):
return schema_sql


class Database(Schema):
def __getattr__(self, item):
return Schema(item, parent=self)


class Table(Selectable):
@staticmethod
def _init_schema(schema):
Expand Down
35 changes: 34 additions & 1 deletion pypika/tests/test_tables.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,48 @@
import unittest

from pypika import (
Database,
Schema,
Table,
Tables
Tables,
)

__author__ = "Timothy Heys"
__email__ = "theys@kayak.com"


class TableStructureTests(unittest.TestCase):
def test_table_sql(self):
table = Table('test_table')

self.assertEqual('"test_table"', str(table))

def test_table_with_alias(self):
table = Table('test_table').as_('my_table')

self.assertEqual('"test_table" "my_table"', table.get_sql(with_alias=True, quote_char='"'))

def test_schema_table_attr(self):
table = Schema('x_schema').test_table

self.assertEqual('"x_schema"."test_table"', str(table))

def test_table_with_schema_arg(self):
table = Table("test_table", schema=Schema('x_schema'))

self.assertEqual('"x_schema"."test_table"', str(table))

def test_database_schema_table_attr(self):
table = Database('x_db').x_schema.test_table

self.assertEqual('"x_db"."x_schema"."test_table"', str(table))

def test_table_with_schema_and_schema_parent_arg(self):
table = Table("test_table", schema=Schema('x_schema', parent=Database('x_db')))

self.assertEqual('"x_db"."x_schema"."test_table"', str(table))


class TableEqualityTests(unittest.TestCase):
def test_tables_equal_by_name(self):
t1 = Table("t")
Expand Down

0 comments on commit 46604d7

Please sign in to comment.