Module:UtilsCargo

local p = {} local h = {}

local utilsString = require("Module:UtilsString") local utilsTable = require("Module:UtilsTable")

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) values = utilsTable.map(escape)(values) values = utilsTable.map(utilsString.format("'%s'"))(values) 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