Repository: kayak/pypika (Python)

Issue:
Error with empty argument columns
With support iterable params to columns(issue #372, PR #373). I didn't catch that empty `columns` can be pass to arg of `columns`. Sadly, there is no Testcase that test below cases.

So passing empty argument to `columns` generate errors. Below are simple test code and result.

``` python
from pypika import Query, Table

table = Table("abc")
query = (
    Query.into(table)
    .columns()
    .insert(1, "a", True)
)

print(str(query))
```

Result at 0.35.21
``` SQL
INSERT INTO "abc" VALUES (1,'a',true)
```

Result at 0.37.4
``` bash
  File "a.py", line 5, in <module>
    Query.into(table)
  File "/root/.pyenv/versions/py37/lib/python3.7/site-packages/pypika/utils.py", line 50, in _copy
    result = func(self_copy, *args, **kwargs)
  File "/root/.pyenv/versions/py37/lib/python3.7/site-packages/pypika/queries.py", line 775, in columns
    if isinstance(terms[0], (list, tuple)):
IndexError: tuple index out of range
```



Discussion:

Patch:
diff --git a/pypika/queries.py b/pypika/queries.py
index 2ab94ed1..65dfd71f 100644
--- a/pypika/queries.py
+++ b/pypika/queries.py
@@ -772,7 +772,7 @@ def columns(self, *terms: Any) -> "QueryBuilder":
         if self._insert_table is None:
             raise AttributeError("'Query' object has no attribute '%s'" % "insert")
 
-        if isinstance(terms[0], (list, tuple)):
+        if terms and isinstance(terms[0], (list, tuple)):
             terms = terms[0]
 
         for term in terms:


Test patch:
diff --git a/pypika/tests/test_inserts.py b/pypika/tests/test_inserts.py
index 7a3ada75..3f888c60 100644
--- a/pypika/tests/test_inserts.py
+++ b/pypika/tests/test_inserts.py
@@ -113,6 +113,17 @@ def test_insert_selected_columns(self):
             'INSERT INTO "abc" ("foo","bar","buz") VALUES (1,\'a\',true)', str(query)
         )
 
+    def test_insert_empty_columns(self):
+        query = (
+            Query.into(self.table_abc)
+            .columns()
+            .insert(1, "a", True)
+        )
+
+        self.assertEqual(
+            'INSERT INTO "abc" VALUES (1,\'a\',true)', str(query)
+        )
+
     def test_insert_selected_columns_type_list(self):
         query = (
             Query.into(self.table_abc)
@@ -124,6 +135,17 @@ def test_insert_selected_columns_type_list(self):
             'INSERT INTO "abc" ("foo","bar","buz") VALUES (1,\'a\',true)', str(query)
         )
 
+    def test_insert_empty_columns_type_list(self):
+        query = (
+            Query.into(self.table_abc)
+            .columns([])
+            .insert(1, "a", True)
+        )
+
+        self.assertEqual(
+            'INSERT INTO "abc" VALUES (1,\'a\',true)', str(query)
+        )
+
     def test_insert_selected_columns_type_tuple(self):
         query = (
             Query.into(self.table_abc)
@@ -135,6 +157,17 @@ def test_insert_selected_columns_type_tuple(self):
             'INSERT INTO "abc" ("foo","bar","buz") VALUES (1,\'a\',true)', str(query)
         )
 
+    def test_insert_empty_columns_type_tuple(self):
+        query = (
+            Query.into(self.table_abc)
+            .columns(())
+            .insert(1, "a", True)
+        )
+
+        self.assertEqual(
+            'INSERT INTO "abc" VALUES (1,\'a\',true)', str(query)
+        )
+
     def test_insert_none_skipped(self):
         query = Query.into(self.table_abc).insert()