Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the implementation function of the selection operator in PostgreSQL implicit type conversion

2025-02-27 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Database >

Share

Shulou(Shulou.com)05/31 Report--

This article mainly explains "what is the implementation function of the selection operator in PostgreSQL implicit type conversion". The content of the article is simple and clear, and it is easy to learn and understand. Please follow Xiaobian's train of thought to slowly deepen together to study and learn what is the implementation function of the selection operator in PostgreSQL implicit type conversion.

I. data structure

FuncCandidateList

This structure stores a linked list of all possible selected functions or operators retrieved.

/ * * This structure holds a list of possible functions or operators * found by namespace lookup. Each function/operator is identified * by OID and by argument types; the list must be pruned by type * resolution rules that are embodied in the parser, not here. * See FuncnameGetCandidates's comments for more info. * this structure stores a linked list of all possible selected functions or operators retrieved. * each function / operator is uniquely determined by OID and parameter type. * the linked list is tailored through the type resolution rules integrated into the analyzer (but not implemented here). For more information, please see the FuncnameGetCandidates function. * / typedef struct _ FuncCandidateList {struct _ FuncCandidateList * next; / / for namespace search the number of parameters using int pathpos; / * for internal use of namespace lookup * / OID Oid oid; / * the function or operator's OID * / number of parameters int nargs; / * number of arg types returned * / variadic array int nvargs / * number of args to become variadic array * / / default number of parameters int ndargs; / * number of defaulted args * / / Parameter location index int * argnumbers; / * args' positional indexes, if named call * / / Parameter type Oid args [flex _ ARRAY_MEMBER]; / * arg types * /} * FuncCandidateList; II, source code interpretation

Func_select_candidate

The processing logic is the same as the type conversion rules in PG documents, which are detailed in the Operator section of Resources.

/ * create table t_tmp (C1 int,c2 int); insert into t_tmp values (1Magne1); create cast (integer as text) with inout as implicit;testdb=# select C1 | |'-'| | c2 from tactitmpany psql: ERROR: operator is not unique: integer | | unknownLINE 1: select C1 | |'-'| c2 from tactitmp; ^ HINT: Could not choose a best candidate operator. You might need to add explicit type casts.*//* func_select_candidate () * Given the input argtype array and more than one candidate * for the function, attempt to resolve the conflict. * given the parameter type and more than 1 candidate function, try to resolve the conflict and choose the appropriate function. * * Returns the selected candidate if the conflict can be resolved, * otherwise returns NULL. * if the conflict is resolved, the selected function is returned, otherwise NULL. * * Note that the caller has already determined that there is no candidate * exactly matching the input argtypes, and has pruned away any "candidates" * that aren't actually coercion-compatible with the input types. * Note: the caller has determined that no function fully satisfies the input parameter type. * all functions that are not compatible with the input parameter type have been cleared. * * This is also used for resolving ambiguous operator references. Formerly * parse_oper.c had its own, essentially duplicate code for the purpose. * The following comments (formerly in parse_oper.c) are kept to record some * of the history of these heuristics. * this routine is also used to resolve fuzzy operator references. Parse_oper.c used to have its own code, which is essentially repetitive code. * the following comments (previously in parse_oper.c) are reserved to record the history of these heuristics. * * OLD COMMENTS: * * This routine is new code, replacing binary_oper_select_candidate () * which dates from v4.2/v1.0.x days. It tries very hard to match up * operators with types, including allowing type coercions if necessary. * The important thing is that the code do as much as possible, * while _ never_ doing the wrong thing, where "the wrong thing" would * be returning an operator when other better choices are available, * or returning an operator which is a non-intuitive possibility. *-thomas 1998-05-21 * this routine tries to match operators by type, including allowing type casting if needed. * * The comments below came from binary_oper_select_candidate (), and * illustrate the issues and choices which are possible: *-thomas 1998-05-20 * * current wisdom holds that the default operator should be one in which * both operands have the same type (there will only be one such * operator) * currently we believe that the default operator should be two operands of the same type (there is only one such operator). * * 7.27.93-I have decided not to do this; it's too hard to justify, and * it's easy enough to typecast explicitly-avi * [the rest of this routine was commented out since then-ay] * * 6-23-95-I don't complete agree with avi. In particular, casting * floats is a pain for users. Whatever the rationale behind not doing * this is, I need the following special case to work. * * In the WHERE clause of a query, if a float is specified without * quotes, we treat it as float8. I added the float48* operators so * that we can operate on float4 and float8. But now we have more than * one matching operator if the right arg is unknown (eg. Float * specified with quotes). This break some stuff in the regression * test where there are floats in quotes not properly casted. Below is * the solution. In addition to requiring the operator operates on the * same type for both operands [as in the code Avi originally * commented out], we also require that the operators be equivalent in * some sense. (see equivalentOpersAfterPromotion for details.) *-ay 6 PG 95 * in the WHERE statement, if float is not in quotation marks, PG treats the value as a float8 type. The purpose of adding the float48* operator is to handle both float4 and float8 types. * however, if the type of the right Operand is unknown (such as a floating-point number with quotation marks), there will be more than one matching operator. * this will cause the floating-point number to fail in the regression test when it is enclosed in quotation marks and not converted correctly. * in addition to requiring operators to be of the same type of operands, operators are required to be equivalent in some scenarios. * / FuncCandidateListfunc_select_candidate (int nargs, Oid * input_typeids, FuncCandidateList candidates) {FuncCandidateList current_candidate, first_candidate, last_candidate; Oid * current_typeids; Oid current_type; int i; int ncandidates Int nbestMatch, nmatch, nunknowns; Oid input_base_ types [FUNC _ MAX_ARGS]; TYPCATEGORY slot_ types [FUNC _ MAX_ARGS], current_category; bool current_is_preferred; bool slot_has_preferred_ type [FUNC _ MAX_ARGS]; bool resolved_unknowns / * protect local fixed-size arrays * / / verify if (nargs > FUNC_MAX_ARGS) ereport (ERROR, (errcode (ERRCODE_TOO_MANY_ARGUMENTS), errmsg_plural ("cannot pass more than% d argument to a function", "cannot pass more than% d arguments to a function") FUNC_MAX_ARGS, FUNC_MAX_ARGS) / * If any input types are domains, reduce them to their base types. This * ensures that we will consider functions on the base type to be "exact * matches" in the exact-match heuristic; it also makes it possible to do * something useful with the type-category heuristics. Note that this * makes it difficult, but not impossible, to use functions declared to * take a domain as an input datatype. Such a function will be selected * over the base-type function only if it is an exact match at all * argument positions, and so was already chosen by our caller. * While we're at it, count the number of unknown-type arguments for use * later. * calculate the number of parameters of unknown type * / / * If any input argument is of a domain type, treat it as being of the domain's base type for all subsequent steps. This ensures that domains act like their base types for purposes of ambiguous-operator resolution. * / nunknowns = 0; for (I = 0; I

