Repository: tami5/sql.nvim (lua)

Issue:
table.each accept function as first arg
support table.each/map to accept function as first argument and query as second argument and vice-versa

Pull request description:
#### Purpose

closes #79

Patch:
diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml
index 1c41dbfb..8b50e673 100644
--- a/.github/workflows/changelog.yml
+++ b/.github/workflows/changelog.yml
@@ -37,8 +37,8 @@ jobs:
           COMMIT_MSG: |
             :memo: update CHANGELOG.md
         run: |
-          git config user.email "actions@github"
-          git config user.name "Actions"
+          git config --global user.name "github-actions[bot]"
+          git config --global user.email "github-actions[bot]@users.noreply.github.com"
           git remote set-url origin https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git
           git add CHANGELOG.md
           # Only commit and push if we have changes
diff --git a/.github/workflows/docgen.yml b/.github/workflows/docgen.yml
index 44d9df73..9b78a479 100644
--- a/.github/workflows/docgen.yml
+++ b/.github/workflows/docgen.yml
@@ -49,8 +49,8 @@ jobs:
           COMMIT_MSG: |
             :memo: DOC: Update doc/sql.txt
         run: |
-          git config user.email "actions@github"
-          git config user.name "Actions"
+          git config --global user.name "github-actions[bot]"
+          git config --global user.email "github-actions[bot]@users.noreply.github.com"
           git remote set-url origin https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git
           git add doc/
           # Only commit and push if we have changes
diff --git a/doc/sql.txt b/doc/sql.txt
index 3ba801c6..ee07fba4 100644
--- a/doc/sql.txt
+++ b/doc/sql.txt
@@ -519,14 +519,14 @@ tbl:where({where})                                               *tbl:where()*
         |DB:select()|
 
 
-tbl:each({query}, {func})                                         *tbl:each()*
+tbl:each({func}, {query})                                         *tbl:each()*
     Iterate over table rows and execute {func}. Returns true only when rows is
     not emtpy.
 
 
     Parameters: ~
-        {query} (table)     query.where, query.keys, query.join
         {func}  (function)  func(row)
+        {query} (table)     query.where, query.keys, query.join
 
     Return: ~
         boolean
@@ -534,16 +534,16 @@ tbl:each({query}, {func})                                         *tbl:each()*
     Usage: ~
         `let query = { where = { status = "pending"}, contains = { title =
         "fix*" } }`
-        `todos:each(query, function(row) print(row.title) end)`
+        `todos:each(function(row) print(row.title) end, query)`
 
 
-tbl:map({query}, {func})                                           *tbl:map()*
+tbl:map({func}, {query})                                           *tbl:map()*
     Create a new table from iterating over {self.name} rows with {func}.
 
 
     Parameters: ~
+        {func}  (function)  func(row)
         {query} (table)     query.where, query.keys, query.join
-        {func}  (function)  a function that expects a row
 
     Return: ~
         table[]
@@ -551,7 +551,7 @@ tbl:map({query}, {func})                                           *tbl:map()*
     Usage: ~
         `let query = { where = { status = "pending"}, contains = { title =
         "fix*" } }`
-        `local t = todos:map(query, function(row) return row.title end)`
+        `local t = todos:map(function(row) return row.title end, query)`
 
 
 tbl:sort({query}, {transform}, {comp})                            *tbl:sort()*
diff --git a/lua/sql/table.lua b/lua/sql/table.lua
index 3c9cd1ad..032b9327 100644
--- a/lua/sql/table.lua
+++ b/lua/sql/table.lua
@@ -160,13 +160,16 @@ end
 
 ---Iterate over table rows and execute {func}.
 ---Returns true only when rows is not emtpy.
----@param query table: query.where, query.keys, query.join
 ---@param func function: func(row)
+---@param query table: query.where, query.keys, query.join
 ---@usage `let query = { where = { status = "pending"}, contains = { title = "fix*" } }`
----@usage `todos:each(query, function(row)  print(row.title) end)`
+---@usage `todos:each(function(row) print(row.title) end, query)`
 ---@return boolean
-function tbl:each(query, func)
-  assert(type(func) == "function", "required a function as second params")
+function tbl:each(func, query)
+  query = query or {}
+  if type(func) == "table" then
+    func, query = query, func
+  end
 
   local rows = self.db:select(self.name, query)
   if not rows then
@@ -181,17 +184,27 @@ function tbl:each(query, func)
 end
 
 ---Create a new table from iterating over {self.name} rows with {func}.
+---@param func function: func(row)
 ---@param query table: query.where, query.keys, query.join
----@param func function: a function that expects a row
 ---@usage `let query = { where = { status = "pending"}, contains = { title = "fix*" } }`
----@usage `local t = todos:map(query, function(row) return row.title end)`
+---@usage `local t = todos:map(function(row) return row.title end, query)`
 ---@return table[]
-function tbl:map(query, func)
-  assert(type(func) == "function", "required a function as second params")
+function tbl:map(func, query)
+  query = query or {}
   local res = {}
-  self:each(query, function(row)
+  if type(func) == "table" then
+    func, query = query, func
+  end
+
+  local rows = self.db:select(self.name, query)
+  if not rows then
+    return {}
+  end
+
+  for _, row in ipairs(rows) do
     table.insert(res, func(row))
-  end)
+  end
+
   return res
 end
 


Test patch:
diff --git a/test/auto/table_spec.lua b/test/auto/table_spec.lua
index c64851bd..ba66fd84 100644
--- a/test/auto/table_spec.lua
+++ b/test/auto/table_spec.lua
@@ -164,6 +164,28 @@ describe("table", function()
       )
       eq(res, { 99, 32, 12 }, "should be identical") -- this might fail at some point because of the ordering.
     end)
+    it("supports function as first argument", function()
+      local res = {}
+      eq(
+        true,
+        t1:each(function(row)
+          table.insert(res, row.a)
+        end, { where = { a = { 12, 99, 32 } } }),
+        "the number of rows"
+      )
+      eq(res, { 99, 32, 12 }, "should be identical")
+    end)
+    it("supports function as first argument with no query", function()
+      local res = {}
+      eq(
+        true,
+        t1:each(function(row)
+          table.insert(res, row.a)
+        end),
+        "the number of rows"
+      )
+      eq(res, { 1, 99, 32, 12, 35, 4, 5 }, "should be identical")
+    end)
   end)
 
   describe(":map", function()
@@ -173,6 +195,18 @@ describe("table", function()
       end)
       eq(res, { 99, 32, 12 }, "should be identical") -- this might fail at some point because of the ordering.
     end)
+    it("support function as first argument", function()
+      local res = t1:map(function(row)
+        return row.a
+      end, { where = { a = { 12, 99, 32 } } })
+      eq(res, { 99, 32, 12 }, "should be identical") -- this might fail at some point because of the ordering.
+    end)
+    it("support function as first argument with no query", function()
+      local res = t1:map(function(row)
+        return row.a
+      end)
+      eq(res, { 1, 99, 32, 12, 35, 4, 5 }, "should be identical") -- this might fail at some point because of the ordering.
+    end)
   end)
 
   describe(":sort", function()