|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.106 2001/05/19 00:33:20 momjian Exp $ |
| 11 | + * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.107 2001/05/19 00:37:45 momjian Exp $ |
12 | 12 | *
|
13 | 13 | *-------------------------------------------------------------------------
|
14 | 14 | */
|
@@ -104,136 +104,6 @@ ParseNestedFuncOrColumn(ParseState *pstate, Attr *attr, int precedence)
|
104 | 104 | returnretval;
|
105 | 105 | }
|
106 | 106 |
|
107 |
| -staticint |
108 |
| -agg_get_candidates(char*aggname, |
109 |
| -OidtypeId, |
110 |
| -CandidateList*candidates) |
111 |
| -{ |
112 |
| -CandidateListcurrent_candidate; |
113 |
| -Relationpg_aggregate_desc; |
114 |
| -HeapScanDescpg_aggregate_scan; |
115 |
| -HeapTupletup; |
116 |
| -Form_pg_aggregateagg; |
117 |
| -intncandidates=0; |
118 |
| -ScanKeyDataaggKey[1]; |
119 |
| - |
120 |
| -*candidates=NULL; |
121 |
| - |
122 |
| -ScanKeyEntryInitialize(&aggKey[0],0, |
123 |
| -Anum_pg_aggregate_aggname, |
124 |
| -F_NAMEEQ, |
125 |
| -NameGetDatum(aggname)); |
126 |
| - |
127 |
| -pg_aggregate_desc=heap_openr(AggregateRelationName,AccessShareLock); |
128 |
| -pg_aggregate_scan=heap_beginscan(pg_aggregate_desc, |
129 |
| -0, |
130 |
| -SnapshotSelf,/* ??? */ |
131 |
| -1, |
132 |
| -aggKey); |
133 |
| - |
134 |
| -while (HeapTupleIsValid(tup=heap_getnext(pg_aggregate_scan,0))) |
135 |
| -{ |
136 |
| -agg= (Form_pg_aggregate)GETSTRUCT(tup); |
137 |
| - |
138 |
| -current_candidate= (CandidateList)palloc(sizeof(struct_CandidateList)); |
139 |
| -current_candidate->args= (Oid*)palloc(sizeof(Oid)); |
140 |
| - |
141 |
| -current_candidate->args[0]=agg->aggbasetype; |
142 |
| -current_candidate->next=*candidates; |
143 |
| -*candidates=current_candidate; |
144 |
| -ncandidates++; |
145 |
| -} |
146 |
| - |
147 |
| -heap_endscan(pg_aggregate_scan); |
148 |
| -heap_close(pg_aggregate_desc,AccessShareLock); |
149 |
| - |
150 |
| -returnncandidates; |
151 |
| -}/* agg_get_candidates() */ |
152 |
| - |
153 |
| -/* agg_select_candidate() |
154 |
| - * |
155 |
| - * Try to choose only one candidate aggregate function from a list of |
156 |
| - * possible matches. Return value is Oid of input type of aggregate |
157 |
| - * if successful, else InvalidOid. |
158 |
| - */ |
159 |
| -staticOid |
160 |
| -agg_select_candidate(Oidtypeid,CandidateListcandidates) |
161 |
| -{ |
162 |
| -CandidateListcurrent_candidate; |
163 |
| -CandidateListlast_candidate; |
164 |
| -Oidcurrent_typeid; |
165 |
| -intncandidates; |
166 |
| -CATEGORYcategory, |
167 |
| -current_category; |
168 |
| - |
169 |
| -/* |
170 |
| - * First look for exact matches or binary compatible matches. (Of |
171 |
| - * course exact matches shouldn't even get here, but anyway.) |
172 |
| - */ |
173 |
| -ncandidates=0; |
174 |
| -last_candidate=NULL; |
175 |
| -for (current_candidate=candidates; |
176 |
| -current_candidate!=NULL; |
177 |
| -current_candidate=current_candidate->next) |
178 |
| -{ |
179 |
| -current_typeid=current_candidate->args[0]; |
180 |
| - |
181 |
| -if (current_typeid==typeid |
182 |
| -||IS_BINARY_COMPATIBLE(current_typeid,typeid)) |
183 |
| -{ |
184 |
| -last_candidate=current_candidate; |
185 |
| -ncandidates++; |
186 |
| -} |
187 |
| -} |
188 |
| -if (ncandidates==1) |
189 |
| -returnlast_candidate->args[0]; |
190 |
| - |
191 |
| -/* |
192 |
| - * If no luck that way, look for candidates which allow coercion and |
193 |
| - * have a preferred type. Keep all candidates if none match. |
194 |
| - */ |
195 |
| -category=TypeCategory(typeid); |
196 |
| -ncandidates=0; |
197 |
| -last_candidate=NULL; |
198 |
| -for (current_candidate=candidates; |
199 |
| -current_candidate!=NULL; |
200 |
| -current_candidate=current_candidate->next) |
201 |
| -{ |
202 |
| -current_typeid=current_candidate->args[0]; |
203 |
| -current_category=TypeCategory(current_typeid); |
204 |
| - |
205 |
| -if (current_category==category |
206 |
| -&&IsPreferredType(current_category,current_typeid) |
207 |
| -&&can_coerce_type(1,&typeid,¤t_typeid)) |
208 |
| -{ |
209 |
| -/* only one so far? then keep it... */ |
210 |
| -if (last_candidate==NULL) |
211 |
| -{ |
212 |
| -candidates=current_candidate; |
213 |
| -last_candidate=current_candidate; |
214 |
| -ncandidates=1; |
215 |
| -} |
216 |
| -/* otherwise, keep this one too... */ |
217 |
| -else |
218 |
| -{ |
219 |
| -last_candidate->next=current_candidate; |
220 |
| -last_candidate=current_candidate; |
221 |
| -ncandidates++; |
222 |
| -} |
223 |
| -} |
224 |
| -/* otherwise, don't bother keeping this one around... */ |
225 |
| -} |
226 |
| - |
227 |
| -if (last_candidate)/* terminate rebuilt list */ |
228 |
| -last_candidate->next=NULL; |
229 |
| - |
230 |
| -if (ncandidates==1) |
231 |
| -returncandidates->args[0]; |
232 |
| - |
233 |
| -returnInvalidOid; |
234 |
| -}/* agg_select_candidate() */ |
235 |
| - |
236 |
| - |
237 | 107 | /*
|
238 | 108 | * parse function
|
239 | 109 | * This code is confusing because the database can accept
|
@@ -709,6 +579,136 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
709 | 579 | }
|
710 | 580 |
|
711 | 581 |
|
| 582 | +staticint |
| 583 | +agg_get_candidates(char*aggname, |
| 584 | +OidtypeId, |
| 585 | +CandidateList*candidates) |
| 586 | +{ |
| 587 | +CandidateListcurrent_candidate; |
| 588 | +Relationpg_aggregate_desc; |
| 589 | +HeapScanDescpg_aggregate_scan; |
| 590 | +HeapTupletup; |
| 591 | +Form_pg_aggregateagg; |
| 592 | +intncandidates=0; |
| 593 | +ScanKeyDataaggKey[1]; |
| 594 | + |
| 595 | +*candidates=NULL; |
| 596 | + |
| 597 | +ScanKeyEntryInitialize(&aggKey[0],0, |
| 598 | +Anum_pg_aggregate_aggname, |
| 599 | +F_NAMEEQ, |
| 600 | +NameGetDatum(aggname)); |
| 601 | + |
| 602 | +pg_aggregate_desc=heap_openr(AggregateRelationName,AccessShareLock); |
| 603 | +pg_aggregate_scan=heap_beginscan(pg_aggregate_desc, |
| 604 | +0, |
| 605 | +SnapshotSelf,/* ??? */ |
| 606 | +1, |
| 607 | +aggKey); |
| 608 | + |
| 609 | +while (HeapTupleIsValid(tup=heap_getnext(pg_aggregate_scan,0))) |
| 610 | +{ |
| 611 | +agg= (Form_pg_aggregate)GETSTRUCT(tup); |
| 612 | + |
| 613 | +current_candidate= (CandidateList)palloc(sizeof(struct_CandidateList)); |
| 614 | +current_candidate->args= (Oid*)palloc(sizeof(Oid)); |
| 615 | + |
| 616 | +current_candidate->args[0]=agg->aggbasetype; |
| 617 | +current_candidate->next=*candidates; |
| 618 | +*candidates=current_candidate; |
| 619 | +ncandidates++; |
| 620 | +} |
| 621 | + |
| 622 | +heap_endscan(pg_aggregate_scan); |
| 623 | +heap_close(pg_aggregate_desc,AccessShareLock); |
| 624 | + |
| 625 | +returnncandidates; |
| 626 | +}/* agg_get_candidates() */ |
| 627 | + |
| 628 | +/* agg_select_candidate() |
| 629 | + * |
| 630 | + * Try to choose only one candidate aggregate function from a list of |
| 631 | + * possible matches. Return value is Oid of input type of aggregate |
| 632 | + * if successful, else InvalidOid. |
| 633 | + */ |
| 634 | +staticOid |
| 635 | +agg_select_candidate(Oidtypeid,CandidateListcandidates) |
| 636 | +{ |
| 637 | +CandidateListcurrent_candidate; |
| 638 | +CandidateListlast_candidate; |
| 639 | +Oidcurrent_typeid; |
| 640 | +intncandidates; |
| 641 | +CATEGORYcategory, |
| 642 | +current_category; |
| 643 | + |
| 644 | +/* |
| 645 | + * First look for exact matches or binary compatible matches. (Of |
| 646 | + * course exact matches shouldn't even get here, but anyway.) |
| 647 | + */ |
| 648 | +ncandidates=0; |
| 649 | +last_candidate=NULL; |
| 650 | +for (current_candidate=candidates; |
| 651 | +current_candidate!=NULL; |
| 652 | +current_candidate=current_candidate->next) |
| 653 | +{ |
| 654 | +current_typeid=current_candidate->args[0]; |
| 655 | + |
| 656 | +if (current_typeid==typeid |
| 657 | +||IS_BINARY_COMPATIBLE(current_typeid,typeid)) |
| 658 | +{ |
| 659 | +last_candidate=current_candidate; |
| 660 | +ncandidates++; |
| 661 | +} |
| 662 | +} |
| 663 | +if (ncandidates==1) |
| 664 | +returnlast_candidate->args[0]; |
| 665 | + |
| 666 | +/* |
| 667 | + * If no luck that way, look for candidates which allow coercion and |
| 668 | + * have a preferred type. Keep all candidates if none match. |
| 669 | + */ |
| 670 | +category=TypeCategory(typeid); |
| 671 | +ncandidates=0; |
| 672 | +last_candidate=NULL; |
| 673 | +for (current_candidate=candidates; |
| 674 | +current_candidate!=NULL; |
| 675 | +current_candidate=current_candidate->next) |
| 676 | +{ |
| 677 | +current_typeid=current_candidate->args[0]; |
| 678 | +current_category=TypeCategory(current_typeid); |
| 679 | + |
| 680 | +if (current_category==category |
| 681 | +&&IsPreferredType(current_category,current_typeid) |
| 682 | +&&can_coerce_type(1,&typeid,¤t_typeid)) |
| 683 | +{ |
| 684 | +/* only one so far? then keep it... */ |
| 685 | +if (last_candidate==NULL) |
| 686 | +{ |
| 687 | +candidates=current_candidate; |
| 688 | +last_candidate=current_candidate; |
| 689 | +ncandidates=1; |
| 690 | +} |
| 691 | +/* otherwise, keep this one too... */ |
| 692 | +else |
| 693 | +{ |
| 694 | +last_candidate->next=current_candidate; |
| 695 | +last_candidate=current_candidate; |
| 696 | +ncandidates++; |
| 697 | +} |
| 698 | +} |
| 699 | +/* otherwise, don't bother keeping this one around... */ |
| 700 | +} |
| 701 | + |
| 702 | +if (last_candidate)/* terminate rebuilt list */ |
| 703 | +last_candidate->next=NULL; |
| 704 | + |
| 705 | +if (ncandidates==1) |
| 706 | +returncandidates->args[0]; |
| 707 | + |
| 708 | +returnInvalidOid; |
| 709 | +}/* agg_select_candidate() */ |
| 710 | + |
| 711 | + |
712 | 712 | /* func_get_candidates()
|
713 | 713 | * get a list of all argument type vectors for which a function named
|
714 | 714 | * funcname taking nargs arguments exists
|
|