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