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

📄 analyze.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 3 页
字号:
 *	so that the generated names are easily predictable by a person. */static char *makeObjectName(char *name1, char *name2, char *typename){	char	   *name;	int			overhead = 0;	/* chars needed for type and underscores */	int			availchars;		/* chars available for name(s) */	int			name1chars;		/* chars allocated to name1 */	int			name2chars;		/* chars allocated to name2 */	int			ndx;	name1chars = strlen(name1);	if (name2)	{		name2chars = strlen(name2);		overhead++;				/* allow for separating underscore */	}	else		name2chars = 0;	if (typename)		overhead += strlen(typename) + 1;	availchars = NAMEDATALEN-1 - overhead;	/* If we must truncate,  preferentially truncate the longer name.	 * This logic could be expressed without a loop, but it's simple and	 * obvious as a loop.	 */	while (name1chars + name2chars > availchars)	{		if (name1chars > name2chars)			name1chars--;		else			name2chars--;	}	/* Now construct the string using the chosen lengths */	name = palloc(name1chars + name2chars + overhead + 1);	strncpy(name, name1, name1chars);	ndx = name1chars;	if (name2)	{		name[ndx++] = '_';		strncpy(name+ndx, name2, name2chars);		ndx += name2chars;	}	if (typename)	{		name[ndx++] = '_';		strcpy(name+ndx, typename);	}	else		name[ndx] = '\0';	return name;}static char *CreateIndexName(char *table_name, char *column_name, char *label, List *indices){	int			pass = 0;	char	   *iname = NULL;	List	   *ilist;	char		typename[NAMEDATALEN];	/* The type name for makeObjectName is label, or labelN if that's	 * necessary to prevent collisions among multiple indexes for the same	 * table.  Note there is no check for collisions with already-existing	 * indexes; this ought to be rethought someday.	 */	strcpy(typename, label);	for (;;)	{		iname = makeObjectName(table_name, column_name, typename);		foreach(ilist, indices)		{			IndexStmt  *index = lfirst(ilist);			if (strcasecmp(iname, index->idxname) == 0)				break;		}		/* ran through entire list? then no name conflict found so done */		if (ilist == NIL)			break;		/* the last one conflicted, so try a new name component */		pfree(iname);		sprintf(typename, "%s%d", label, ++pass);	}	return iname;}/* * transformCreateStmt - *	  transforms the "create table" statement *	  SQL92 allows constraints to be scattered all over, so thumb through *	   the columns and collect all constraints into one place. *	  If there are any implied indices (e.g. UNIQUE or PRIMARY KEY) *	   then expand those into multiple IndexStmt blocks. *	  - thomas 1997-12-02 */static Query *transformCreateStmt(ParseState *pstate, CreateStmt *stmt){	Query	   *q;	List	   *elements;	Node	   *element;	List	   *columns;	List	   *dlist;	ColumnDef  *column;	List	   *constraints,			   *clist;	Constraint *constraint;	List	   *keys;	Ident	   *key;	List	   *blist = NIL;	/* "before list" of things to do before								 * creating the table */	List	   *ilist = NIL;	/* "index list" of things to do after								 * creating the table */	IndexStmt  *index,			   *pkey = NULL;	IndexElem  *iparam;	q = makeNode(Query);	q->commandType = CMD_UTILITY;	elements = stmt->tableElts;	constraints = stmt->constraints;	columns = NIL;	dlist = NIL;	/*	 * Run through each primary element in the table creation clause	 */	while (elements != NIL)	{		element = lfirst(elements);		switch (nodeTag(element))		{			case T_ColumnDef:				column = (ColumnDef *) element;				columns = lappend(columns, column);				/* Special case SERIAL type? */				if (column->is_sequence)				{					char	   *sname;					char	   *cstring;					CreateSeqStmt *sequence;					sname = makeObjectName(stmt->relname, column->colname,										   "seq");					constraint = makeNode(Constraint);					constraint->contype = CONSTR_DEFAULT;					constraint->name = sname;					cstring = palloc(10 + strlen(constraint->name) + 3 + 1);					strcpy(cstring, "nextval('\"");					strcat(cstring, constraint->name);					strcat(cstring, "\"')");					constraint->def = cstring;					constraint->keys = NULL;					column->constraints = lappend(column->constraints, constraint);					constraint = makeNode(Constraint);					constraint->contype = CONSTR_UNIQUE;					constraint->name = makeObjectName(stmt->relname,													  column->colname,													  "key");					column->constraints = lappend(column->constraints, constraint);					sequence = makeNode(CreateSeqStmt);					sequence->seqname = pstrdup(sname);					sequence->options = NIL;					elog(NOTICE, "CREATE TABLE will create implicit sequence '%s' for SERIAL column '%s.%s'",					  sequence->seqname, stmt->relname, column->colname);					blist = lcons(sequence, NIL);				}				/* Check for column constraints, if any... */				if (column->constraints != NIL)				{					clist = column->constraints;					while (clist != NIL)					{						constraint = lfirst(clist);						switch (constraint->contype)						{							case CONSTR_NULL:								/*								 * We should mark this explicitly, so we								 * can tell if NULL and NOT NULL are both								 * specified								 */								if (column->is_not_null)									elog(ERROR, "CREATE TABLE/(NOT) NULL conflicting declaration"										 " for '%s.%s'", stmt->relname, column->colname);								column->is_not_null = FALSE;								break;							case CONSTR_NOTNULL:								if (column->is_not_null)									elog(ERROR, "CREATE TABLE/NOT NULL already specified"										 " for '%s.%s'", stmt->relname, column->colname);								column->is_not_null = TRUE;								break;							case CONSTR_DEFAULT:								if (column->defval != NULL)									elog(ERROR, "CREATE TABLE/DEFAULT multiple values specified"										 " for '%s.%s'", stmt->relname, column->colname);								column->defval = constraint->def;								break;							case CONSTR_PRIMARY:								if (constraint->name == NULL)									constraint->name = makeObjectName(stmt->relname, NULL, "pkey");								if (constraint->keys == NIL)									constraint->keys = lappend(constraint->keys, column);								dlist = lappend(dlist, constraint);								break;							case CONSTR_UNIQUE:								if (constraint->name == NULL)									constraint->name = makeObjectName(stmt->relname, column->colname, "key");								if (constraint->keys == NIL)									constraint->keys = lappend(constraint->keys, column);								dlist = lappend(dlist, constraint);								break;							case CONSTR_CHECK:								constraints = lappend(constraints, constraint);								if (constraint->name == NULL)									constraint->name = makeObjectName(stmt->relname, column->colname, NULL);								break;							default:								elog(ERROR, "parser: unrecognized constraint (internal error)", NULL);								break;						}						clist = lnext(clist);					}				}				break;			case T_Constraint:				constraint = (Constraint *) element;				switch (constraint->contype)				{					case CONSTR_PRIMARY:						if (constraint->name == NULL)							constraint->name = makeObjectName(stmt->relname, NULL, "pkey");						dlist = lappend(dlist, constraint);						break;					case CONSTR_UNIQUE:						dlist = lappend(dlist, constraint);						break;					case CONSTR_CHECK:						constraints = lappend(constraints, constraint);						break;					case CONSTR_NOTNULL:					case CONSTR_DEFAULT:						elog(ERROR, "parser: illegal context for constraint (internal error)", NULL);						break;					default:						elog(ERROR, "parser: unrecognized constraint (internal error)", NULL);						break;				}				break;			default:				elog(ERROR, "parser: unrecognized node (internal error)", NULL);		}		elements = lnext(elements);	}	stmt->tableElts = columns;	stmt->constraints = constraints;/* Now run through the "deferred list" to complete the query transformation. * For PRIMARY KEYs, mark each column as NOT NULL and create an index. * For UNIQUE, create an index as for PRIMARY KEYS, but do not insist on NOT NULL. * * Note that this code does not currently look for all possible redundant cases *	and either ignore or stop with warning. The create might fail later when *	names for indices turn out to be duplicated, or a user might have specified *	extra useless indices which might hurt performance. - thomas 1997-12-08 */	while (dlist != NIL)	{		constraint = lfirst(dlist);		Assert(nodeTag(constraint) == T_Constraint);		Assert((constraint->contype == CONSTR_PRIMARY)			   || (constraint->contype == CONSTR_UNIQUE));		index = makeNode(IndexStmt);		index->unique = TRUE;		index->primary = (constraint->contype == CONSTR_PRIMARY ? TRUE : FALSE);		if (index->primary)		{			if (pkey != NULL)				elog(ERROR, "CREATE TABLE/PRIMARY KEY multiple primary keys"					 " for table '%s' are not allowed", stmt->relname);			pkey = (IndexStmt *) index;		}		if (constraint->name != NULL)			index->idxname = pstrdup(constraint->name);		else if (constraint->contype == CONSTR_PRIMARY)			index->idxname = makeObjectName(stmt->relname, NULL, "pkey");		else			index->idxname = NULL;		index->relname = stmt->relname;		index->accessMethod = "btree";		index->indexParams = NIL;		index->withClause = NIL;		index->whereClause = NULL;		keys = constraint->keys;		while (keys != NIL)		{			key = lfirst(keys);			columns = stmt->tableElts;			column = NULL;			while (columns != NIL)			{				column = lfirst(columns);				if (strcasecmp(column->colname, key->name) == 0)					break;				else					column = NULL;				columns = lnext(columns);			}			if (column == NULL)				elog(ERROR, "CREATE TABLE column '%s' in key does not exist", key->name);			if (constraint->contype == CONSTR_PRIMARY)				column->is_not_null = TRUE;			iparam = makeNode(IndexElem);			iparam->name = pstrdup(column->colname);			iparam->args = NIL;			iparam->class = NULL;			iparam->typename = NULL;			index->indexParams = lappend(index->indexParams, iparam);			if (index->idxname == NULL)				index->idxname = CreateIndexName(stmt->relname, iparam->name, "key", ilist);			keys = lnext(keys);		}		if (index->idxname == NULL)	/* should not happen */			elog(ERROR, "CREATE TABLE: failed to make implicit index name");		ilist = lappend(ilist, index);		dlist = lnext(dlist);	}/* OK, now finally, if there is a primary key, then make sure that there aren't any redundant * unique indices defined on columns. This can arise if someone specifies UNIQUE explicitly * or if a SERIAL column was defined along with a table PRIMARY KEY constraint. * - thomas 1999-05-11 */	if (pkey != NULL)	{		dlist = ilist;		ilist = NIL;		while (dlist != NIL)		{			List *pcols, *icols;			int plen, ilen;			int	keep = TRUE;			index = lfirst(dlist);			pcols = pkey->indexParams;			icols = index->indexParams;			plen = length(pcols);			ilen = length(icols);			/* Not the same as the primary key? Then we should look... */			if ((index != pkey) && (ilen == plen))			{				keep = FALSE;				while ((pcols != NIL) && (icols != NIL))				{					IndexElem *pcol = lfirst(pcols);					IndexElem *icol = lfirst(icols);					char *pname = pcol->name;					char *iname = icol->name;					/* different names? then no match... */					if (strcmp(iname, pname) != 0)					{						keep = TRUE;						break;					}					pcols = lnext(pcols);					icols = lnext(icols);				}			}			if (keep)				ilist = lappend(ilist, index);			dlist = lnext(dlist);		}	}	dlist = ilist;	while (dlist != NIL)	{		index = lfirst(dlist);		elog(NOTICE, "CREATE TABLE/%s will create implicit index '%s' for table '%s'",			 (index->primary ? "PRIMARY KEY" : "UNIQUE"),			 index->idxname, stmt->relname);		dlist = lnext(dlist);	}	q->utilityStmt = (Node *) stmt;

⌨️ 快捷键说明

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