⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 describe.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 4 页
字号:
					  "  SELECT p.oid as oid, p.tableoid as tableoid,\n"					  "  n.nspname as nspname,\n"					  "  CAST(p.proname AS pg_catalog.text) as name,"					  "  CAST('%s' AS pg_catalog.text) as object\n"					  "  FROM pg_catalog.pg_proc p\n"	 "       LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n"		 "  WHERE p.prorettype <> 'pg_catalog.cstring'::pg_catalog.regtype\n"					  "      AND (p.proargtypes[0] IS NULL\n"					  "      OR   p.proargtypes[0] <> 'pg_catalog.cstring'::pg_catalog.regtype)\n"					  "      AND NOT p.proisagg\n",					  _("function"));	processNamePattern(&buf, pattern, true, false,					   "n.nspname", "p.proname", NULL,					   "pg_catalog.pg_function_is_visible(p.oid)");	/* Operator descriptions (only if operator has its own comment) */	appendPQExpBuffer(&buf,					  "UNION ALL\n"					  "  SELECT o.oid as oid, o.tableoid as tableoid,\n"					  "  n.nspname as nspname,\n"					  "  CAST(o.oprname AS pg_catalog.text) as name,"					  "  CAST('%s' AS pg_catalog.text) as object\n"					  "  FROM pg_catalog.pg_operator o\n"	"       LEFT JOIN pg_catalog.pg_namespace n ON n.oid = o.oprnamespace\n",					  _("operator"));	processNamePattern(&buf, pattern, false, false,					   "n.nspname", "o.oprname", NULL,					   "pg_catalog.pg_operator_is_visible(o.oid)");	/* Type description */	appendPQExpBuffer(&buf,					  "UNION ALL\n"					  "  SELECT t.oid as oid, t.tableoid as tableoid,\n"					  "  n.nspname as nspname,\n"					  "  pg_catalog.format_type(t.oid, NULL) as name,"					  "  CAST('%s' AS pg_catalog.text) as object\n"					  "  FROM pg_catalog.pg_type t\n"	"       LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n",					  _("data type"));	processNamePattern(&buf, pattern, false, false,					"n.nspname", "pg_catalog.format_type(t.oid, NULL)", NULL,					   "pg_catalog.pg_type_is_visible(t.oid)");	/* Relation (tables, views, indexes, sequences) descriptions */	appendPQExpBuffer(&buf,					  "UNION ALL\n"					  "  SELECT c.oid as oid, c.tableoid as tableoid,\n"					  "  n.nspname as nspname,\n"					  "  CAST(c.relname AS pg_catalog.text) as name,\n"					  "  CAST(\n"					  "    CASE c.relkind WHEN 'r' THEN '%s' WHEN 'v' THEN '%s' WHEN 'i' THEN '%s' WHEN 'S' THEN '%s' END"					  "  AS pg_catalog.text) as object\n"					  "  FROM pg_catalog.pg_class c\n"	 "       LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n"					  "  WHERE c.relkind IN ('r', 'v', 'i', 'S')\n",					  _("table"), _("view"), _("index"), _("sequence"));	processNamePattern(&buf, pattern, true, false,					   "n.nspname", "c.relname", NULL,					   "pg_catalog.pg_table_is_visible(c.oid)");	/* Rule description (ignore rules for views) */	appendPQExpBuffer(&buf,					  "UNION ALL\n"					  "  SELECT r.oid as oid, r.tableoid as tableoid,\n"					  "  n.nspname as nspname,\n"					  "  CAST(r.rulename AS pg_catalog.text) as name,"					  "  CAST('%s' AS pg_catalog.text) as object\n"					  "  FROM pg_catalog.pg_rewrite r\n"				  "       JOIN pg_catalog.pg_class c ON c.oid = r.ev_class\n"	 "       LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n"					  "  WHERE r.rulename != '_RETURN'\n",					  _("rule"));	/* XXX not sure what to do about visibility rule here? */	processNamePattern(&buf, pattern, true, false,					   "n.nspname", "r.rulename", NULL,					   "pg_catalog.pg_table_is_visible(c.oid)");	/* Trigger description */	appendPQExpBuffer(&buf,					  "UNION ALL\n"					  "  SELECT t.oid as oid, t.tableoid as tableoid,\n"					  "  n.nspname as nspname,\n"					  "  CAST(t.tgname AS pg_catalog.text) as name,"					  "  CAST('%s' AS pg_catalog.text) as object\n"					  "  FROM pg_catalog.pg_trigger t\n"				   "       JOIN pg_catalog.pg_class c ON c.oid = t.tgrelid\n"	"       LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n",					  _("trigger"));	/* XXX not sure what to do about visibility rule here? */	processNamePattern(&buf, pattern, false, false,					   "n.nspname", "t.tgname", NULL,					   "pg_catalog.pg_table_is_visible(c.oid)");	appendPQExpBuffer(&buf,					  ") AS tt\n"					  "  JOIN pg_catalog.pg_description d ON (tt.oid = d.objoid AND tt.tableoid = d.classoid AND d.objsubid = 0)\n");	appendPQExpBuffer(&buf, "ORDER BY 1, 2, 3;");	res = PSQLexec(buf.data, false);	termPQExpBuffer(&buf);	if (!res)		return false;	myopt.nullPrint = NULL;	myopt.title = _("Object descriptions");	printQuery(res, &myopt, pset.queryFout, pset.logfile);	PQclear(res);	return true;}/* * describeTableDetails (for \d) * * This routine finds the tables to be displayed, and calls * describeOneTableDetails for each one. * * verbose: if true, this is \d+ */booldescribeTableDetails(const char *pattern, bool verbose){	PQExpBufferData buf;	PGresult   *res;	int			i;	initPQExpBuffer(&buf);	printfPQExpBuffer(&buf,					  "SELECT c.oid,\n"					  "  n.nspname,\n"					  "  c.relname\n"					  "FROM pg_catalog.pg_class c\n"	 "     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n");	processNamePattern(&buf, pattern, false, false,					   "n.nspname", "c.relname", NULL,					   "pg_catalog.pg_table_is_visible(c.oid)");	appendPQExpBuffer(&buf, "ORDER BY 2, 3;");	res = PSQLexec(buf.data, false);	termPQExpBuffer(&buf);	if (!res)		return false;	if (PQntuples(res) == 0)	{		if (!QUIET())			fprintf(stderr, _("Did not find any relation named \"%s\".\n"),					pattern);		PQclear(res);		return false;	}	for (i = 0; i < PQntuples(res); i++)	{		const char *oid;		const char *nspname;		const char *relname;		oid = PQgetvalue(res, i, 0);		nspname = PQgetvalue(res, i, 1);		relname = PQgetvalue(res, i, 2);		if (!describeOneTableDetails(nspname, relname, oid, verbose))		{			PQclear(res);			return false;		}	}	PQclear(res);	return true;}/* * describeOneTableDetails (for \d) * * Unfortunately, the information presented here is so complicated that it * cannot be done in a single query. So we have to assemble the printed table * by hand and pass it to the underlying printTable() function. */static booldescribeOneTableDetails(const char *schemaname,						const char *relationname,						const char *oid,						bool verbose){	PQExpBufferData buf;	PGresult   *res = NULL;	printTableOpt myopt = pset.popt.topt;	int			i;	char	   *view_def = NULL;	const char *headers[5];	char	  **cells = NULL;	char	  **footers = NULL;	char	  **ptr;	PQExpBufferData title;	PQExpBufferData tmpbuf;	int			cols = 0;	int			numrows = 0;	struct	{		int16		checks;		int16		triggers;		char		relkind;		bool		hasindex;		bool		hasrules;		bool		hasoids;		Oid			tablespace;	}			tableinfo;	bool		show_modifiers = false;	bool		retval;	retval = false;	/* This output looks confusing in expanded mode. */	myopt.expanded = false;	initPQExpBuffer(&buf);	initPQExpBuffer(&title);	initPQExpBuffer(&tmpbuf);	/* Get general table info */	printfPQExpBuffer(&buf,	   "SELECT relhasindex, relkind, relchecks, reltriggers, relhasrules, \n"					  "relhasoids %s \n"					  "FROM pg_catalog.pg_class WHERE oid = '%s'",					  pset.sversion >= 80000 ? ", reltablespace" : "",					  oid);	res = PSQLexec(buf.data, false);	if (!res)		goto error_return;	/* Did we get anything? */	if (PQntuples(res) == 0)	{		if (!QUIET())			fprintf(stderr, _("Did not find any relation with OID %s.\n"),					oid);		goto error_return;	}	/* FIXME: check for null pointers here? */	tableinfo.checks = atoi(PQgetvalue(res, 0, 2));	tableinfo.triggers = atoi(PQgetvalue(res, 0, 3));	tableinfo.relkind = *(PQgetvalue(res, 0, 1));	tableinfo.hasindex = strcmp(PQgetvalue(res, 0, 0), "t") == 0;	tableinfo.hasrules = strcmp(PQgetvalue(res, 0, 4), "t") == 0;	tableinfo.hasoids = strcmp(PQgetvalue(res, 0, 5), "t") == 0;	tableinfo.tablespace = (pset.sversion >= 80000) ?		atooid(PQgetvalue(res, 0, 6)) : 0;	PQclear(res);	headers[0] = _("Column");	headers[1] = _("Type");	cols = 2;	if (tableinfo.relkind == 'r' || tableinfo.relkind == 'v')	{		show_modifiers = true;		cols++;		headers[cols - 1] = _("Modifiers");	}	if (verbose)	{		cols++;		headers[cols - 1] = _("Description");	}	headers[cols] = NULL;	/* Get column info (index requires additional checks) */	printfPQExpBuffer(&buf, "SELECT a.attname,");	appendPQExpBuffer(&buf, "\n  pg_catalog.format_type(a.atttypid, a.atttypmod),"					  "\n  (SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128)"					  "\n   FROM pg_catalog.pg_attrdef d"					  "\n   WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef),"					  "\n  a.attnotnull, a.attnum");	if (verbose)		appendPQExpBuffer(&buf, ", pg_catalog.col_description(a.attrelid, a.attnum)");	appendPQExpBuffer(&buf, "\nFROM pg_catalog.pg_attribute a");	if (tableinfo.relkind == 'i')		appendPQExpBuffer(&buf, ", pg_catalog.pg_index i");	appendPQExpBuffer(&buf, "\nWHERE a.attrelid = '%s' AND a.attnum > 0 AND NOT a.attisdropped", oid);	if (tableinfo.relkind == 'i')		appendPQExpBuffer(&buf, " AND a.attrelid = i.indexrelid");	appendPQExpBuffer(&buf, "\nORDER BY a.attnum");	res = PSQLexec(buf.data, false);	if (!res)		goto error_return;	numrows = PQntuples(res);	/* Check if table is a view */	if (tableinfo.relkind == 'v')	{		PGresult   *result;		printfPQExpBuffer(&buf, "SELECT pg_catalog.pg_get_viewdef('%s'::pg_catalog.oid, true)", oid);		result = PSQLexec(buf.data, false);		if (!result)			goto error_return;		if (PQntuples(result) > 0)			view_def = pg_strdup(PQgetvalue(result, 0, 0));		PQclear(result);	}	/* Generate table cells to be printed */	/* note: initialize all cells[] to NULL in case of error exit */	cells = pg_malloc_zero((numrows * cols + 1) * sizeof(*cells));	for (i = 0; i < numrows; i++)	{		/* Name */#ifdef WIN32		cells[i * cols + 0] = mbvalidate(PQgetvalue(res, i, 0), myopt.encoding);#else		cells[i * cols + 0] = PQgetvalue(res, i, 0);	/* don't free this														 * afterwards */#endif		/* Type */#ifdef WIN32		cells[i * cols + 1] = mbvalidate(PQgetvalue(res, i, 1), myopt.encoding);#else		cells[i * cols + 1] = PQgetvalue(res, i, 1);	/* don't free this														 * either */#endif		/* Extra: not null and default */		if (show_modifiers)		{			resetPQExpBuffer(&tmpbuf);			if (strcmp(PQgetvalue(res, i, 3), "t") == 0)				appendPQExpBufferStr(&tmpbuf, "not null");			/* handle "default" here */			/* (note: above we cut off the 'default' string at 128) */			if (strlen(PQgetvalue(res, i, 2)) != 0)			{				if (tmpbuf.len > 0)					appendPQExpBufferStr(&tmpbuf, " ");				appendPQExpBuffer(&tmpbuf, "default %s",								  PQgetvalue(res, i, 2));			}#ifdef WIN32			cells[i * cols + 2] = pg_strdup(mbvalidate(tmpbuf.data, myopt.encoding));#else			cells[i * cols + 2] = pg_strdup(tmpbuf.data);#endif		}		/* Description */		if (verbose)#ifdef WIN32			cells[i * cols + cols - 1] = mbvalidate(PQgetvalue(res, i, 5), myopt.encoding);#else			cells[i * cols + cols - 1] = PQgetvalue(res, i, 5);#endif	}	/* Make title */	switch (tableinfo.relkind)	{		case 'r':			printfPQExpBuffer(&title, _("Table \"%s.%s\""),							  schemaname, relationname);			break;		case 'v':			printfPQExpBuffer(&title, _("View \"%s.%s\""),							  schemaname, relationname);			break;		case 'S':			printfPQExpBuffer(&title, _("Sequence \"%s.%s\""),							  schemaname, relationname);			break;		case 'i':			printfPQExpBuffer(&title, _("Index \"%s.%s\""),							  schemaname, relationname);			break;		case 's':			printfPQExpBuffer(&title, _("Special relation \"%s.%s\""),							  schemaname, relationname);			break;		case 't':			printfPQExpBuffer(&title, _("TOAST table \"%s.%s\""),							  schemaname, relationname);			break;		case 'c':			printfPQExpBuffer(&title, _("Composite type \"%s.%s\""),							  schemaname, relationname);			break;		default:			printfPQExpBuffer(&title, _("?%c? \"%s.%s\""),							  tableinfo.relkind, schemaname, relationname);			break;	}	/* Make footers */	if (tableinfo.relkind == 'i')	{		/* Footer information about an index */		PGresult   *result;		printfPQExpBuffer(&buf,						  "SELECT i.indisunique, i.indisprimary, i.indisclustered, a.amname, c2.relname,\n"					"  pg_catalog.pg_get_expr(i.indpred, i.indrelid, true)\n"						  "FROM pg_catalog.pg_index i, pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_am a\n"		  "WHERE i.indexrelid = c.oid AND c.oid = '%s' AND c.relam = a.oid\n"						  "AND i.indrelid = c2.oid",						  oid);		result = PSQLexec(buf.data, false);		if (!result)			goto error_return;		else if (PQntuples(result) != 1)		{			PQclear(result);			goto error_return;		}		else		{			char	   *indisunique = PQgetvalue(result, 0, 0);			char	   *indisprimary = PQgetvalue(result, 0, 1);			char	   *indisclustered = PQgetvalue(result, 0, 2);			char	   *indamname = PQgetvalue(result, 0, 3);			char	   *indtable = PQgetvalue(result, 0, 4);			char	   *indpred = PQgetvalue(result, 0, 5);			int			count_footers = 0;			if (strcmp(indisprimary, "t") == 0)				printfPQExpBuffer(&tmpbuf, _("primary key, "));			else if (strcmp(indisunique, "t") == 0)				printfPQExpBuffer(&tmpbuf, _("unique, "));			else				resetPQExpBuffer(&tmpbuf);			appendPQExpBuffer(&tmpbuf, "%s, ", indamname);			/* we assume here that index and table are in same schema */			appendPQExpBuffer(&tmpbuf, _("for table \"%s.%s\""),							  schemaname, indtable);			if (strlen(indpred))				appendPQExpBuffer(&tmpbuf, _(", predicate (%s)"), indpred);			if (strcmp(indisclustered, "t") == 0)				appendPQExpBuffer(&tmpbuf, _(", clustered"));			footers = pg_malloc_zero(4 * sizeof(*footers));			footers[count_footers++] = pg_strdup(tmpbuf.data);			add_tablespace_footer(tableinfo.relkind, tableinfo.tablespace,								  footers, &count_footers, tmpbuf, true);			footers[count_footers] = NULL;		}		PQclear(result);	}	else if (view_def)	{		PGresult   *result = NULL;		int			rule_count = 0;		int			count_footers = 0;		/* count rules other than the view rule */		if (tableinfo.hasrules)		{			printfPQExpBuffer(&buf,							  "SELECT r.rulename, trim(trailing ';' from pg_catalog.pg_get_ruledef(r.oid, true))\n"							  "FROM pg_catalog.pg_rewrite r\n"			"WHERE r.ev_class = '%s' AND r.rulename != '_RETURN' ORDER BY 1",							  oid);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -