|
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 | return retval;
|
105 | 105 | }
|
106 | 106 |
|
107 |
| -static int |
108 |
| -agg_get_candidates(char *aggname, |
109 |
| - Oid typeId, |
110 |
| - CandidateList *candidates) |
111 |
| -{ |
112 |
| - CandidateList current_candidate; |
113 |
| - Relation pg_aggregate_desc; |
114 |
| - HeapScanDesc pg_aggregate_scan; |
115 |
| - HeapTuple tup; |
116 |
| - Form_pg_aggregate agg; |
117 |
| - int ncandidates = 0; |
118 |
| - ScanKeyData aggKey[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 |
| - return ncandidates; |
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 |
| -static Oid |
160 |
| -agg_select_candidate(Oid typeid, CandidateList candidates) |
161 |
| -{ |
162 |
| - CandidateList current_candidate; |
163 |
| - CandidateList last_candidate; |
164 |
| - Oid current_typeid; |
165 |
| - int ncandidates; |
166 |
| - CATEGORY category, |
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 |
| - return last_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 |
| - return candidates->args[0]; |
232 |
| - |
233 |
| - return InvalidOid; |
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 | +static int |
| 583 | +agg_get_candidates(char *aggname, |
| 584 | + Oid typeId, |
| 585 | + CandidateList *candidates) |
| 586 | +{ |
| 587 | + CandidateList current_candidate; |
| 588 | + Relation pg_aggregate_desc; |
| 589 | + HeapScanDesc pg_aggregate_scan; |
| 590 | + HeapTuple tup; |
| 591 | + Form_pg_aggregate agg; |
| 592 | + int ncandidates = 0; |
| 593 | + ScanKeyData aggKey[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 | + return ncandidates; |
| 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 | +static Oid |
| 635 | +agg_select_candidate(Oid typeid, CandidateList candidates) |
| 636 | +{ |
| 637 | + CandidateList current_candidate; |
| 638 | + CandidateList last_candidate; |
| 639 | + Oid current_typeid; |
| 640 | + int ncandidates; |
| 641 | + CATEGORY category, |
| 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 | + return last_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 | + return candidates->args[0]; |
| 707 | + |
| 708 | + return InvalidOid; |
| 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
|
|
0 commit comments