Resolve a field name to an available context. If list is true, then this function can detect and return a relation node if there is no name. This is used for cases of "SELECT . ...". CVC: The function attempts to detect if an unqualified field appears in more than one context and hence it returns the number of occurrences. This was added to allow the caller to detect ambiguous commands
| 6069 | // ambiguous commands like select from t1 join t2 on t1.f = t2.f order by common_field. |
| 6070 | // While inoffensive on inner joins, it changes the result on outer joins. |
| 6071 | ValueExprNode* FieldNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch, RecordSourceNode** list) |
| 6072 | { |
| 6073 | thread_db* tdbb = JRD_get_thread_data(); |
| 6074 | |
| 6075 | if (list) |
| 6076 | *list = NULL; |
| 6077 | |
| 6078 | /* CVC: PLEASE READ THIS EXPLANATION IF YOU NEED TO CHANGE THIS CODE. |
| 6079 | You should ensure that this function: |
| 6080 | 1.- Never returns NULL. In such case, it such fall back to an invocation |
| 6081 | to PASS1_field_unknown() near the end of this function. None of the multiple callers |
| 6082 | of this function (inside this same module) expect a null pointer, hence they |
| 6083 | will crash the engine in such case. |
| 6084 | 2.- Doesn't allocate more than one field in "node". Either you put a break, |
| 6085 | keep the current "continue" or call ALLD_release if you don't want nor the |
| 6086 | continue neither the break if node is already allocated. If it isn't evident, |
| 6087 | but this variable is initialized to zero in the declaration above. You |
| 6088 | may write an explicit line to set it to zero here, before the loop. |
| 6089 | |
| 6090 | 3.- Doesn't waste cycles if qualifier is not null. The problem is not the cycles |
| 6091 | themselves, but the fact that you'll detect an ambiguity that doesn't exist: if |
| 6092 | the field appears in more than one context but it's always qualified, then |
| 6093 | there's no ambiguity. There's PASS1_make_context() that prevents a context's |
| 6094 | alias from being reused. However, other places in the code don't check that you |
| 6095 | don't create a join or subselect with the same context without disambiguating it |
| 6096 | with different aliases. This is the place where resolveContext() is called for |
| 6097 | that purpose. In the future, it will be fine if we force the use of the alias as |
| 6098 | the only allowed qualifier if the alias exists. Hopefully, we will eliminate |
| 6099 | some day this construction: "select table.field from table t" because it |
| 6100 | should be "t.field" instead. |
| 6101 | |
| 6102 | AB: 2004-01-09 |
| 6103 | The explained query directly above doesn't work anymore, thus the day has come ;-) |
| 6104 | It's allowed to use the same fieldname between different scope levels (sub-queries) |
| 6105 | without being hit by the ambiguity check. The field uses the first match starting |
| 6106 | from it's own level (of course ambiguity-check on each level is done). |
| 6107 | |
| 6108 | 4.- Doesn't verify code derived automatically from check constraints. They are |
| 6109 | ill-formed by nature but making that code generation more orthodox is not a |
| 6110 | priority. Typically, they only check a field against a contant. The problem |
| 6111 | appears when they check a field against a subselect, for example. For now, |
| 6112 | allow the user to write ambiguous subselects in check() statements. |
| 6113 | Claudio Valderrama - 2001.1.29. |
| 6114 | */ |
| 6115 | |
| 6116 | // Try to resolve field against various contexts; |
| 6117 | // if there is an alias, check only against the first matching |
| 6118 | |
| 6119 | ValueExprNode* node = NULL; // This var must be initialized. |
| 6120 | DsqlContextStack ambiguousCtxStack; |
| 6121 | |
| 6122 | bool resolveByAlias = true; |
| 6123 | const bool relaxedAliasChecking = Config::getRelaxedAliasChecking(); |
| 6124 | |
| 6125 | while (true) |
| 6126 | { |
| 6127 | // AB: Loop through the scope_levels starting by its own. |
| 6128 | bool done = false; |
no test coverage detected