Repository: kayak/pypika (python)

Issue:
add Table.select?
Has allowing `Table` to `select`, eliminating the name to re-specify a table name with `from_` been considered? e.g.

```python
from pypika import Table, Query
t = Table('my_table')
t.select(t.x, t.y) == Query.from_('my_table').select(t.x, t.y) # -> True
```

Just an idea. Seems like it would add convenience when using from console/jupyter.

Thanks for your hard work on a great library!

Pull request description:
feat: add table level alias for select, insert and update
Fixes #264 and #259 

### To Do

- [x] Add documentation about table level aliases
- [x] Add example in documentation

Patch:
diff --git a/README.rst b/README.rst
index 8c7686e..c33b32f 100644
--- a/README.rst
+++ b/README.rst
@@ -92,6 +92,20 @@ Both of the above examples result in the following SQL:
 
     SELECT id,fname,lname,phone FROM customers
 
+Using ``pypika.Table`` based select alias
+
+.. code-block:: python
+
+    customers = Table('customers')
+    q = customers.select(custimers.id, customers.fname)
+
+query will return in the following SQL:
+
+.. code-block:: sql
+
+    SELECT id, fname FROM customers
+
+
 Results can be ordered by using the following syntax:
 
 .. code-block:: python
@@ -428,8 +442,8 @@ Example of a correlated subquery in the `SELECT`
     q = Query.from_(customers).select(
         customers.id, last_purchase_at._as('last_purchase_at')
     )
-    
-    
+
+
 .. code-block:: sql
 
     SELECT
@@ -634,6 +648,16 @@ Insert with values
 
     INSERT INTO customers VALUES (1,'Jane','Doe','jane@example.com')
 
+.. code-block:: python
+
+    customers =  Table('customers')
+
+    q = customers.insert(1, 'Jane', 'Doe', 'jane@example.com')
+
+.. code-block:: sql
+
+    INSERT INTO customers VALUES (1,'Jane','Doe','jane@example.com')
+
 Multiple rows of data can be inserted either by chaining the ``insert`` function or passing multiple tuples as args.
 
 .. code-block:: python
@@ -764,6 +788,35 @@ The syntax for joining tables is the same as when selecting data
    JOIN "profiles" ON "profiles"."customer_id"="customers"."id"
    SET "customers"."lname"="profiles"."lname"
 
+Using ``pypika.Table`` alias to perform the update
+
+.. code-block:: python
+
+    customers = Table('customers')
+
+    customers.update()
+            .set(customers.lname, 'smith')
+            .where(customers.id == 10)
+
+.. code-block:: sql
+
+    UPDATE "customers" SET "lname"='smith' WHERE "id"=10
+
+Using ``limit`` for performing update
+
+.. code-block:: python
+
+    customers = Table('customers')
+
+    customers.update()
+            .set(customers.lname, 'smith')
+            .limit(2)
+
+.. code-block:: sql
+
+    UPDATE "customers" SET "lname"='smith' LIMIT 2
+
+
 Parametrized Queries
 ^^^^^^^^^^^^^^^^^^^^
 
diff --git a/pypika/queries.py b/pypika/queries.py
index 2b385cd..d3da3a3 100644
--- a/pypika/queries.py
+++ b/pypika/queries.py
@@ -148,6 +148,40 @@ class Table(Selectable):
     def __hash__(self):
         return hash(str(self))
 