< nargs; i++) { if (input_typeids[i] != UNKNOWNOID) input_base_typeids[i] = getBaseType(input_typeids[i]);//基本类型 else { //unknown 类型 /* no need to call getBaseType on UNKNOWNOID */ input_base_typeids[i] = UNKNOWNOID; nunknowns++; } } /* * Run through all candidates and keep those with the most matches on * exact types. Keep all candidates if none match. * 遍历所有候选,保留那些类型一致的那些.如无匹配的,保留所有候选. */ /* Run through all candidates and keep those with the most exact matches on input types. Keep all candidates if none have exact matches. If only one candidate remains, use it; else continue to the next step. */ ncandidates = 0;//候选数 nbestMatch = 0;//最佳匹配数 last_candidate = NULL;//最后一个候选 for (current_candidate = candidates; current_candidate != NULL; current_candidate = current_candidate->

Next) / / traversing {/ / to get the parameters of the candidate function current_typeids = current_candidate- > args; nmatch = 0; for (I = 0; I

< nargs; i++) { //计算参数匹配个数 if (input_base_typeids[i] != UNKNOWNOID && current_typeids[i] == input_base_typeids[i]) nmatch++; } /* take this one as the best choice so far? */ //就拿这个作为最好的选择? if ((nmatch >

NbestMatch) | | (last_candidate = = NULL) {/ / 1. Larger than the number of optimal parameter matches, adjust the number of optimal matches (number of parameters) / / 2.last_candidate = = NULL, the first cycle nbestMatch = nmatch; candidates = current_candidate; last_candidate = current_candidate; ncandidates = 1 } / * no worse than the last choice, so keep this one too? * / / will not be worse than the last option, so leave this option else if (nmatch = = nbestMatch) {/ / in the linked list last_candidate- > next = current_candidate; last_candidate = current_candidate; ncandidates++ } / * otherwise, don't bother keeping this one... * / / otherwise, there is no need to keep} if (last_candidate) / * terminate rebuilt list * / last_candidate- > next = NULL; if (ncandidates = = 1) / / there is only one candidate, and return return candidates; / * * Still too many candidates? Now look for candidates which have either * exact matches or preferred types at the args that will require * coercion. (Restriction added in 7.4preferred type must be of same * category as input type; give no preference to cross-category * conversions to preferred types.) Keep all candidates if none match. * are there still too many candidates? * retrieve candidates with preferred type after args exact match or cast. * (the preferred type must be the same directory as the input type). * if there is no match, keep all candidates. * / * Run through all candidates and keep those that accept preferred types (of the input data type's type category) at the most positions where type conversion will be required. Keep all candidates if none accept preferred types. If only one candidate remains, use it; else continue to the next step. * / for (I = 0; I

< nargs; i++) /* avoid multiple lookups */ slot_category[i] = TypeCategory(input_base_typeids[i]);//获取类型目录 ncandidates = 0; nbestMatch = 0; last_candidate = NULL; for (current_candidate = candidates; current_candidate != NULL; current_candidate = current_candidate->

