Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit1ac4ae4

Browse files
author
Thomas G. Lockhart
committed
Add SQL92-compliant syntax for constraints.
Implement PRIMARY KEY and UNIQUE clauses using indices.
1 parent7b06d99 commit1ac4ae4

File tree

2 files changed

+601
-209
lines changed

2 files changed

+601
-209
lines changed

‎src/backend/parser/analyze.c

Lines changed: 329 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.51 1997/11/26 01:11:03 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.52 1997/12/04 23:07:18 thomas Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
1414

1515
#include<stdio.h>
1616
#include<stdlib.h>
17+
#include<stdarg.h>
1718
#include<string.h>
1819

1920
#include"postgres.h"
@@ -39,7 +40,9 @@ static Query *transformRuleStmt(ParseState *query, RuleStmt *stmt);
3940
staticQuery*transformSelectStmt(ParseState*pstate,RetrieveStmt*stmt);
4041
staticQuery*transformUpdateStmt(ParseState*pstate,ReplaceStmt*stmt);
4142
staticQuery*transformCursorStmt(ParseState*pstate,CursorStmt*stmt);
43+
staticQuery*transformCreateStmt(ParseState*pstate,CreateStmt*stmt);
4244

45+
List*extras=NIL;
4346

4447
/*
4548
* parse_analyze -
@@ -65,6 +68,17 @@ parse_analyze(List *pl)
6568
{
6669
pstate=make_parsestate();
6770
result->qtrees[i++]=transformStmt(pstate,lfirst(pl));
71+
if (extras!=NIL)
72+
{
73+
result->len+=length(extras);
74+
result->qtrees= (Query**)realloc(result->qtrees,result->len*sizeof(Query*));
75+
while (extras!=NIL)
76+
{
77+
result->qtrees[i++]=transformStmt(pstate,lfirst(extras));
78+
extras=lnext(extras);
79+
}
80+
}
81+
extras=NIL;
6882
pl=lnext(pl);
6983
if (pstate->p_target_relation!=NULL)
7084
heap_close(pstate->p_target_relation);
@@ -90,6 +104,10 @@ transformStmt(ParseState *pstate, Node *parseTree)
90104
*Non-optimizable statements
91105
*------------------------
92106
*/
107+
caseT_CreateStmt:
108+
result=transformCreateStmt(pstate, (CreateStmt*)parseTree);
109+
break;
110+
93111
caseT_IndexStmt:
94112
result=transformIndexStmt(pstate, (IndexStmt*)parseTree);
95113
break;
@@ -309,6 +327,316 @@ transformInsertStmt(ParseState *pstate, AppendStmt *stmt)
309327
return (Query*)qry;
310328
}
311329

