Module:SchemaDiagram

--[[ Example for debug console:

mw.logObject( p._parse_sql( [===[ CREATE TABLE /*_*/user ( user_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,  user_name varchar(255) binary NOT NULL default ,  user_real_name varchar(255) binary NOT NULL default ,  user_password tinyblob NOT NULL,  user_newpassword tinyblob NOT NULL,  user_newpass_time binary(14),  user_email tinytext NOT NULL,  user_touched binary(14) NOT NULL default ,  user_token binary(32) NOT NULL default ,  user_email_authenticated binary(14),  user_email_token binary(32),  user_email_token_expires binary(14),  user_registration binary(14),  user_editcount int,  user_password_expires varbinary(14) DEFAULT NULL

) /*$wgDBTableOptions*/; ]===] ) )

]]

-- For MediaWiki 1.37 and later function parse_json(tables_json) local parsed_tables = {}

local map_field_types = { integer = "INT", mwtinyint = "TINYINT" }	function format_field_type(column_v) type = map_field_types[column_v.type] or string.upper( column_v.type ) if type == "MWENUM" then return "ENUM(…)" end if type == "MWTIMESTAMP" then return type end if column_v.options and column_v.options.length and column_v.options.length < 9999 then type = type .. '(' .. column_v.options.length .. ')' end return type end

for table_i, table_v in ipairs( tables_json ) do		local current = { table_name = table_v.name, -- For each field, the object can have keys: -- * Required 'type' -- * Optional: 'primary', 'nullable' table_fields = {} }		for column_i, column_v in ipairs( table_v.columns ) do			local field_name = column_v.name local field_attribs = {} field_attribs.type = format_field_type( column_v ) if column_v.options and column_v.options.notnull then field_attribs.nullable = false end if table_v.pk and #table_v.pk == 1 and table_v.pk[1] == field_name then field_attribs.primary = true end

table.insert( current.table_fields, {				name = field_name,				attribs = field_attribs,			} ) end if ( current.table_name ) then -- mw.log( "completed table: " .. current.table_name ) -- mw.logObject( current.table_fields ) parsed_tables[current.table_name] = current.table_fields end end return parsed_tables end

-- For MediaWiki 1.36 and earlier, -- where tables where not yet completely generated via JSON. function parse_sql(sql) local legal_states = { root = { create = true, root = true, },		create = { create = true, create_table = true, root = true, },		create_table = { create_table = true, table_field_start = true, },		table_field_start = { table_field_type = true, table_field_start = true, create = true, create_table_goto_semi = true, },		table_field_type = { table_field_attrib = true, table_field_goto_closeparen = true, },		table_field_goto_closeparen = { table_field_goto_closeparen = true, table_field_attrib = true, },		table_field_attrib = { table_field_attrib_not = true, table_field_attrib = true, table_field_start = true, create = true, },		table_field_attrib_not = { table_field_attrib = true, },		create_table_goto_semi = { create_table_goto_semi = true, root = true, },	}	local state = "root"

local parsed_tables = {} local parsed_current = { table_name = nil, table_fields = nil, field_name = nil, -- Required keys: 'type' -- Optional keys: 'primary', 'nullable'. field_attribs = nil }

-- Inspired by http://lua-users.org/wiki/SwitchStatement local parser = { -- outer-most state ["root"] = function (token) if token == "CREATE" then return "create" end

-- ignore anything else return "root" end, -- seen "CREATE" ["create"] = function (token) -- expect "TABLE" for "CREATE TABLE" if token == "TABLE" then return "create_table" end -- expect ";" (end of CREATE statement) if token == ";" then record_table_commit_maybe return "root" end -- expect top-level "INDEX" for "CREATE INDEX" (ignored) -- expect top-level "UNIQUE" for "CREATE UNIQUE INDEX" (ignored) -- expect "/*$wgDBTableOptions*/" (ignored) return "create" end, -- seen "CREATE TABLE" ["create_table"] = function (token) -- expect "/*_*/ '			.. ' '	end

if credit_line then result_html = result_html .. '' .. frame:preprocess( 'Credit: ' .. credit_line .. ' From ' ) .. ' '	end

-- Close the diagram element (flexbox) result_html = result_html .. ' '

if warn_incomplete_layout then for table_name, table_fields in pairs( parsed_tables ) do			if not shown_table_names[table_name] then mw.log( "table not in layout: " .. table_name ) mw.addWarning( "Database table '" .. table_name .. "' is not in the current layout." ) end end end

return result_html end

p._parse_sql = parse_sql

return p