Next) / / traversal {current_typeids = current_candidate- > args;// parameter nmatch = 0; for (I = 0; I

< nargs; i++) { if (input_base_typeids[i] != UNKNOWNOID) { if (current_typeids[i] == input_base_typeids[i] || IsPreferredType(slot_category[i], current_typeids[i])) nmatch++;//不要求精确匹配,存在首选项一样的参数也可以了 } } if ((nmatch >

NbestMatch) | | (last_candidate = = NULL) {/ / 1. Larger than the number of optimal parameter matches, adjust the number of optimal matches (number of parameters) / / 2.last_candidate = = NULL, the first cycle nbestMatch = nmatch; candidates = current_candidate; last_candidate = current_candidate; ncandidates = 1 } else if (nmatch = = nbestMatch) {/ / keep the candidate last_candidate- > next = current_candidate; last_candidate = current_candidate; ncandidates++;}} if (last_candidate) / * terminate rebuilt list * / last_candidate- > next = NULL as the best match If (ncandidates = = 1) return candidates;// / * Still too many candidates? Try assigning types for the unknown inputs. * are there still too many candidates? Try to assign a value of * * If there are no unknown inputs, we have no more heuristics that apply, * and must fail to the unknown type. * if there is no unknown type, no more heuristics are available, so fail * / if (nunknowns = = 0) / / fail return NULL; / * failed to select a best candidate * / / * The next step examines each unknown argument position to see if we can * determine a "type category" for it. If any candidate has an input * datatype of STRING category, use STRING category (this bias towards * STRING is appropriate since unknown-type literals look like strings). * Otherwise, if all the candidates agree on the type category of this * argument position, use that category. Otherwise, fail because we * cannot determine a category. * next, check the parameter location of each unknown type to determine whether the type directory of the parameter can be found. * if the candidate has the input data type of the STRING directory, use the STRING directory (because unknown literals looks like string) * otherwise, if all candidates agree with the type directory at the location of the parameter, use this directory. * if the directory cannot be determined, it fails. * If we are able to determine atype category, also notice whether any of * the candidates takes a preferred datatype within the category. * if you can determine the type catalog, also note whether one of the candidates uses the preferred data type in the catalog. * Having completed this examination, remove candidates that accept the * wrong category at any unknown position. Also, if at least one * candidate accepted a preferred type at a position, remove candidates * that accept non-preferred types. If just one candidate remains, return * that one. However, if this rule turns out to reject all candidates, * keep them all instead. * after completing this check, remove the candidate to accept the wrong directory at the unknown location. * at the same time, if at least one candidate accepts the preferred type in that position, remove the candidate without the preferred type. * if there is only one candidate reserved, that candidate is returned. * otherwise, reject all candidates and keep all. * If any input arguments are unknown, check the type categories accepted at those argument positions by the remaining candidates. At each position, select the string category if any candidate accepts that category. (This bias towards string is appropriate since an unknown-type literal looks like a string.) Otherwise, if all the remaining candidates accept the same type category, select that category; otherwise fail because the correct choice cannot be deduced without more clues. Now discard candidates that do not accept the selected type category. Furthermore, if any candidate accepts a preferred type in that category, discard candidates that accept non-preferred types for that argument. Keep all candidates if none survive these tests. If only one candidate remains, use it; else continue to the next step. * / resolved_unknowns = whether the unknown type tag for (I = 0; I) has been resolved by false;//

< nargs; i++)//遍历参数 { bool have_conflict;//是否存在冲突标记 if (input_base_typeids[i] != UNKNOWNOID) continue;//非unknown类型 resolved_unknowns = true; /* 假定可以搞掂 assume we can do it */ slot_category[i] = TYPCATEGORY_INVALID; slot_has_preferred_type[i] = false; have_conflict = false; for (current_candidate = candidates; current_candidate != NULL; current_candidate = current_candidate->

Next) / / traverses all candidates {current_typeids = current_candidate- > args; current_type = current_ typeids [I]; get_type_category_preferred (current_type, & current_category, & current_is_preferred) If (slot_ type [I] = TYPCATEGORY_INVALID) {/ * first candidate * / / first candidate slot_ category [I] = current_category; slot_has_preferred_ type [I] = current_is_preferred } else if (current_category = = slot_ category [I]) {/ * more candidates in same category * / there are more candidate slot_has_preferred_ types in the same directory [I] | = current_is_preferred } else {/ * category conflict! * / / directory conflict if (current_category = = TYPCATEGORY_STRING) {/ * STRING always wins if available * / / if possible STRING slot_ preferred [I] = current_category Slot_has_preferred_ type [I] = current_is_preferred } else {/ * * Remember conflict, but keep going (might find STRING) * has a conflict, but continue to process * / have_conflict = true } if (have_conflict & & slot_ conflict [I]! = TYPCATEGORY_STRING) {/ / there is a conflict, and the directory is not STRING / * Failed to resolve category conflict at this position * / cannot resolve the conflict resolved_unknowns = false; break }} if (resolved_unknowns) {/ / conflict has been resolved / * Strip non-matching candidates * / ncandidates = 0; first_candidate = candidates; last_candidate = NULL; for (current_candidate = candidates; current_candidate! = NULL Current_candidate = current_candidate- > next) / / iterate through {bool keepit = true; / / if at least one candidate accepts the preferred type at that location, remove the candidate with no preferred type. Current_typeids = current_candidate- > args; for (I = 0; I

< nargs; i++)//遍历参数 { if (input_base_typeids[i] != UNKNOWNOID) continue;//非unknown参数,跳过 current_type = current_typeids[i];//当前类型 get_type_category_preferred(current_type, ¤t_category, ¤t_is_preferred);//首选类型 if (current_category != slot_category[i]) { //当前目录不等于slot中的目录,退出参数循环 keepit = false; break; } if (slot_has_preferred_type[i] && !current_is_preferred) { //存在首选类型但当前首选类型为NULL,退出参数循环 keepit = false; break; } } if (keepit) { /* keep this candidate */ //保留该候选 last_candidate = current_candidate; ncandidates++; } else { /* forget this candidate */ // if (last_candidate) last_candidate->

Next = current_candidate- > next; else first_candidate = current_candidate- > next;}} / * if we found any matches, restrict our attention to those * / if (last_candidate) {candidates = first_candidate; / * terminate rebuilt list * / last_candidate- > next = NULL } if (ncandidates = = 1) return candidates;} / * * Last gasp: if there are both known- and unknown-type inputs, and all * the known types are the same, assume the unknown inputs are also that * type, and see if that gives us a unique match. If so, use that match. * finally: if there are both known and unknown types, * and the known type is the same, then assume that the unknown input is also of that type, and then see if there is a unique match, and if so, use the candidate. * * NOTE: for a binary operator with one unknown and one non-unknown input, * we already tried this heuristic in binary_oper_exact (). However, that * code only finds exact matches, whereas here we will handle matches that * involve coercion, polymorphic type resolution, etc. * Note: for binary operators with a unknown and a known type parameter, * has used this heuristic in the binary_oper_exact () function. * however, those codes can only find exact matches, and here we will deal with matches involving enforcement, polymorphic type parsing, and so on. * / * If there are both unknown and known-type arguments, and all the known-type arguments have the same type, assume that the unknown arguments are also of that type, and check which candidates can accept that type at the unknown-argument positions. If exactly one candidate passes this test, use it. Otherwise, fail. * / if (nunknowns

< nargs) { Oid known_type = UNKNOWNOID; for (i = 0; i < nargs; i++)//找到基本类型,找不到则失败 { if (input_base_typeids[i] == UNKNOWNOID) continue; if (known_type == UNKNOWNOID) /* first known arg? */ known_type = input_base_typeids[i]; else if (known_type != input_base_typeids[i]) { /* oops, not all match */ known_type = UNKNOWNOID; break; } } if (known_type != UNKNOWNOID)//找到了基本类型 { /* okay, just one known type, apply the heuristic */ for (i = 0; i < nargs; i++) input_base_typeids[i] = known_type;//使用该基本类型 ncandidates = 0; last_candidate = NULL; for (current_candidate = candidates; current_candidate != NULL; current_candidate = current_candidate->

Next) / / traversing {current_typeids = current_candidate- > args; if (can_coerce_type (nargs, input_base_typeids, current_typeids, COERCION_IMPLICIT)) {if (+ + ncandidates > 1) break / * not unique, give up * / last_candidate = current_candidate;}} if (ncandidates = = 1) {/ * successfully identified a unique match * / / successful! Last_candidate- > next = NULL; return last_candidate;}} / / return NULL return NULL; / * failed to select a best candidate * /} / * func_select_candidate () * / 3. Tracking analysis

