|
26 | 26 | * |
27 | 27 | * |
28 | 28 | * IDENTIFICATION |
29 | | - * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.198 2003/01/12 18:19:37petere Exp $ |
| 29 | + * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.199 2003/01/23 05:10:37tgl Exp $ |
30 | 30 | * |
31 | 31 | *------------------------------------------------------------------------- |
32 | 32 | */ |
@@ -450,6 +450,7 @@ InitPlan(QueryDesc *queryDesc) |
450 | 450 | PlanState*planstate; |
451 | 451 | List*rangeTable; |
452 | 452 | RelationintoRelationDesc; |
| 453 | +booldo_select_into; |
453 | 454 | TupleDesctupType; |
454 | 455 |
|
455 | 456 | /* |
@@ -529,6 +530,26 @@ InitPlan(QueryDesc *queryDesc) |
529 | 530 | estate->es_result_relation_info=NULL; |
530 | 531 | } |
531 | 532 |
|
| 533 | +/* |
| 534 | + * Detect whether we're doing SELECT INTO. If so, set the force_oids |
| 535 | + * flag appropriately so that the plan tree will be initialized with |
| 536 | + * the correct tuple descriptors. |
| 537 | + */ |
| 538 | +do_select_into= false; |
| 539 | + |
| 540 | +if (operation==CMD_SELECT&& |
| 541 | +!parseTree->isPortal&& |
| 542 | +parseTree->into!=NULL) |
| 543 | +{ |
| 544 | +do_select_into= true; |
| 545 | +/* |
| 546 | + * For now, always create OIDs in SELECT INTO; this is for backwards |
| 547 | + * compatibility with pre-7.3 behavior. Eventually we might want |
| 548 | + * to allow the user to choose. |
| 549 | + */ |
| 550 | +estate->es_force_oids= true; |
| 551 | +} |
| 552 | + |
532 | 553 | /* |
533 | 554 | * Have to lock relations selected for update |
534 | 555 | */ |
@@ -687,79 +708,64 @@ InitPlan(QueryDesc *queryDesc) |
687 | 708 | } |
688 | 709 |
|
689 | 710 | /* |
690 | | - * initialize the "into" relation |
| 711 | + * If doing SELECT INTO, initialize the "into" relation. We must wait |
| 712 | + * till now so we have the "clean" result tuple type to create the |
| 713 | + * new table from. |
691 | 714 | */ |
692 | 715 | intoRelationDesc= (Relation)NULL; |
693 | 716 |
|
694 | | -if (operation==CMD_SELECT) |
| 717 | +if (do_select_into) |
695 | 718 | { |
696 | | -if (!parseTree->isPortal) |
697 | | -{ |
698 | | -/* |
699 | | - * a select into table --- need to create the "into" table |
700 | | - */ |
701 | | -if (parseTree->into!=NULL) |
702 | | -{ |
703 | | -char*intoName; |
704 | | -OidnamespaceId; |
705 | | -AclResultaclresult; |
706 | | -OidintoRelationId; |
707 | | -TupleDesctupdesc; |
| 719 | +char*intoName; |
| 720 | +OidnamespaceId; |
| 721 | +AclResultaclresult; |
| 722 | +OidintoRelationId; |
| 723 | +TupleDesctupdesc; |
708 | 724 |
|
709 | | -/* |
710 | | - * find namespace to create in, check permissions |
711 | | - */ |
712 | | -intoName=parseTree->into->relname; |
713 | | -namespaceId=RangeVarGetCreationNamespace(parseTree->into); |
| 725 | +/* |
| 726 | + * find namespace to create in, check permissions |
| 727 | + */ |
| 728 | +intoName=parseTree->into->relname; |
| 729 | +namespaceId=RangeVarGetCreationNamespace(parseTree->into); |
714 | 730 |
|
715 | | -aclresult=pg_namespace_aclcheck(namespaceId,GetUserId(), |
716 | | -ACL_CREATE); |
717 | | -if (aclresult!=ACLCHECK_OK) |
718 | | -aclcheck_error(aclresult, |
719 | | -get_namespace_name(namespaceId)); |
| 731 | +aclresult=pg_namespace_aclcheck(namespaceId,GetUserId(), |
| 732 | +ACL_CREATE); |
| 733 | +if (aclresult!=ACLCHECK_OK) |
| 734 | +aclcheck_error(aclresult,get_namespace_name(namespaceId)); |
720 | 735 |
|
721 | | -/* |
722 | | - * have to copy tupType to get rid of constraints |
723 | | - */ |
724 | | -tupdesc=CreateTupleDescCopy(tupType); |
725 | | - |
726 | | -/* |
727 | | - * Formerly we forced the output table to have OIDs, but |
728 | | - * as of 7.3 it will not have OIDs, because it's too late |
729 | | - * here to change the tupdescs of the already-initialized |
730 | | - * plan tree. (Perhaps we could recurse and change them |
731 | | - * all, but it's not really worth the trouble IMHO...) |
732 | | - */ |
| 736 | +/* |
| 737 | + * have to copy tupType to get rid of constraints |
| 738 | + */ |
| 739 | +tupdesc=CreateTupleDescCopy(tupType); |
733 | 740 |
|
734 | | -intoRelationId= |
735 | | -heap_create_with_catalog(intoName, |
736 | | -namespaceId, |
737 | | -tupdesc, |
738 | | -RELKIND_RELATION, |
739 | | - false, |
740 | | -ONCOMMIT_NOOP, |
741 | | -allowSystemTableMods); |
| 741 | +intoRelationId=heap_create_with_catalog(intoName, |
| 742 | +namespaceId, |
| 743 | +tupdesc, |
| 744 | +RELKIND_RELATION, |
| 745 | + false, |
| 746 | +ONCOMMIT_NOOP, |
| 747 | +allowSystemTableMods); |
742 | 748 |
|
743 | | -FreeTupleDesc(tupdesc); |
| 749 | +FreeTupleDesc(tupdesc); |
744 | 750 |
|
745 | | -/* |
746 | | - * Advance command counter so that the newly-created |
747 | | - * relation's catalog tuples will be visible to heap_open. |
748 | | - */ |
749 | | -CommandCounterIncrement(); |
| 751 | +/* |
| 752 | + * Advance command counter so that the newly-created |
| 753 | + * relation's catalog tuples will be visible to heap_open. |
| 754 | + */ |
| 755 | +CommandCounterIncrement(); |
750 | 756 |
|
751 | | -/* |
752 | | - * If necessary, create a TOAST table for the into |
753 | | - * relation. Note that AlterTableCreateToastTable ends |
754 | | - * with CommandCounterIncrement(), so that the TOAST table |
755 | | - * will be visible for insertion. |
756 | | - */ |
757 | | -AlterTableCreateToastTable(intoRelationId, true); |
| 757 | +/* |
| 758 | + * If necessary, create a TOAST table for the into |
| 759 | + * relation. Note that AlterTableCreateToastTable ends |
| 760 | + * with CommandCounterIncrement(), so that the TOAST table |
| 761 | + * will be visible for insertion. |
| 762 | + */ |
| 763 | +AlterTableCreateToastTable(intoRelationId, true); |
758 | 764 |
|
759 | | -intoRelationDesc=heap_open(intoRelationId, |
760 | | -AccessExclusiveLock); |
761 | | -} |
762 | | -} |
| 765 | +/* |
| 766 | + * And open the constructed table for writing. |
| 767 | + */ |
| 768 | +intoRelationDesc=heap_open(intoRelationId,AccessExclusiveLock); |
763 | 769 | } |
764 | 770 |
|
765 | 771 | estate->es_into_relation_descriptor=intoRelationDesc; |
@@ -1964,6 +1970,7 @@ EvalPlanQualStart(evalPlanQual *epq, EState *estate, evalPlanQual *priorepq) |
1964 | 1970 | palloc0(estate->es_topPlan->nParamExec*sizeof(ParamExecData)); |
1965 | 1971 | epqstate->es_rowMark=estate->es_rowMark; |
1966 | 1972 | epqstate->es_instrument=estate->es_instrument; |
| 1973 | +epqstate->es_force_oids=estate->es_force_oids; |
1967 | 1974 | epqstate->es_topPlan=estate->es_topPlan; |
1968 | 1975 | /* |
1969 | 1976 | * Each epqstate must have its own es_evTupleNull state, but |
|