Module:UtilsCargo

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

function p.allOf(...) local query for i, v in ipairs({...}) do		if type(v) == "table" then for k, v in pairs(v) do				v = string.gsub(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 = string.gsub(value, "'", "\\'") query = h.orClause(query, string.format("%s HOLDS '%s'", field, value)) end return query 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" }, }	} }

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, },				},				expected = { { initialism = "TLoZ", subtitle = "The Legend of Zelda"}, { initialism = "TAoL", subtitle = "The Adventure of Link"}, { initialism = "ALttP", subtitle = "A Link to the Past"}, },			},		}	},	{		name = "allOf", outputOnly = true, params = {"..."}, cases = { {				args = { {						game = "Link's Awakening", remakeNum = 2, },					"foo HOLDS 'bar'", "baz LIKE '%quux%'", },				expected = remakeNum='2' AND game='Link\'s Awakening' AND foo HOLDS 'bar' AND baz LIKE '%quux%' }		},	},	{		name = "holdsAny", outputOnly = true, params = {"field", "values"}, returns = "A query string of or'ed HOLDS clauses.", cases = { {				args = {"game", {"Link's Awakening"}}, expected = "game HOLDS 'Link\\'s Awakening'", },			{				args = {"game", {"OoT", "TP"}}, expected = "game HOLDS 'OoT' OR game HOLDS 'TP'", }		}	} }

return p