Test script

Create cast (integer as text) with inout as implicit;select id | |'X' from t_cast

Tracking and analysis

Breakpoint 1, func_select_candidate (nargs=2, input_typeids=0x7fff5f3ac6c0, candidates=0x2daa6f0) at parse_func.c:10211021 if (nargs > FUNC_MAX_ARGS) (gdb) p * input_typeids$6 = 23 (gdb) p * candidates$7 = {next = 0x2daa720, pathpos = 0, oid = 654, nargs=2, nvargs = 0, ndargs = 0, argnumbers = 0x0, args= 0x2daa718} (gdb) p * candidates- > next$8 = {next = 0x2daa7e0, pathpos = 0, oid = 2779, nargs=2, nvargs = 0, ndargs = 0, argnumbers = 0x0 Args = 0x2daa748} (gdb) p * candidates- > next- > next$9 = {next = 0x2daa810, pathpos = 0, oid = 3744,nargs = 2, nvargs = 0, ndargs = 0, argnumbers = 0x0, args = 0x2daa808} (gdb) p * candidates- > next- > next- > next$10 = {next = 0x0, pathpos = 0, oid = 2780, nargs = 2, nvargs = 0, ndargs = 0, argnumbers = 0x0, args = 0x2daa838} (gdb) p * candidates- > next- > next- (next-) n1042 next- = 0 (gdb) 1043 for (I = 0; I

< nargs; i++)(gdb) 1045 if (input_typeids[i] != UNKNOWNOID)(gdb) 1046 input_base_typeids[i] = getBaseType(input_typeids[i]);(gdb) 1043 for (i = 0; i < nargs; i++)(gdb) p input_base_typeids[0]$12 = 23(gdb) n1045 if (input_typeids[i] != UNKNOWNOID)(gdb) 1050 input_base_typeids[i] = UNKNOWNOID;(gdb) p input_typeids[i]$13 = 705(gdb) p UNKNOWNOID$14 = 705(gdb) n1051 nunknowns++;(gdb) 1043 for (i = 0; i < nargs; i++)(gdb) 1059 ncandidates = 0;(gdb) 1060 nbestMatch = 0;(gdb) 1061 last_candidate = NULL;(gdb) 1062 for (current_candidate = candidates;(gdb) 1066 current_typeids = current_candidate->

Args; (gdb) 1067 nmatch = 0; (gdb) 1068 for (I = 0; I)

< nargs; i++)(gdb) 1070 if (input_base_typeids[i] != UNKNOWNOID &&(gdb) 1071 current_typeids[i] == input_base_typeids[i])(gdb) p current_typeids[i]$15 = 25(gdb) p input_base_typeids[i]$16 = 23(gdb) n1070 if (input_base_typeids[i] != UNKNOWNOID &&(gdb) 1068 for (i = 0; i < nargs; i++)(gdb) 1070 if (input_base_typeids[i] != UNKNOWNOID &&(gdb) 1068 for (i = 0; i < nargs; i++)(gdb) 1076 if ((nmatch >

NbestMatch) | (last_candidate = = NULL)) (gdb) 1078 nbestMatch = nmatch; (gdb) 1079 candidates = current_candidate; (gdb) 1080 last_candidate = current_candidate; (gdb) 1081 ncandidates = 1; (gdb) 1064 current_candidate = current_candidate- > next) (gdb) 1062 for (current_candidate = candidates; (gdb) 1066 current_typeids = current_candidate- > args (gdb) 1067 nmatch = 0; (gdb) 1068 for (I = 0; I)

< nargs; i++)(gdb) 1070 if (input_base_typeids[i] != UNKNOWNOID &&(gdb) 1071 current_typeids[i] == input_base_typeids[i])(gdb) 1070 if (input_base_typeids[i] != UNKNOWNOID &&(gdb) 1068 for (i = 0; i < nargs; i++)(gdb) 1070 if (input_base_typeids[i] != UNKNOWNOID &&(gdb) 1068 for (i = 0; i < nargs; i++)(gdb) 1076 if ((nmatch >

NbestMatch) | | (last_candidate = = NULL)) (gdb) 1084 else if (nmatch = = nbestMatch) (gdb) 1086 last_candidate- > next = current_candidate (gdb) p * last_candidate$17 = {next = 0x2daa720, pathpos = 0, oid = 654, nargs = 2, nvargs = 0, ndargs = 0, argnumbers = 0x0, args = 0x2daa718} (gdb) p * current_candidate$18 = {next = 0x2daa7e0, pathpos = 0, oid = 2779, nargs = 2, nvargs = 0, ndargs = 0, argnumbers = 0x0, args = 0x2daa748} (gdb) n1087 last_candidate = current_candidate; (gdb) 1088 ncandidates++ (gdb) 1064 current_candidate = current_candidate- > next) (gdb) 1062 for (current_candidate = candidates; (gdb) 1066 current_typeids = current_candidate- > args; (gdb) 1067 nmatch = 0; (gdb) 1068 for (I = 0; I)

< nargs; i++)(gdb) 1070 if (input_base_typeids[i] != UNKNOWNOID &&(gdb) 1071 current_typeids[i] == input_base_typeids[i])(gdb) 1070 if (input_base_typeids[i] != UNKNOWNOID &&(gdb) 1068 for (i = 0; i < nargs; i++)(gdb) 1070 if (input_base_typeids[i] != UNKNOWNOID &&(gdb) 1068 for (i = 0; i < nargs; i++)(gdb) 1076 if ((nmatch >

NbestMatch) | (last_candidate = = NULL)) (gdb) p * candidates$19 = {next = 0x2daa720, pathpos = 0, oid = 654, nargs = 2, nvargs = 0, ndargs = 0, argnumbers = 0x0, args = 0x2daa718} (gdb) n1084 else if (nmatch = = nbestMatch) (gdb) 1086 last_candidate- > next = current_candidate; (gdb) 1087 last_candidate = current_candidate; (gdb) 1088 ncandidates++ (gdb) n1064 current_candidate = current_candidate- > next) (gdb) 1062 for (current_candidate = candidates; (gdb) 1066 current_typeids = current_candidate- > args; (gdb) 1067 nmatch = 0; (gdb) 1068 for (I = 0; I)

< nargs; i++)(gdb) 1070 if (input_base_typeids[i] != UNKNOWNOID &&(gdb) 1071 current_typeids[i] == input_base_typeids[i])(gdb) 1070 if (input_base_typeids[i] != UNKNOWNOID &&(gdb) 1068 for (i = 0; i < nargs; i++)(gdb) 1070 if (input_base_typeids[i] != UNKNOWNOID &&(gdb) 1068 for (i = 0; i < nargs; i++)(gdb) 1076 if ((nmatch >

NbestMatch) | | (last_candidate = = NULL)) (gdb) 1084 else if (nmatch = = nbestMatch) (gdb) 1086 last_candidate- > next = current_candidate; (gdb) 1087 last_candidate = current_candidate; (gdb) 1088 ncandidates++; (gdb) 1064 current_candidate = current_candidate- > next) (gdb) 1062 for (current_candidate = candidates (gdb) 1093 if (last_candidate) / * terminate rebuilt list * / (gdb) 1094 last_candidate- > next = NULL; (gdb) 1096 if (ncandidates = = 1) (gdb) p * last_candidate$20 = {next = 0x0, pathpos = 0, oid = 2780, nargs = 2, nvargs = 0, ndargs = 0, argnumbers = 0x0, args = 0x2daa838} (gdb) n1106 for (I = 0; I

< nargs; i++) /* avoid multiple lookups */(gdb) 1107 slot_category[i] = TypeCategory(input_base_typeids[i]);(gdb) 1106 for (i = 0; i < nargs; i++) /* avoid multiple lookups */(gdb) p slot_category[i] $21 = 78 'N'(gdb) n1107 slot_category[i] = TypeCategory(input_base_typeids[i]);(gdb) 1106 for (i = 0; i < nargs; i++) /* avoid multiple lookups */(gdb) p slot_category[i] $22 = 88 'X'(gdb) n1108 ncandidates = 0;(gdb) 1109 nbestMatch = 0;(gdb) 1110 last_candidate = NULL;(gdb) 1111 for (current_candidate = candidates;(gdb) 1115 current_typeids = current_candidate->

Args; (gdb) 1116 nmatch = 0; (gdb) 1117 for (I = 0; I)

< nargs; i++)(gdb) 1119 if (input_base_typeids[i] != UNKNOWNOID)(gdb) 1121 if (current_typeids[i] == input_base_typeids[i] ||(gdb) p current_typeids[i]$23 = 25(gdb) n1122 IsPreferredType(slot_category[i], current_typeids[i]))(gdb) 1121 if (current_typeids[i] == input_base_typeids[i] ||(gdb) 1117 for (i = 0; i < nargs; i++)(gdb) 1119 if (input_base_typeids[i] != UNKNOWNOID)(gdb) 1117 for (i = 0; i < nargs; i++)(gdb) 1127 if ((nmatch >

NbestMatch) | (last_candidate = = NULL)) (gdb) 1129 nbestMatch = nmatch; (gdb) 1130 candidates = current_candidate; (gdb) 1131 last_candidate = current_candidate; (gdb) 1132 ncandidates = 1; (gdb) 1113 current_candidate = current_candidate- > next) (gdb) 1111 for (current_candidate = candidates; (gdb) 1115 current_typeids = current_candidate- > args (gdb) 1116 nmatch = 0; (gdb) 1117 for (I = 0; I)

< nargs; i++)(gdb) 1119 if (input_base_typeids[i] != UNKNOWNOID)(gdb) 1121 if (current_typeids[i] == input_base_typeids[i] ||(gdb) 1122 IsPreferredType(slot_category[i], current_typeids[i]))(gdb) 1121 if (current_typeids[i] == input_base_typeids[i] ||(gdb) 1117 for (i = 0; i < nargs; i++)(gdb) 1119 if (input_base_typeids[i] != UNKNOWNOID)(gdb) 1117 for (i = 0; i < nargs; i++)(gdb) 1127 if ((nmatch >

NbestMatch) | | (last_candidate = = NULL)) (gdb) 1134 else if (nmatch = = nbestMatch) (gdb) 1136 last_candidate- > next = current_candidate; (gdb) 1137 last_candidate = current_candidate; (gdb) 1138 ncandidates++; (gdb) 1113 current_candidate = current_candidate- > next) (gdb) 1111 for (current_candidate = candidates (gdb) 1115 current_typeids = current_candidate- > args; (gdb) 1116 nmatch = 0; (gdb) 1117 for (I = 0; I

< nargs; i++)(gdb) 1119 if (input_base_typeids[i] != UNKNOWNOID)(gdb) 1121 if (current_typeids[i] == input_base_typeids[i] ||(gdb) 1122 IsPreferredType(slot_category[i], current_typeids[i]))(gdb) p *last_candidate$24 = {next = 0x2daa7e0, pathpos = 0, oid = 2779, nargs = 2, nvargs = 0, ndargs = 0, argnumbers = 0x0, args = 0x2daa748}(gdb) n1121 if (current_typeids[i] == input_base_typeids[i] ||(gdb) 1117 for (i = 0; i < nargs; i++)(gdb) 1119 if (input_base_typeids[i] != UNKNOWNOID)(gdb) 1117 for (i = 0; i < nargs; i++)(gdb) 1127 if ((nmatch >

NbestMatch) | | (last_candidate = = NULL)) (gdb) 1134 else if (nmatch = = nbestMatch) (gdb) 1136 last_candidate- > next = current_candidate; (gdb) 1137 last_candidate = current_candidate; (gdb) 1138 ncandidates++; (gdb) 1113 current_candidate = current_candidate- > next) (gdb) 1111 for (current_candidate = candidates (gdb) 1115 current_typeids = current_candidate- > args; (gdb) 1116 nmatch = 0; (gdb) 1117 for (I = 0; I

< nargs; i++)(gdb) 1119 if (input_base_typeids[i] != UNKNOWNOID)(gdb) 1121 if (current_typeids[i] == input_base_typeids[i] ||(gdb) 1122 IsPreferredType(slot_category[i], current_typeids[i]))(gdb) 1121 if (current_typeids[i] == input_base_typeids[i] ||(gdb) 1117 for (i = 0; i < nargs; i++)(gdb) 1119 if (input_base_typeids[i] != UNKNOWNOID)(gdb) 1117 for (i = 0; i < nargs; i++)(gdb) 1127 if ((nmatch >

NbestMatch) | | (last_candidate = = NULL)) (gdb) 1134 else if (nmatch = = nbestMatch) (gdb) 1136 last_candidate- > next = current_candidate; (gdb) 1137 last_candidate = current_candidate; (gdb) 1138 ncandidates++; (gdb) 1113 current_candidate = current_candidate- > next) (gdb) 1111 for (current_candidate = candidates (gdb) 1142 if (last_candidate) / * terminate rebuilt list * / (gdb) 1143 last_candidate- > next = NULL; (gdb) 1145 if (ncandidates = = 1) (gdb) 1154 if (nunknowns = 0) (gdb) 1176 resolved_unknowns = false; (gdb) 1177 for (I = 0; I

< nargs; i++)(gdb) 1181 if (input_base_typeids[i] != UNKNOWNOID)(gdb) 1182 continue;(gdb) 1177 for (i = 0; i < nargs; i++)(gdb) 1181 if (input_base_typeids[i] != UNKNOWNOID)(gdb) 1183 resolved_unknowns = true; /* assume we can do it */(gdb) 1184 slot_category[i] = TYPCATEGORY_INVALID;(gdb) 1185 slot_has_preferred_type[i] = false;(gdb) 1186 have_conflict = false;(gdb) 1187 for (current_candidate = candidates;(gdb) 1191 current_typeids = current_candidate->

Args; (gdb) 1192 current_type = current_ typeids [I] (gdb) 1193 get_type_category_preferred (current_type, (gdb) 1196 if (slot_ equation [I] = TYPCATEGORY_INVALID) (gdb) p current_type$25 = 25 (gdb) p current_category$26 = 83'S' (gdb) p current_is_preferred$27 = true (gdb) p slot_category [I] $28 = 0'\ 000' (gdb) n1199 slot_ ratio [I] = current_category (gdb) 1200 slot_has_preferred_ type [I] = current_is_preferred; (gdb) 1189 current_candidate = current_candidate- > next) (gdb) p current_category$29 = 83's'(gdb) p current_is_preferred$30 = true (gdb) n1187 for (current_candidate = candidates; (gdb) 1191 current_typeids = current_candidate- > args (gdb) 1192 current_type = current_ typeids [I] (gdb) 1193 get_type_category_preferred (current_type (gdb) 1196 if (slot_ criteria [I] = = TYPCATEGORY_INVALID) (gdb) p current_category$31 = 80'P' (gdb) p current_is_preferred$32 = false (gdb) n1202 else if (current_category = = slot_ satisfaction [I]) (gdb) 1210 if (current_category = TYPCATEGORY_STRING) (gdb) 1221 have_conflict = true (gdb) 1189 current_candidate = current_candidate- > next) (gdb) 1187 for (current_candidate = candidates; (gdb) 1191 current_typeids = current_candidate- > args; (gdb) 1192 current_type = current_ typeids [I] (gdb) 1193 get_type_category_preferred (current_type (gdb) 1196 if (slot_ criteria [I] = = TYPCATEGORY_INVALID) (gdb) p current_type$33 = 2277 (gdb) p current_is_preferred$34 = false (gdb) p current_category$35 = 80'P' (gdb) n1202 else if (current_category = = slot_ assurance [I]) (gdb) 1210 if (current_category = = TYPCATEGORY_STRING) (gdb) 1221 have_conflict = true (gdb) 1189 current_candidate = current_candidate- > next) (gdb) 1187 for (current_candidate = candidates; (gdb) 1191 current_typeids = current_candidate- > args; (gdb) 1192 current_type = current_ typeids [I] (gdb) 1193 get_type_category_preferred (current_type, (gdb) 1196 if (slot_ category [I] = = TYPCATEGORY_INVALID) (gdb) 1202 else if (current_category = = slot_ definition [I]) (gdb) 1205 slot_has_preferred_ type [I] | = current_is_preferred (gdb) p current_category$36 = 83'S' (gdb) n1189 current_candidate = current_candidate- > next) (gdb) 1187 for (current_candidate = candidates; (gdb) 1225 if (have_conflict & & slot_ criteria [I]! = TYPCATEGORY_STRING) (gdb) 1177 for (I = 0; I)

< nargs; i++)(gdb) p resolved_unknowns$37 = true(gdb) n1233 if (resolved_unknowns)(gdb) 1236 ncandidates = 0;(gdb) 1237 first_candidate = candidates;(gdb) 1238 last_candidate = NULL;(gdb) 1239 for (current_candidate = candidates;(gdb) 1243 bool keepit = true;(gdb) 1245 current_typeids = current_candidate->

Args; (gdb) 1246 for (I = 0; I

< nargs; i++)(gdb) 1248 if (input_base_typeids[i] != UNKNOWNOID)(gdb) 1249 continue;(gdb) 1246 for (i = 0; i < nargs; i++)(gdb) 1248 if (input_base_typeids[i] != UNKNOWNOID)(gdb) 1250 current_type = current_typeids[i];(gdb) 1251 get_type_category_preferred(current_type,(gdb) p current_type$38 = 25(gdb) n1254 if (current_category != slot_category[i])(gdb) p current_category$39 = 83 'S'(gdb) p slot_category[i]$40 = 83 'S'(gdb) n1259 if (slot_has_preferred_type[i] && !current_is_preferred)(gdb) 1246 for (i = 0; i < nargs; i++)(gdb) 1265 if (keepit)(gdb) 1268 last_candidate = current_candidate;(gdb) p *current_candidate$41 = {next = 0x2daa720, pathpos = 0, oid = 654, nargs = 2, nvargs = 0, ndargs = 0, argnumbers = 0x0, args = 0x2daa718}(gdb) n1269 ncandidates++;(gdb) 1241 current_candidate = current_candidate->

Next) (gdb) n1239 for (current_candidate = candidates; (gdb) 1243 bool keepit = true; (gdb) 1245 current_typeids = current_candidate- > args; (gdb) 1246 for (I = 0; I

< nargs; i++)(gdb) 1248 if (input_base_typeids[i] != UNKNOWNOID)(gdb) 1249 continue;(gdb) 1246 for (i = 0; i < nargs; i++)(gdb) 1248 if (input_base_typeids[i] != UNKNOWNOID)(gdb) 1250 current_type = current_typeids[i];(gdb) 1251 get_type_category_preferred(current_type,(gdb) 1254 if (current_category != slot_category[i])(gdb) p current_type$42 = 2776(gdb) p current_category$43 = 80 'P'(gdb) n1256 keepit = false;(gdb) 1257 break;(gdb) 1265 if (keepit)(gdb) 1274 if (last_candidate)(gdb) 1275 last_candidate->

Next = current_candidate- > next; (gdb) 1241 current_candidate = current_candidate- > next) (gdb) p * last_candidate$44 = {next = 0x2daa7e0, pathpos = 0, oid = 654, nargs = 2, nvargs = 0, ndargs = 0, argnumbers = 0x0, args = 0x2daa718} (gdb) n1239 for (current_candidate = candidates; (gdb) 1243 bool keepit = true; (gdb) 1245 current_typeids = current_candidate- > args (gdb) 1246 for (I = 0; I

< nargs; i++)(gdb) 1248 if (input_base_typeids[i] != UNKNOWNOID)(gdb) 1249 continue;(gdb) 1246 for (i = 0; i < nargs; i++)(gdb) 1248 if (input_base_typeids[i] != UNKNOWNOID)(gdb) 1250 current_type = current_typeids[i];(gdb) 1251 get_type_category_preferred(current_type,(gdb) p current_type$45 = 2277(gdb) p current_category$46 = 80 'P'(gdb) n1254 if (current_category != slot_category[i])(gdb) 1256 keepit = false;(gdb) 1257 break;(gdb) 1265 if (keepit)(gdb) 1274 if (last_candidate)(gdb) 1275 last_candidate->

Next = current_candidate- > next; (gdb) 1241 current_candidate = current_candidate- > next) (gdb) 1239 for (current_candidate = candidates; (gdb) 1243 bool keepit = true; (gdb) 1245 current_typeids = current_candidate- > args; (gdb) 1246 for (I = 0; I

< nargs; i++)(gdb) 1248 if (input_base_typeids[i] != UNKNOWNOID)(gdb) 1249 continue;(gdb) 1246 for (i = 0; i < nargs; i++)(gdb) 1248 if (input_base_typeids[i] != UNKNOWNOID)(gdb) 1250 current_type = current_typeids[i];(gdb) 1251 get_type_category_preferred(current_type,(gdb) 1254 if (current_category != slot_category[i])(gdb) 1259 if (slot_has_preferred_type[i] && !current_is_preferred)(gdb) p current_category$47 = 83 'S'(gdb) p *current_candidate$48 = {next = 0x0, pathpos = 0, oid = 2780, nargs = 2, nvargs = 0, ndargs = 0, argnumbers = 0x0, args = 0x2daa838}(gdb) n1246 for (i = 0; i < nargs; i++)(gdb) 1265 if (keepit)(gdb) 1268 last_candidate = current_candidate;(gdb) 1269 ncandidates++;(gdb) 1241 current_candidate = current_candidate->

Next) (gdb) 1239 for (current_candidate = candidates; (gdb) 1282 if (last_candidate) (gdb) 1284 candidates = first_candidate (gdb) p * first_candidate$49 = {next = 0x2daa810, pathpos = 0, oid = 654, nargs = 2, nvargs = 0, ndargs = 0, argnumbers = 0x0, args = 0x2daa718} (gdb) p * last_candidate$50 = {next = 0x0, pathpos = 0, oid = 2780, nargs = 2, nvargs = 0, ndargs = 0, argnumbers = 0x0, args = 0x2daa838} (gdb) n1286 last_candidate- > next = NULL; (gdb) n1289 if (ncandidates = 1) (gdb) 1303 if (nunknowns)

< nargs)(gdb) p *candidates$51 = {next = 0x2daa810, pathpos = 0, oid = 654, nargs = 2, nvargs = 0, ndargs = 0, argnumbers = 0x0, args = 0x2daa718}(gdb) p *candidates->

Next$52 = {next = 0x0, pathpos = 0, oid = 2780, nargs = 2, nvargs = 0, ndargs = 0, argnumbers = 0x0, args = 0x2daa838} (gdb) n1305 Oid known_type = UNKNOWNOID; (gdb) 1307 for (I = 0; I

< nargs; i++)(gdb) 1309 if (input_base_typeids[i] == UNKNOWNOID)(gdb) 1311 if (known_type == UNKNOWNOID) /* first known arg? */(gdb) 1312 known_type = input_base_typeids[i];(gdb) 1307 for (i = 0; i < nargs; i++)(gdb) p known_type$53 = 23(gdb) n1309 if (input_base_typeids[i] == UNKNOWNOID)(gdb) 1310 continue;(gdb) 1307 for (i = 0; i < nargs; i++)(gdb) 1321 if (known_type != UNKNOWNOID)(gdb) 1324 for (i = 0; i < nargs; i++)(gdb) 1325 input_base_typeids[i] = known_type;(gdb) 1324 for (i = 0; i < nargs; i++)(gdb) p known_type$54 = 23(gdb) n1325 input_base_typeids[i] = known_type;(gdb) 1324 for (i = 0; i < nargs; i++)(gdb) 1326 ncandidates = 0;(gdb) 1327 last_candidate = NULL;(gdb) 1328 for (current_candidate = candidates;(gdb) 1332 current_typeids = current_candidate->

Args; (gdb) 1333 if (can_coerce_type (nargs, input_base_typeids, current_typeids, (gdb) 1336 if (+ + ncandidates > 1) (gdb) n1338 last_candidate = current_candidate; (gdb) 1330 current_candidate = current_candidate- > next) (gdb) 1328 for (current_candidate = candidates (gdb) 1332 current_typeids = current_candidate- > args; (gdb) 1333 if (can_coerce_type (nargs, input_base_typeids, current_typeids, (gdb) 1336 if (+ + ncandidates > 1) (gdb) 1337 break / * not unique, give up * / (gdb) 1341 if (ncandidates = = 1) (gdb) 1350 return NULL / * failed to select a best candidate * / (gdb) Thank you for your reading, the above is the content of "what is the implementation function of the selection operator in PostgreSQL implicit type conversion". After the study of this article, I believe you have a deeper understanding of what the implementation function of the selection operator in PostgreSQL implicit type conversion is, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Database

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report