+    def select(self, *terms):
+        """
+        Perform a SELECT operation on the current table
+
+        :param terms:
+            Type:  list[expression]
+
+            A list of terms to select. These can be any type of int, float, str, bool or Term or a Field.
+
+        :return:  QueryBuilder
+        """
+        return Query.from_(self).select(*terms)
+
+    def update(self):
+        """
+        Perform an UPDATE operation on the current table
+
+        :return: QueryBuilder
+        """
+        return Query.update(self)
+
+    def insert(self, *terms):
+        """
+        Perform an INSERT operation on the current table
+
+        :param terms:
+            Type: list[expression]
+
+            A list of terms to select. These can be any type of int, float, str, bool or  any other valid data
+
+        :return: QueryBuilder
+        """
+        return Query.into(self).insert(*terms)
+
 
 def make_tables(*names, **kwargs):
     """
@@ -811,6 +845,9 @@ class QueryBuilder(Selectable, Term):
             if self._wheres:
                 querystring += self._where_sql(**kwargs)
 
+            if self._limit:
+                querystring += self._limit_sql()
+
             return querystring
 
         if self._delete_from:


Test patch:
diff --git a/pypika/tests/test_inserts.py b/pypika/tests/test_inserts.py
index 574e309..8e55efc 100644
--- a/pypika/tests/test_inserts.py
+++ b/pypika/tests/test_inserts.py
@@ -110,6 +110,14 @@ class InsertIntoTests(unittest.TestCase):
 
         self.assertEqual('INSERT INTO "abc" VALUES (NULL)', str(query))
 
+    def test_insert_column_using_table_alias(self):
+        q = self.table_abc.insert(1)
+        self.assertEqual('INSERT INTO "abc" VALUES (1)', str(q))
+
+    def test_insert_column_using_alias_with_chain(self):
+        q = self.table_abc.insert(1, 'a', True).insert(2, 'b', False)
+        self.assertEqual('INSERT INTO "abc" VALUES (1,\'a\',true),(2,\'b\',false)', str(q))
+
 
 class PostgresInsertIntoOnConflictTests(unittest.TestCase):
     table_abc = Table('abc')
diff --git a/pypika/tests/test_selects.py b/pypika/tests/test_selects.py
index 6b97500..9c153a8 100644
--- a/pypika/tests/test_selects.py
+++ b/pypika/tests/test_selects.py
@@ -222,6 +222,22 @@ class SelectTests(unittest.TestCase):
 
         self.assertEqual('SELECT "foo","bar" FROM "abc"', str(q))
 
+    def test_table_select_alias(self):
+        q = self.table_abc.select(1)
+
+        self.assertEqual('SELECT 1 FROM "abc"', str(q))
+        self.assertEqual(q, Query.from_("abc").select(1))
+
+    def test_table_select_alias_with_offset_and_limit(self):
+        self.assertEqual(
+            self.table_abc.select("foo")[10:10],
+            Query.from_('abc').select('foo')[10:10]
+        )
+        self.assertEqual(
+            self.table_abc.select(self.table_abc.foo)[10:10],
+            Query.from_('abc').select('foo')[10:10]
+        )
+
 
 class WhereTests(unittest.TestCase):
     t = Table('abc')
@@ -232,6 +248,8 @@ class WhereTests(unittest.TestCase):
 
         self.assertEqual('SELECT * FROM "abc" WHERE "foo"="bar"', str(q1))
         self.assertEqual('SELECT * FROM "abc" WHERE "foo"="bar"', str(q2))
+        q = self.t.select('*').where(self.t.foo == self.t.bar)
+        self.assertEqual(q, q1)
 
     def test_where_field_equals_where(self):
         q = Query.from_(self.t).select('*').where(self.t.foo == 1).where(self.t.bar == self.t.baz)
diff --git a/pypika/tests/test_updates.py b/pypika/tests/test_updates.py
index a6d731c..16c8699 100644
--- a/pypika/tests/test_updates.py
+++ b/pypika/tests/test_updates.py
@@ -40,6 +40,10 @@ class UpdateTests(unittest.TestCase):
         q = Query.update(self.table_abc).join(self.table_def).on(self.table_def.abc_id == self.table_abc.id).set(self.table_abc.lname, self.table_def.lname)
         self.assertEqual('UPDATE "abc" JOIN "def" ON "def"."abc_id"="abc"."id" SET "abc"."lname"="def"."lname"', str(q))
 
+    def test_update_with_limit(self):
+        q = Query.update(self.table_abc).set(self.table_abc.lname, "test").limit(1)
+        self.assertEqual('UPDATE "abc" SET "lname"=\'test\' LIMIT 1', str(q))
+
 
 class PostgresUpdateTests(unittest.TestCase):
     table_abc = Table('abc')