330+
/* makeTableName()
331+
* Create a table name from a list of fields.
332+
*/
333+
staticchar*
334+
makeTableName(void*elem,...);
335+
336+
staticchar*
337+
makeTableName(void*elem,...)
338+
{
339+
va_listargs;
340+
341+
char*name;
342+
charbuf[NAMEDATALEN+1];
343+
344+
strcpy(buf,"");
345+
346+
va_start(args,elem);
347+
348+
name=elem;
349+
while (name!=NULL)
350+
{
351+
/* not enough room for next part? then return nothing */
352+
if ((strlen(buf)+strlen(name)) >= (sizeof(buf)-1))
353+
return (NULL);
354+
355+
if (strlen(buf)>0)strcat(buf,"_");
356+
strcat(buf,name);
357+
358+
name=va_arg(args,void*);
359+
}
360+
361+
va_end(args);
362+
363+
name=palloc(strlen(buf)+1);
364+
strcpy(name,buf);
365+
366+
return (name);
367+
}/* makeTableName() */
368+
369+
/*
370+
* transformCreateStmt -
371+
* transforms the "create table" statement
372+
* SQL92 allows constraints to be scattered all over, so thumb through
373+
* the columns and collect all constraints into one place.
374+
* If there are any implied indices (e.g. UNIQUE or PRIMARY KEY)
375+
* then expand those into multiple IndexStmt blocks.
376+
* - thomas 1997-12-02
377+
*/
378+
staticQuery*
379+
transformCreateStmt(ParseState*pstate,CreateStmt*stmt)
380+
{
381+
Query*q;
382+
List*elements;
383+
Node*element;
384+
List*columns;
385+
List*dlist;
386+
ColumnDef*column;
387+
List*constraints,*clist;
388+
Constraint*constraint;
389+
List*keys;
390+
Ident*key;
391+
List*ilist;
392+
IndexStmt*index;
393+
IndexElem*iparam;
394+
395+
q=makeNode(Query);
396+
q->commandType=CMD_UTILITY;
397+
398+
elements=stmt->tableElts;
399+
constraints=stmt->constraints;
400+
columns=NIL;
401+
dlist=NIL;
402+
403+
while (elements!=NIL)
404+
{
405+
element=lfirst(elements);
406+
switch (nodeTag(element))
407+
{
408+
caseT_ColumnDef:
409+
column= (ColumnDef*)element;
410+
#ifPARSEDEBUG
411+
printf("transformCreateStmt- found column %s\n",column->colname);
412+
#endif
413+
columns=lappend(columns,column);
414+
if (column->constraints!=NIL)
415+
{
416+
#ifPARSEDEBUG
417+
printf("transformCreateStmt- found constraint(s) on column %s\n",column->colname);
418+
#endif
419+
clist=column->constraints;
420+
while (clist!=NIL)
421+
{
422+
constraint=lfirst(clist);
423+
switch (constraint->contype)
424+
{
425+
caseCONSTR_NOTNULL:
426+
#ifPARSEDEBUG
427+
printf("transformCreateStmt- found NOT NULL constraint on column %s\n",column->colname);
428+
#endif
429+
if (column->is_not_null)
430+
elog(WARN,"CREATE TABLE/NOT NULL already specified"
431+
" for %s.%s",stmt->relname,column->colname);
432+
column->is_not_null= TRUE;
433+
break;
434+
435+
caseCONSTR_DEFAULT:
436+
#ifPARSEDEBUG
437+
printf("transformCreateStmt- found DEFAULT clause on column %s\n",column->colname);
438+
#endif
439+
if (column->defval!=NULL)
440+
elog(WARN,"CREATE TABLE/DEFAULT multiple values specified"
441+
" for %s.%s",stmt->relname,column->colname);
442+
column->defval=constraint->def;
443+
break;
444+
445+
caseCONSTR_PRIMARY:
446+
#ifPARSEDEBUG
447+
printf("transformCreateStmt- found PRIMARY KEY clause on column %s\n",column->colname);
448+
#endif
449+
if (constraint->name==NULL)
450+
constraint->name=makeTableName(stmt->relname,"pkey",NULL);
451+
if (constraint->keys==NIL)
452+
constraint->keys=lappend(constraint->keys,column);
453+
dlist=lappend(dlist,constraint);
454+
break;
455+
456+
caseCONSTR_UNIQUE:
457+
#ifPARSEDEBUG
458+
printf("transformCreateStmt- found UNIQUE clause on column %s\n",column->colname);
459+
#endif
460+
if (constraint->name==NULL)
461+
constraint->name=makeTableName(stmt->relname,column->colname,"key",NULL);
462+
if (constraint->keys==NIL)
463+
constraint->keys=lappend(constraint->keys,column);
464+
dlist=lappend(dlist,constraint);
465+
break;
466+
467+
caseCONSTR_CHECK:
468+
#ifPARSEDEBUG
469+
printf("transformCreateStmt- found CHECK clause on column %s\n",column->colname);
470+
#endif
471+
constraints=lappend(constraints,constraint);
472+
if (constraint->name==NULL)
473+
constraint->name=makeTableName(stmt->relname,".",column->colname,NULL);
474+
break;
475+
476+
default:
477+
elog(WARN,"parser: internal error; unrecognized constraint",NULL);
478+
break;
479+
}
480+
clist=lnext(clist);
481+
}
482+
}
483+
break;
484+
485+
caseT_Constraint:
486+
constraint= (Constraint*)element;
487+
#ifPARSEDEBUG
488+
printf("transformCreateStmt- found constraint %s\n", ((constraint->name!=NULL)?constraint->name:"(unknown)"));
489+
#endif
490+
switch (constraint->contype)
491+
{
492+
caseCONSTR_PRIMARY:
493+
#ifPARSEDEBUG
494+
printf("transformCreateStmt- found PRIMARY KEY clause\n");
495+
#endif
496+
if (constraint->name==NULL)
497+
constraint->name=makeTableName(stmt->relname,"pkey",NULL);
498+
dlist=lappend(dlist,constraint);
499+
break;
500+
501+
caseCONSTR_UNIQUE:
502+
#ifPARSEDEBUG
503+
printf("transformCreateStmt- found UNIQUE clause\n");
504+
#endif
505+
#ifFALSE
506+
if (constraint->name==NULL)
507+
constraint->name=makeTableName(stmt->relname,"key",NULL);
508+
#endif
509+
dlist=lappend(dlist,constraint);
510+
break;
511+
512+
caseCONSTR_CHECK:
513+
#ifPARSEDEBUG
514+
printf("transformCreateStmt- found CHECK clause\n");
515+
#endif
516+
constraints=lappend(constraints,constraint);
517+
break;
518+
519+
caseCONSTR_NOTNULL:
520+
caseCONSTR_DEFAULT:
521+
elog(WARN,"parser: internal error; illegal context for constraint",NULL);
522+
break;
523+
default:
524+
elog(WARN,"parser: internal error; unrecognized constraint",NULL);
525+
break;
526+
}
527+
break;
528+
529+
default:
530+
elog(WARN,"parser: internal error; unrecognized node",NULL);
531+
}
532+
533+
elements=lnext(elements);
534+
}
535+
536+
stmt->tableElts=columns;
537+
stmt->constraints=constraints;
538+
539+
/* Now run through the "deferred list" to complete the query transformation.
540+
* For PRIMARY KEYs, mark each column as NOT NULL and create an index.
541+
* For UNIQUE, create an index as for PRIMARY KEYS, but do not insist on NOT NULL.
542+
*
543+
* Note that this code does not currently look for all possible redundant cases
544+
* and either ignore or stop with warning. The create will fail later when
545+
* names for indices turn out to be redundant, or a user might just find
546+
* extra useless indices which might kill performance. - thomas 1997-12-04
547+
*/
548+
ilist=NIL;
549+
while (dlist!=NIL)
550+
{
551+
constraint=lfirst(dlist);
552+
if (nodeTag(constraint)!=T_Constraint)
553+
elog(WARN,"parser: internal error; unrecognized deferred node",NULL);
554+
555+
if ((constraint->contype!=CONSTR_PRIMARY)
556+
&& (constraint->contype!=CONSTR_UNIQUE))
557+
elog(WARN,"parser: internal error; illegal deferred constraint",NULL);
558+
559+
#ifPARSEDEBUG
560+
printf("transformCreateStmt- found deferred constraint %s\n",
561+
((constraint->name!=NULL)?constraint->name:"(unknown)"));
562+
#endif
563+
564+
#ifPARSEDEBUG
565+
printf("transformCreateStmt- found deferred %s clause\n",
566+
(constraint->contype==CONSTR_PRIMARY?"PRIMARY KEY":"UNIQUE"));
567+
#endif
568+
index=makeNode(IndexStmt);
569+
ilist=lappend(ilist,index);
570+
571+
index->unique= TRUE;
572+
if (constraint->name!=NULL)
573+
index->idxname=constraint->name;
574+
elseif (constraint->contype==CONSTR_PRIMARY)
575+
index->idxname=makeTableName(stmt->relname,"pkey",NULL);
576+
else
577+
index->idxname=NULL;
578+
579+
index->relname=stmt->relname;
580+
index->accessMethod="btree";
581+
index->indexParams=NIL;
582+
index->withClause=NIL;
583+
index->whereClause=NULL;
584+
585+
keys=constraint->keys;
586+
while (keys!=NIL)
587+
{
588+
key=lfirst(keys);
589+
#ifPARSEDEBUG
590+
printf("transformCreateStmt- check key %s for column match\n",key->name);
591+
#endif
592+
columns=stmt->tableElts;
593+
column=NULL;
594+
while (columns!=NIL)
595+
{
596+
column=lfirst(columns);
597+
#ifPARSEDEBUG
598+
printf("transformCreateStmt- check column %s for key match\n",column->colname);
599+
#endif
600+
if (strcasecmp(column->colname,key->name)==0)break;
601+
elsecolumn=NULL;
602+
columns=lnext(columns);
603+
}
604+
if (column==NULL)
605+
elog(WARN,"parser: column '%s' in key does not exist",key->name);
606+
607+
if (constraint->contype==CONSTR_PRIMARY)
608+
{
609+
#ifPARSEDEBUG
610+
printf("transformCreateStmt- mark column %s as NOT NULL\n",column->colname);
611+
#endif
612+
column->is_not_null= TRUE;
613+
}
614+
iparam=makeNode(IndexElem);
615+
iparam->name=strcpy(palloc(strlen(column->colname)+1),column->colname);
616+
iparam->args=NIL;
617+
iparam->class=NULL;
618+
iparam->tname=NULL;
619+
index->indexParams=lappend(index->indexParams,iparam);
620+
621+
if (index->idxname==NULL)
622+
index->idxname=makeTableName(stmt->relname,iparam->name,"key",NULL);
623+
624+
keys=lnext(keys);
625+
}
626+
627+
if (index->idxname==NULL)
628+
elog(WARN,"parser: unable to construct implicit index for table %s"
629+
"; name too long",stmt->relname);
630+
631+
dlist=lnext(dlist);
632+
}
633+
634+
q->utilityStmt= (Node*)stmt;
635+
extras=ilist;
636+
637+
returnq;
638+
}/* transformCreateStmt() */
639+
312640
/*
313641
* transformIndexStmt -
314642
* transforms the qualification of the index statement

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp