Module:CargoQuery
This module lets you get around the |no html
bug that Cargo has by avoiding |format=template.
To use, preface query arguments with q?
. Even if you are only using one table, use |q?tables=
.
You must specify the template that will handle each row of the query result using |template=
.
You may additionally specify |intro=
, |outro=
, |delimiter=
, and |default=
.
Use Lua names of all query parameters, so |q?join=
, |q?groupBy
, etc.
For simplicity of code, the named args parameter is required to be Yes, and you do not need to specify it.
Unlike |format=template
, this wrapper will NOT rename parameters with underscores in them to use spaces instead.
Parameters & Invocation
{{#invoke:CargoQuery|main
|tables= <!-- corresponds to table / tables -->
|join= <!-- corresponds to join on -->
|fields= <!-- corresponds to fields -->
|where= <!-- corresponds to where -->
|groupBy= <!-- corresponds to group by -->
|having= <!-- corresponds to having -->
|orderBy= <!-- corresponds to order by -->
|limit= <!-- corresponds to limit -->
|template= <!-- pagename of template (required). remember to name your args! -->
|intro=
|outro=
|delimiter=
|default=
}}
Additionally, if you have one-to-many data, you may specify these parameters:
|one_to_many=
|one_to_many_group=
|one_to_many_sep=,
For example, if you have many City
s for every one Kingdom
, you might supply:
|one_to_many=City
|one_to_many_group=Kingdom
|one_to_many_sep=,
And then for the Kingdom="Skyrim"
line, you'd get |City=Whiterun,Riften,...
local PARAM_LOOKUP = {
['order by'] = 'orderBy',
['join on'] = 'join',
['group by'] = 'groupBy',
table = 'tables',
}
local h = {}
local p = {}
function p.main(frame)
local args = h.merge()
args.one_to_many_sep = args.one_to_many_sep and args.one_to_many_sep:gsub('\\s', ' ') or ','
local query = {}
for k, v in pairs(args) do
if string.sub(k, 0, 2) == 'q?' then
local key = string.sub(k, 3)
query[PARAM_LOOKUP[key] or key] = v
elseif PARAM_LOOKUP[k] then
query[PARAM_LOOKUP[k]] = v
else
query[k] = v
end
end
if args.one_to_many then
query.fields = query.fields .. ',' .. query.one_to_many
end
local result = mw.ext.cargo.query(query.tables, query.fields, query)
if #result == 0 then
return frame:preprocess(args.default or '')
end
if args.one_to_many then
result = h.groupOneToManyFields(result, h.getOneToManyTableFromArgs(args))
h.concatOneToManyFieldsInEachRow(result, args.one_to_many_sep)
end
local tbl = {}
for i, row in ipairs(result) do
row.index = i
tbl[#tbl+1] = frame:expandTemplate{ title = args.template, args = row }
end
local intro = frame:preprocess(args.intro or '')
local outro = frame:preprocess(args.outro or '')
return intro .. table.concat(tbl,args.delimiter or '') .. outro
end
-- This function on Leaguepedia is part of Module:ArgsUtil but is copied here to avoid dependencies
function h.merge()
local f = mw.getCurrentFrame()
local origArgs = f.args
local parentArgs = f:getParent().args
local args = {}
for k, v in pairs(origArgs) do
v = mw.text.trim(tostring(v))
if v ~= '' then
args[k] = v
end
end
for k, v in pairs(parentArgs) do
v = mw.text.trim(v)
if v ~= '' then
args[k] = v
end
end
return args
end
function h.getOneToManyTableFromArgs(args)
local oneToMany = {
fields = mw.text.split(args.one_to_many, '%s*,%s*'),
groupBy = { args.one_to_many_group },
}
return oneToMany
end
-- These functions on Leaguepedia are part of Module:CargoUtil but are copied here to avoide dependencies
-- Some code is updated to avoid further dependencies
function h.groupOneToManyFields(result, oneToMany)
if not oneToMany then return result end
local currentKey
local groupedResult = {}
local fields = h.parseFieldsForKeys(oneToMany.fields)
for _, row in ipairs(result) do
local newKey = h.getNewKey(row, oneToMany.groupBy)
if newKey == currentKey then
h.addRowToExistingGroup(groupedResult, row, fields)
else
h.addRowToNewGroup(groupedResult, row, fields)
currentKey = newKey
end
end
return groupedResult
end
function h.parseFieldsForKeys(fields)
for i, v in ipairs(fields) do
fields[i] = h.parseOneFieldForKey(v)
end
return fields
end
function h.getNewKey(row, groupBy)
local toConcat = {}
for _, v in ipairs(groupBy) do
toConcat[#toConcat+1] = row[v]
end
return table.concat(toConcat)
end
function h.parseOneFieldForKey(str)
if not str:find('=') then return str end
return str:match('=(.+)')
end
function h.addRowToExistingGroup(groupedResult, row, fields)
for _, v in ipairs(fields) do
local parentRowValues = groupedResult[#groupedResult][v]
parentRowValues[#parentRowValues+1] = row[v]
end
end
function h.addRowToNewGroup(groupedResult, row, fields)
for _, v in ipairs(fields) do
row[v] = { row[v] }
end
groupedResult[#groupedResult+1] = row
end
function h.concatOneToManyFieldsInEachRow(result, sep)
for _, row in ipairs(result) do
for k, v in pairs(row) do
if type(v) == 'table' then
row[k] = table.concat(v, sep)
end
end
end
end
return p