|
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
|
|