Module:CommonData/Join

-- CommonData

local function bit_band(a, b)   local _floor = math.floor local result = 0 local bitval = 1 while a > 0 and b > 0 do     if a % 2 == 1 and b % 2 == 1 then result = result + bitval end bitval = bitval * 2 a = _floor(a / 2) b = _floor(b / 2) end return result end

-- bor, bxor, band = 1, 3, 4 local function _bit(oper, a, b)  local result, bitval, s = 0, 2147483648 --2^31 repeat s,a,b = a + b + bitval, a % bitval, b % bitval result = result + bitval * oper % (s-a-b) bitval = bitval / 2 until bitval < 1 return result end

local p = {}

-- get one value from a row matching the querry local function GetSingleValueByName(frame) local args = frame.args local p1,p2,p3,p4 = args[1],args[2],args[3],args[4] local tableModule = require('Module:CommonData/' .. p1) local cols = tableModule.GetRawColumns(frame) local rows = tableModule.GetRawTable(frame) local colsR = {} for i,v in ipairs(cols) do       colsR[v] = i    end local key,keyColIndex,result = p3, colsR[p2], "" while rows do       for _,v in pairs(rows) do            local value = tostring(v[keyColIndex]) if value == key then result = v[colsR[p4]]; break end end rows = tableModule.GetNextRawTable(frame, rows) end if (not result or result == "") and args.default and args.default ~= "" then result = frame:preprocess(args.default) end

return result end

local function dummy end

local function band(frame, value, flags) value, flags = tonumber(value) or 0, tonumber(flags) or 0 return bit_band(value, flags) end

local function AnyFlag(frame, value, flags) value = band(frame, value, flags) return value ~= 0 and value or nil end

p["&"] = band p["&~"] = AnyFlag

-- process wiki code per row matching the query local function GetTranscludeEachRowJoin(frame, limit) local args, has = frame.args local data, code, vars, sorts, istable, source = args[1], args.wiki, args.vars, args.sort, args.istable, args.source

code = code and code ~= "" and code or nil istable = istable and istable ~= "" and istable or nil source = tonumber(source) or 0

limit = limit or tonumber(args.limit) or 8000 limit = limit ~= 0 and limit or nil vars = vars and vars ~= "" and (","..vars..",") or nil sorts = sorts and sorts ~= "" and (sorts..",") or nil

local tableModule = require('Module:CommonData/' .. data) local cols = tableModule.GetRawColumns(frame) local rows = tableModule.GetRawTable(frame)

if code then code = mw.text.unstripNoWiki(code) -- go ahead and remove the nowiki end if code and istable then               -- table or alternate other markup code = code :gsub("@([^#^%s^!^@]+)@", "<%1>")-- unescape any wraped tags :gsub("@!([^@]+)@!", "@%1@")   -- unescape next tag layer :gsub("%^%^", "@##@")          -- escape our table markup :gsub("%^([%s%{%}%-%+])", "@#%1@")-- escape our table markup end local colsR, colsCode = {}, {}         -- reverse cols and cols in code local colsVar = {}                     -- compiled var define start local expsCode = {}                    -- exps colId, cmd, arg, expsVar for i,v in ipairs(cols) do       local found = false colsR[v] = i       if code and code:find(v) then if code:find("{{#var:[!]?"..v.."[}|]") then found = true colsCode[#colsCode + 1] = i               colsVar[#colsCode] = '{{#vardefine:'..v..'|' end for k2,v2,y2 in code:gmatch("{{#var:[!]?("..v.."%s*([&^][~]?)%s*(%w+))[}|]") do               expsCode[#expsCode + 1] = { i, v2, y2, '{{#vardefine:'..k2..'|' } end end if not found and vars and vars:find(v) and vars:find(","..v..",") then colsCode[#colsCode + 1] = i           colsVar[#colsCode] = '{{#vardefine:'..v..'|' end end

local keyIds,keyVals,count = {}, {}, 0 -- make list of lookup fields for i = 2,10,2 do       local key = args[i] if not key or key == "" then break end

local keyId = colsR[key] if not keyId then return "Bad field \"'"..key.."\"" end count = count + 1 keyIds[count], keyVals[count] = keyId, args[i + 1] or "" end

if sorts then local t = {}; count = 0 while rows do           for _,v in pairs(rows) do                local found, value = true, nil for i3,v3 in ipairs(keyIds) do                   value = tostring(v[v3]) or "" if value ~= keyVals[i3] then found = false; break end end if found then count = count + 1 t[count] = v                   if limit and count >= limit then limit = -1; break end end end rows = limit ~= -1 and tableModule.GetNextRawTable(frame, rows) or nil end rows = t

for v in sorts:gmatch("([^,]+),") do           local i = colsR[v] has = has or "" for k2,v2 in pairs(colsR) do               has = has .. (tostring(k2) or "") .. "," .. (tostring(v2) or "") .. "& "            end return has --.. "found" .. (v or "bo") .. " " .. (i or "bo") --if i then               table.sort(rows, function(b,a) return                    (tonumber(a[i]) or 0) < (tonumber(b[i]) or 0)                    or (tostring(a[i]) or "") < (tostring(b[i]) or "") end)                return "found"            end end end

local result,resulti = {}, 0 count = 0 while rows do       for _,v in ipairs(rows) do            local found, value = true, nil if not sorts then for i3,v3 in ipairs(keyIds) do                   value = tostring(v[v3]) or "" if value ~= keyVals[i3] then found = false; break end end end if found then for _,v2 in pairs(expsCode) do -- add exps value = (p[v2[2]] or dummy)(frame, v[v2[1]], v2[3]) value = value and tostring(value) or "" resulti = resulti + 1 result[resulti] = v2[4] .. value .. '}}'               end for i2,v2 in pairs(colsCode) do -- add cols value = v[v2] value = value and tostring(value) or "" resulti = resulti + 1 result[resulti] = colsVar[i2] .. value .. '}}'               end if code then                  -- add code resulti = resulti + 1 result[resulti] = code end

if not sorts then count = count + 1 if limit and count >= limit then limit = -1; break end end end end rows = not sorts or limit ~= -1 and tableModule.GetNextRawTable(frame, rows) or nil end keyIds,keyVals,colsR,colsCode,colsVar,expsCode,cols,rows,sorts = nil

result = resulti > 0 and table.concat(result) or ""

if result ~= "" and (code or source == 0) and source < 2 then result = frame:preprocess(result) or "" end if result == "" then result = mw.text.unstripNoWiki(args.default or "") or "" result = frame:preprocess(result) or "" end

if code and istable then result = result :gsub("@##@", "||") :gsub("@# @", "| ") :gsub("@#%+@", "\n|") :gsub("@#%-@", "\n|-") :gsub("@#%{@", "\n{|") :gsub("@#%}@", "\n|}") end if source > 0 then result = " 2 and           " style=\"white-space:pre-wrap;\"" or "")..">"..result.." " end

return result end

-- CommonData function p.GetValue(frame) return GetSingleValueByName(frame) end

function p.GetJoin(frame) return GetTranscludeEachRowJoin(frame) end

return p