/* ********** * http://sourceforge.jp/projects/pgshowcreatetbl/ = show create table for PostgreSQL = * This SQL function returns a CREATE TABLE statement for the table assigned. * PostgreSQL にて CREATE TABLE 文を取得するための SQL 関数です。 PostgreSQL では pg_dump --schema-only コマンドで CREATE TABLE 文を取得できますが、 DB 接続や psql コンソールなどから取得することができません。 本 SQL は、それを実現するためのものです。 = Features = * このファンクションは、SQL文1つから構成されますので、 * PostgreSQL の設定変更なしに利用することができます。 * '''PHP, Java, Ruby 等、お好きな言語に組み込むことができます。''' * 例:1) $1, $2 を言語ごとの変数にする、2) ダブルクオーテーションをエスケープする (" -> \") * This function is written in SQL. This brings the features that: * You do not need to re-configure your PostgreSQL settings. * '''You can embed this function in your preferred languages: PHP, Java, Ruby, etc...''' * example: 1) replace $1 and $2 into variables of the language you are going to use, 2) escape the double-quotations (" -> \") = Usage = {{{ code sql SELECT show_create_table('table_name', 'schema_name'); or SELECT show_create_table('table_name', null); }}} * schema_name を null にすると、全スキーマが検索の対象になります。 * If schema_name = null, all of the schema will be searched. = Install = * psql シェルでコピー&ペーストするなどしてください。 * copy & paste in psql shell. = Available versions = * v8.3.8 * v8.3.x (probably...) * v8.x (maybe...) * 動作バージョンのご報告を頂けると有り難いです。 * If this function successfully runs on your PostgreSQL, please tell me your version! * http://sourceforge.jp/forum/forum.php?forum_id=23996 = known bugs = * see http://sourceforge.jp/projects/pgshowcreatetbl/ticket/?type[]=19647&type_mode[]=eq&status[]=1&view=type * ********** */ CREATE OR REPLACE FUNCTION show_create_table(varchar /*table*/, varchar /*schema*/) returns text as $$ /* * show create table for PostgreSQL v0.6 * 2010.9.3 Tadashi Murakami * * Bug reports are welcome: * http://sourceforge.jp/projects/pgshowcreatetbl/ * * Licensed under the Apache License, Version 2.0. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 */ SELECT CASE WHEN tb.relkind = 'r' THEN (/*0*/ SELECT 'CREATE TABLE ' || $1 || ' (' || chr(10) || array_to_string (/*1,2*/ARRAY( SELECT ' "'||"Column" ||'" '|| "Type" || "Modifiers" || "Index" FROM (/*3*/ SELECT at.attnum, ns.nspname as schema, tb.relname as table, at.attname as "Column", /* Type */ CASE WHEN at.attinhcount<>0 OR at.attisdropped THEN null ELSE CASE WHEN tp.typname = 'int2' THEN 'smallint' WHEN tp.typname = 'int4' THEN 'integer' WHEN tp.typname = 'int8' THEN 'bigint' WHEN tp.typname = 'float4' THEN 'real' WHEN tp.typname = 'float8' THEN 'double precision' WHEN tp.typname = 'bpchar' THEN 'char' ELSE tp.typname END || CASE WHEN at.attlen >= 0 THEN '' WHEN at.atttypmod < 4 THEN '' WHEN tp.typname<>'numeric' THEN '('|| at.atttypmod-4 ||')' WHEN (at.atttypmod & 65535) = 4 THEN '('|| (at.atttypmod >> 16) ||')' ELSE '('|| (at.atttypmod >> 16) ||','|| (at.atttypmod & 65535)-4 ||')' END END as "Type", /* Modifiers */ CASE WHEN at.attnotnull THEN ' not null' ELSE '' END || CASE WHEN ad.adbin IS NULL THEN '' ELSE ' default ' || pg_get_expr(ad.adbin, tb.oid) END as "Modifiers", /* one-column Index */ CASE WHEN ix.indexrelid IS NULL THEN '' ELSE CASE WHEN ix.indisprimary THEN ' PRIMARY KEY' WHEN ix.indisunique THEN ' UNIQUE' ELSE ' /* index */' END || CASE WHEN am.amname <> 'btree' THEN ' /*'||am.amname||'*/' ELSE '' END || ' /* '|| ic.relname ||' */' END as "Index" -- , tb.*, at.*, tp.* FROM pg_attribute at -- -- for Type, Modifiers -- INNER JOIN pg_type tp ON at.atttypid = tp.oid LEFT OUTER JOIN pg_attrdef ad ON ad.adrelid = tb.oid AND ad.adnum = at.attnum -- -- for one-column Index -- LEFT OUTER JOIN pg_index ix ON ix.indrelid = tb.oid AND ix.indnatts = 1 AND at.attnum = ix.indkey[0] LEFT OUTER JOIN pg_class ic ON ix.indexrelid = ic.oid LEFT OUTER JOIN pg_am am ON ic.relam = am.oid -- WHERE tb.oid = at.attrelid AND at.attnum >= 1 )/*3*/ as columns ORDER BY attnum ), ','||chr(10))/*2,1*/ -- -- -- multi-columns Index -- -- ||(/*1*/ SELECT CASE WHEN count(*) = 0 THEN '' ELSE ','||chr(10)||' '|| array_to_string (/*2,3*/ARRAY( SELECT CASE WHEN indisprimary THEN 'PRIMARY KEY ' ELSE 'UNIQUE ' END || substr(indexdef, strpos(indexdef, '('), strpos(indexdef, ')') - strpos(indexdef, '(') + 1) || ' /* '||index||' */' FROM (/*4*/ SELECT ic.relname as index, ns.nspname as schema, tb.relname as table -- , ia.attname, ia.attnum , ix.indnatts, ix.indisunique, ix.indisprimary, am.amname , ix.indkey , pg_get_indexdef(ic.oid) as indexdef -- , pg_get_expr(ix.indexprs, ix.indrelid), pg_get_expr(ix.indpred, ix.indrelid) FROM pg_index ix INNER JOIN pg_class ic ON ix.indexrelid = ic.oid INNER JOIN pg_am am ON ic.relam = am.oid -- LEFT OUTER JOIN pg_attribute ia ON ia.attnum = any(ix.indkey) AND ia.attrelid = tb.oid WHERE ix.indrelid = tb.oid AND ix.indnatts > 1 AND (ix.indisprimary OR ix.indisunique) )/*4*/ as def ORDER BY indisprimary desc, index), ','||chr(10) )/*3,2*/ END -- copy from the above conditions FROM pg_index ix WHERE ix.indrelid = tb.oid AND ix.indnatts > 1 AND (ix.indisprimary OR ix.indisunique) )/*1*/ || chr(10) || ')' )/*0*/ WHEN tb.relkind = 'v' THEN 'CREATE VIEW ' || $1 || ' AS (' || chr(10) || trim(trailing ';' from pg_get_viewdef(tb.oid)) || chr(10) || ')' ELSE '/* pg_class.relkind='''||tb.relkind||''' */' END as show_create_table FROM pg_class tb INNER JOIN pg_namespace ns ON tb.relnamespace = ns.oid WHERE tb.relname = $1 AND (/*0*/ ($2 IS NOT NULL AND ns.nspname = $2) OR (/*1,2*/$2 IS NULL AND ns.nspname = ( SELECT ns.nspname -- FROM pg_class tb, pg_namespace ns -- WHERE tb.relname = $1 -- AND tb.relnamespace = ns.oid WHERE strpos(replace(current_setting('search_path'), '"$user"', current_user), ns.nspname) = (/*3*/ SELECT MIN(strpos(replace(current_setting('search_path'), '"$user"', current_user), ns2.nspname)) FROM pg_class tb2, pg_namespace ns2 WHERE tb2.relname = $1 AND tb2.relnamespace = ns2.oid )/*3*/ ))/*2,1*/ )/*0*/ $$ language sql;