PhantomCaleb (talk | contribs) mNo edit summary |
PhantomCaleb (talk | contribs) No edit summary |
||
Line 1: | Line 1: | ||
local p = {} |
local p = {} |
||
local h = {} |
local h = {} |
||
− | |||
− | local utilsString = require("Module:UtilsString") |
||
− | local utilsTable = require("Module:UtilsTable") |
||
local frame = mw.getCurrentFrame() |
local frame = mw.getCurrentFrame() |
||
Line 54: | Line 51: | ||
function p.IN(field, values) |
function p.IN(field, values) |
||
− | + | for i, value in ipairs(values) do |
|
+ | value = escape(value) |
||
− | values = utilsTable.map(utilsString.format("'%s'"))(values) |
||
+ | value = string.format("'%s'", value) |
||
+ | values[i] = value |
||
+ | end |
||
values = table.concat(values, ", ") |
values = table.concat(values, ", ") |
||
if values == "" then |
if values == "" then |
Revision as of 20:19, 10 April 2020
This module is a wrapper over mw.ext.cargo
. It also provides utilities for constructing queries.
Using this module instead of using mw.ext.cargo directly allows us to see via Special:WhatLinksHere what pages are running Cargo queries.
local p = {}
local h = {}
local frame = mw.getCurrentFrame()
function p.declare(cargoTable, fields)
return frame:callParserFunction{
name = '#cargo_declare:_table=' .. cargoTable,
args = fields
}
end
function p.store(cargoTable, fields)
frame:callParserFunction{
name = '#cargo_store:_table=' .. cargoTable,
args = fields
}
end
function p.query(tables, fields, args)
return mw.ext.cargo.query(tables, fields, args)
end
local function escape(str)
return string.gsub(str, "'", "\\'")
end
function p.allOf(...)
local query
for i, v in ipairs({...}) do
if type(v) == "table" then
for k, v in pairs(v) do
v = escape(v)
query = h.andClause(query, string.format("%s='%s'", k, v))
end
else
query = h.andClause(query, v)
end
end
return query
end
function p.holdsAny(field, values)
local query
for i, value in ipairs(values) do
value = escape(value)
query = h.orClause(query, string.format("%s HOLDS '%s'", field, value))
end
return query
end
function p.IN(field, values)
for i, value in ipairs(values) do
value = escape(value)
value = string.format("'%s'", value)
values[i] = value
end
values = table.concat(values, ", ")
if values == "" then
values = "''"
end
return string.format("%s IN (%s)", field, values)
end
function h.andClause(query, clause)
return h.addClause("AND", query, clause)
end
function h.orClause(query, clause)
return h.addClause("OR", query, clause)
end
function h.addClause(operator, query, clause)
if not query or query == "" then
return clause
end
return table.concat({query, operator, clause}, " ")
end
p.Schemas = {
declare = {
tableName = {
type = "string",
required = true,
},
fields = {
type = "map",
required = true,
keys = { type = "string" },
values = { type = "string" },
},
},
store = {
tableName = {
type = "string",
required = true,
},
fields = {
type = "map",
required = true,
keys = { type = "string" },
values = { type = "string" },
},
},
query = {
tables = {
type = "string",
required = true,
},
fields = {
type = "string",
required = true,
},
args = {
type = "record",
properties = {
{
name = "where",
type = "string",
},
{
name = "join",
type = "string",
},
{
name = "groupBy",
type = "string",
},
{
name = "having",
type = "string",
},
{
name = "orderBy",
type = "string",
},
{
name = "limit",
type = "number",
default = 100,
},
{
name = "offset",
type = "number",
default = 0,
},
}
},
},
allOf = {
["..."] = {
type = "array",
required = true,
items = {
oneOf = {
{
type = "string",
},
{
type = "map",
keys = { type = "string" },
values = { type = "string" },
},
},
}
},
},
holdsAny = {
field = {
type = "string",
required = true,
},
values = {
type = "array",
required = true,
items = { type = "string" },
}
},
IN = {
field = {
type = "string",
required = true,
},
values = {
type = "array",
required = true,
items = { type = "string" },
},
}
}
p.Documentation = {
{
name = "declare",
params = {"tableName", "fields"},
},
{
name = "store",
params = {"tableName", "fields"},
},
{
name = "query",
params = {"tables", "fields", "args"},
returns = "An array of the query results. Throws an error when query syntax is invalid.",
cases = {
{
args = {
"Games",
"initialism, subtitle",
{
where = "type='main' AND mainrelease !=''",
orderBy = "mainrelease",
limit = 3,
},
},
expect = {
{ initialism = "TLoZ", subtitle = "The Legend of Zelda"},
{ initialism = "TAoL", subtitle = "The Adventure of Link"},
{ initialism = "ALttP", subtitle = "A Link to the Past"},
},
},
}
},
{
name = "allOf",
params = {"..."},
returns = "A WHERE clause with ANDed conditions and escaped quotation marks.",
cases = {
outputOnly = true,
{
args = {
{
game = "Link's Awakening",
remakeNum = 2,
},
"foo HOLDS 'bar'",
"baz LIKE '%quux%'",
},
expect = [[remakeNum='2' AND game='Link\'s Awakening' AND foo HOLDS 'bar' AND baz LIKE '%quux%']]
}
},
},
{
name = "holdsAny",
params = {"field", "values"},
returns = "A query string of or'ed HOLDS clauses.",
cases = {
outputOnly = true,
{
args = {"game", {"Link's Awakening"}},
expect = "game HOLDS 'Link\\'s Awakening'",
},
{
args = {"game", {"OoT", "TP"}},
expect = "game HOLDS 'OoT' OR game HOLDS 'TP'",
}
}
},
{
name = "IN",
params = {"field", "values"},
returns = "A where clause using the SQL IN keyword.",
cases = {
outputOnly = true,
{
args = {"_pageName", {"Link's Shadow", "Zelda", "Ganon"}},
expect = [[_pageName IN ('Link\'s Shadow', 'Zelda', 'Ganon')]],
},
{
args = {"_pageName", {}},
expect = [[_pageName IN ('')]],
}
}
}
}
return p