Skip to content

[WIP] Bind function-like string when inserting data #159

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
lua 5.3.6
9 changes: 5 additions & 4 deletions lua/sqlite/parser.lua
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,8 @@ local pvalues = function(defs, kv)

local keys = {}
for k, v in u.opairs(defs) do
if type(v) == "string" and v:match "^[%S]+%(.*%)$" then
tinsert(keys, v)
if type(v) == "function" then
tinsert(keys, v())
else
tinsert(keys, ":" .. k)
end
Expand Down Expand Up @@ -270,7 +270,8 @@ local pselect = function(select)
if type(k) == "number" then
tinsert(items, v)
else
tinsert(items, ("%s as %s"):format(v, k))
local z = type(v) == "function" and v() or v
tinsert(items, ("%s as %s"):format(z, k))
end
end

Expand Down Expand Up @@ -346,7 +347,7 @@ local opts_to_str = function(tbl)
end
end,
default = function(v)
v = (type(v) == "string" and v:match "^[%S]+%(.*%)$") and "(" .. tostring(v) .. ")" or v
v = type(v) == "function" and "(" .. tostring(v()) .. ")" or v
local str = "default "
if tbl["required"] then
return "on conflict replace " .. str .. v
Expand Down
2 changes: 1 addition & 1 deletion lua/sqlite/stmt.lua
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ function sqlstmt:bind(...)

for k, v in pairs(names) do
local index = parameter_index_cache[k] or table.remove(anon_indices, 1)
if ((type(v) == "string" and v:match "^[%S]+%(.*%)$") and flags.ok or self:bind(index, v)) ~= flags.ok then
if ((type(v) == "function") and flags.ok or self:bind(index, v)) ~= flags.ok then
error("sqlite.lua error at stmt:bind(), failed to bind a given value '%s'. Please report issue."):format(v)
end
end
Expand Down
8 changes: 7 additions & 1 deletion lua/sqlite/strfun.lua
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ end
---@usage `sqlstrftime('%s','now') - strftime('%s','2014-10-07 02:34:56')` -> 2110042
M.strftime = function(format, timestring)
local str = [[strftime('%s', %s)]]
return customstr(str:format(format, ts(timestring)))
return M.fn(str:format(format, ts(timestring)))
end

---Return the number of days since noon in Greenwich on November 24, 4714 B.C.
Expand Down Expand Up @@ -132,4 +132,10 @@ M.cast = function(source, as)
return string.format("cast(%s as %s)", source, as)
end

M.fn = function(s)
return function()
return s
end
end

return M
11 changes: 7 additions & 4 deletions test/auto/db_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,10 @@ describe("sqlite.db", function()

it("evaluates sqlite functions", function()
db:eval "create table testa(id integer primary key, date text, title text)"
db:insert("testa", { title = "fd", date = db.lib.strftime "%H:%M:%S" })
db:insert("testa", {
title = "fd",
date = db.lib.strftime "%H:%M:%S",
})

local res = db:eval [[select * from testa]]
eq(os.date "!%H:%M:%S", res[1].date)
Expand Down Expand Up @@ -546,9 +549,9 @@ describe("sqlite.db", function()
end)

describe(":select", function()
if vim.fn.executable("curl") then
pending("'curl' program is not available")
return
if vim.fn.executable "curl" then
pending "'curl' program is not available"
return
end
local db = sql:open(path)
local posts, users
Expand Down
17 changes: 16 additions & 1 deletion test/auto/parser_spec.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
local p = require "sqlite.parser"
local fn = require("sqlite.strfun").fn
local eq = assert.are.same

describe("parse", function()
Expand All @@ -8,7 +9,7 @@ describe("parse", function()
eq(
"insert into todo (date, id) values(date('now'), :id)",
p.insert(tbl, { values = {
date = "date('now')",
date = fn "date('now')",
id = 1,
} })
)
Expand Down Expand Up @@ -257,6 +258,20 @@ describe("parse", function()
end)
end)

describe("[select]", function()
it('works with [select] = "a single string"', function()
local defs = {
select = {
"id",
z = fn "date('now')",
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this is now the only way to execute something as sql?. 🤔 I don't mind it

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you use bindings - yes. But you can always use raw: insert date('now') into ....

},
}
local expected = "select id, date('now') as z from people"
local passed = p.select("people", defs)
eq(expected, passed, "should be identical")
end)
end)

describe("[order by]", function()
it("works with signle table name", function()
local defs = {
Expand Down