Codebase list firebird3.0 / upstream/3.0.5.33083.ds4
New upstream version 3.0.5.33083.ds4 Damyan Ivanov 5 years ago
18 changed file(s) with 369 addition(s) and 301 deletion(s). Raw diff Collapse all Expand all
55 <ItemDefinitionGroup>
66 <ClCompile>
77 <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
8 <AdditionalOptions>/Zo %(AdditionalOptions)</AdditionalOptions>
89 </ClCompile>
910 </ItemDefinitionGroup>
1011 </Project>
55 <ItemDefinitionGroup>
66 <ClCompile>
77 <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
8 <AdditionalOptions>/Zo %(AdditionalOptions)</AdditionalOptions>
89 </ClCompile>
910 </ItemDefinitionGroup>
1011 </Project>
3131 #endif
3232 #ifdef HAVE_SYS_TIMEB_H
3333 #include <sys/timeb.h>
34 #endif
35
36 #ifdef WIN_NT
37 #include <windows.h>
3438 #endif
3539
3640 #include "../common/classes/NoThrowTimeStamp.h"
5256 // is going to to be somewhere in range between 1 ms (like on UNIX/Risc)
5357 // and 53 ms (such as Win9X)
5458
59 int milliseconds;
60
61 #ifdef WIN_NT
62 FILETIME ftUtc, ftLocal;
63 SYSTEMTIME stLocal;
64
65 GetSystemTimeAsFileTime(&ftUtc);
66 if (!FileTimeToLocalFileTime(&ftUtc, &ftLocal))
67 {
68 if (error)
69 *error = "FileTimeToLocalFileTime";
70 return result;
71 }
72 if (!FileTimeToSystemTime(&ftLocal, &stLocal))
73 {
74 if (error)
75 *error = "FileTimeToSystemTime";
76 return result;
77 }
78
79 milliseconds = stLocal.wMilliseconds;
80 #else
5581 time_t seconds; // UTC time
56 int milliseconds;
5782
5883 #ifdef HAVE_GETTIMEOFDAY
5984 struct timeval tp;
6691 seconds = time_buffer.time;
6792 milliseconds = time_buffer.millitm;
6893 #endif
94 #endif // WIN_NT
6995
7096 // NS: Current FB behavior of using server time zone is not appropriate for
7197 // distributed applications. We should be storing UTC times everywhere and
77103
78104 const int fractions = milliseconds * ISC_TIME_SECONDS_PRECISION / 1000;
79105
106 #ifdef WIN_NT
107 // Manually convert SYSTEMTIME to "struct tm" used below
108
109 struct tm times, *ptimes = &times;
110
111 times.tm_sec = stLocal.wSecond; // seconds after the minute - [0,59]
112 times.tm_min = stLocal.wMinute; // minutes after the hour - [0,59]
113 times.tm_hour = stLocal.wHour; // hours since midnight - [0,23]
114 times.tm_mday = stLocal.wDay; // day of the month - [1,31]
115 times.tm_mon = stLocal.wMonth - 1; // months since January - [0,11]
116 times.tm_year = stLocal.wYear - 1900; // years since 1900
117 times.tm_wday = stLocal.wDayOfWeek; // days since Sunday - [0,6]
118
119 // --- no used for encoding below
120 times.tm_yday = 0; // days since January 1 - [0,365]
121 times.tm_isdst = -1; // daylight savings time flag
122 #else
80123 #ifdef HAVE_LOCALTIME_R
81 struct tm times;
124 struct tm times, *ptimes = &times;
82125 if (!localtime_r(&seconds, &times))
83126 {
84127 if (error)
85128 *error = "localtime_r";
86129 return result;
87130 }
88
89 result.encode(&times, fractions);
90131 #else
91 struct tm *times = localtime(&seconds);
92 if (!times)
132 struct tm *ptimes = localtime(&seconds);
133 if (!ptimes)
93134 {
94135 if (error)
95136 *error = "localtime";
96137 return result;
97138 }
98
99 result.encode(times, fractions);
100 #endif
101
139 #endif
140 #endif // WIN_NT
141
142 result.encode(ptimes, fractions);
102143 return result;
103144 }
104145
716716 }
717717
718718 bool ListAggNode::setParameterType(DsqlCompilerScratch* dsqlScratch,
719 const dsc* desc, bool forceVarChar)
720 {
721 return PASS1_set_parameter_type(dsqlScratch, arg, desc, forceVarChar) |
722 PASS1_set_parameter_type(dsqlScratch, delimiter, desc, forceVarChar);
719 const dsc* desc, ValueExprNode* node, bool forceVarChar)
720 {
721 return PASS1_set_parameter_type(dsqlScratch, arg, desc, node, forceVarChar) |
722 PASS1_set_parameter_type(dsqlScratch, delimiter, desc, node, forceVarChar);
723723 }
724724
725725 void ListAggNode::getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc)
830830 dsc desc;
831831 desc.makeText(charSet->maxBytesPerChar(), argDesc.getCharSet());
832832
833 node->setParameterType(dsqlScratch, &desc, false);
833 node->setParameterType(dsqlScratch, &desc, NULL, false);
834834
835835 return node;
836836 }
6464 virtual Firebird::string internalPrint(NodePrinter& printer) const;
6565 virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc);
6666 virtual bool setParameterType(DsqlCompilerScratch* dsqlScratch,
67 const dsc* desc, bool forceVarChar);
67 const dsc* desc, ValueExprNode* node, bool forceVarChar);
6868 virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
6969 virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier) const;
7070
439439 case blr_between:
440440 {
441441 // Try to force arg1 to be same type as arg2 eg: ? = FIELD case
442 PASS1_set_parameter_type(dsqlScratch, node->arg1, procArg2, false);
442 PASS1_set_parameter_type(dsqlScratch, node->arg1, NULL, procArg2, false);
443443
444444 // Try to force arg2 to be same type as arg1 eg: FIELD = ? case
445445 // Try even when the above call succeeded, because "arg2" may
446446 // have arg-expressions that should be resolved.
447 PASS1_set_parameter_type(dsqlScratch, procArg2, node->arg1, false);
447 PASS1_set_parameter_type(dsqlScratch, procArg2, NULL, node->arg1, false);
448448
449449 // X BETWEEN Y AND ? case
450 if (!PASS1_set_parameter_type(dsqlScratch, node->arg3, node->arg1, false))
450 if (!PASS1_set_parameter_type(dsqlScratch, node->arg3, NULL, node->arg1, false))
451451 {
452452 // ? BETWEEN Y AND ? case
453 PASS1_set_parameter_type(dsqlScratch, node->arg3, procArg2, false);
453 PASS1_set_parameter_type(dsqlScratch, node->arg3, NULL, procArg2, false);
454454 }
455455
456456 break;
461461 case blr_similar:
462462 case blr_starting:
463463 // Try to force arg1 to be same type as arg2 eg: ? LIKE FIELD case
464 PASS1_set_parameter_type(dsqlScratch, node->arg1, procArg2, true);
464 PASS1_set_parameter_type(dsqlScratch, node->arg1, NULL, procArg2, true);
465465
466466 // Try to force arg2 same type as arg 1 eg: FIELD LIKE ? case
467467 // Try even when the above call succeeded, because "arg2" may
468468 // have arg-expressions that should be resolved.
469 PASS1_set_parameter_type(dsqlScratch, procArg2, node->arg1, true);
469 PASS1_set_parameter_type(dsqlScratch, procArg2, NULL, node->arg1, true);
470470
471471 // X LIKE Y ESCAPE ? case
472 PASS1_set_parameter_type(dsqlScratch, node->arg3, procArg2, true);
472 PASS1_set_parameter_type(dsqlScratch, node->arg3, NULL, procArg2, true);
473473 }
474474
475475 return node;
12871287 ComparativeBoolNode* cmpNode = FB_NEW_POOL(getPool()) ComparativeBoolNode(getPool(), blrOp,
12881288 doDsqlPass(dsqlScratch, arg1, false), rse->dsqlSelectList->items[0]);
12891289
1290 PASS1_set_parameter_type(dsqlScratch, cmpNode->arg1, cmpNode->arg2, false);
1290 PASS1_set_parameter_type(dsqlScratch, cmpNode->arg1, NULL, cmpNode->arg2, false);
12911291
12921292 rse->dsqlWhere = cmpNode;
12931293
13381338 MissingBoolNode* node = FB_NEW_POOL(getPool()) MissingBoolNode(getPool(),
13391339 doDsqlPass(dsqlScratch, arg));
13401340
1341 PASS1_set_parameter_type(dsqlScratch, node->arg, (dsc*) NULL, false);
1341 PASS1_set_parameter_type(dsqlScratch, node->arg, NULL, NULL, false);
13421342
13431343 dsc desc;
13441344 MAKE_desc(dsqlScratch, &desc, node->arg);
448448 }
449449
450450 bool ArithmeticNode::setParameterType(DsqlCompilerScratch* dsqlScratch,
451 const dsc* desc, bool forceVarChar)
452 {
453 return PASS1_set_parameter_type(dsqlScratch, arg1, desc, forceVarChar) |
454 PASS1_set_parameter_type(dsqlScratch, arg2, desc, forceVarChar);
451 const dsc* desc, ValueExprNode* node, bool forceVarChar)
452 {
453 return PASS1_set_parameter_type(dsqlScratch, arg1, desc, node, forceVarChar) |
454 PASS1_set_parameter_type(dsqlScratch, arg2, desc, node, forceVarChar);
455455 }
456456
457457 void ArithmeticNode::genBlr(DsqlCompilerScratch* dsqlScratch)
26772677 node->dsqlField = dsqlField;
26782678
26792679 DDL_resolve_intl_type(dsqlScratch, node->dsqlField, NULL);
2680 node->setParameterType(dsqlScratch, NULL, false);
2680 node->setParameterType(dsqlScratch, NULL, NULL, false);
26812681
26822682 MAKE_desc_from_field(&node->castDesc, node->dsqlField);
26832683 MAKE_desc(dsqlScratch, &node->source->nodDesc, node->source);
26932693 }
26942694
26952695 bool CastNode::setParameterType(DsqlCompilerScratch* /*dsqlScratch*/,
2696 const dsc* /*desc*/, bool /*forceVarChar*/)
2696 const dsc* /*desc*/, ValueExprNode* /*node*/, bool /*forceVarChar*/)
26972697 {
26982698 // ASF: Attention: CastNode::dsqlPass calls us with NULL node.
26992699
29212921 CoalesceNode* node = FB_NEW_POOL(getPool()) CoalesceNode(getPool(),
29222922 doDsqlPass(dsqlScratch, args));
29232923 node->make(dsqlScratch, &node->nodDesc); // Set descriptor for output node.
2924 node->setParameterType(dsqlScratch, &node->nodDesc, false);
2924 node->setParameterType(dsqlScratch, &node->nodDesc, NULL, false);
29252925 return node;
29262926 }
29272927
29312931 }
29322932
29332933 bool CoalesceNode::setParameterType(DsqlCompilerScratch* dsqlScratch,
2934 const dsc* desc, bool /*forceVarChar*/)
2934 const dsc* desc, ValueExprNode* node, bool /*forceVarChar*/)
29352935 {
29362936 bool ret = false;
29372937
29382938 for (NestConst<ValueExprNode>* ptr = args->items.begin(); ptr != args->items.end(); ++ptr)
2939 ret |= PASS1_set_parameter_type(dsqlScratch, *ptr, desc, false);
2939 {
2940 ret |= PASS1_set_parameter_type(dsqlScratch, *ptr, desc, node, false);
2941 }
29402942
29412943 return ret;
29422944 }
31373139 }
31383140
31393141 bool ConcatenateNode::setParameterType(DsqlCompilerScratch* dsqlScratch,
3140 const dsc* desc, bool forceVarChar)
3141 {
3142 return PASS1_set_parameter_type(dsqlScratch, arg1, desc, forceVarChar) |
3143 PASS1_set_parameter_type(dsqlScratch, arg2, desc, forceVarChar);
3142 const dsc* desc, ValueExprNode* node, bool forceVarChar)
3143 {
3144 return PASS1_set_parameter_type(dsqlScratch, arg1, desc, node, forceVarChar) |
3145 PASS1_set_parameter_type(dsqlScratch, arg2, desc, node, forceVarChar);
31443146 }
31453147
31463148 void ConcatenateNode::genBlr(DsqlCompilerScratch* dsqlScratch)
39143916 doDsqlPass(dsqlScratch, conditions), doDsqlPass(dsqlScratch, values));
39153917 node->label = label;
39163918 node->make(dsqlScratch, &node->nodDesc); // Set descriptor for output node.
3917 node->setParameterType(dsqlScratch, &node->nodDesc, false);
3919 node->setParameterType(dsqlScratch, &node->nodDesc, NULL, false);
39183920
39193921 // Workaround for DECODE/CASE supporting only 255 items - see CORE-5366.
39203922
39773979 }
39783980
39793981 bool DecodeNode::setParameterType(DsqlCompilerScratch* dsqlScratch,
3980 const dsc* desc, bool /*forceVarChar*/)
3982 const dsc* desc, ValueExprNode* node, bool /*forceVarChar*/)
39813983 {
39823984 // Check if there is a parameter in the test/conditions.
39833985 bool setParameters = test->is<ParameterNode>();
40214023 if (!node1Desc.isUnknown())
40224024 {
40234025 // Set parameter describe information.
4024 PASS1_set_parameter_type(dsqlScratch, test, &node1Desc, false);
4026 PASS1_set_parameter_type(dsqlScratch, test, &node1Desc, NULL, false);
40254027
40264028 for (NestConst<ValueExprNode>* ptr = conditions->items.begin();
40274029 ptr != conditions->items.end();
40284030 ++ptr)
40294031 {
4030 PASS1_set_parameter_type(dsqlScratch, *ptr, &node1Desc, false);
4032 PASS1_set_parameter_type(dsqlScratch, *ptr, &node1Desc, NULL, false);
40314033 }
40324034 }
40334035 }
40354037 bool ret = false;
40364038
40374039 for (NestConst<ValueExprNode>* ptr = values->items.begin(); ptr != values->items.end(); ++ptr)
4038 ret |= PASS1_set_parameter_type(dsqlScratch, *ptr, desc, false);
4040 {
4041 ret |= PASS1_set_parameter_type(dsqlScratch, *ptr, desc, node, false);
4042 }
40394043
40404044 return ret;
40414045 }
44784482 }
44794483
44804484 bool ExtractNode::setParameterType(DsqlCompilerScratch* dsqlScratch,
4481 const dsc* desc, bool forceVarChar)
4482 {
4483 return PASS1_set_parameter_type(dsqlScratch, arg, desc, forceVarChar);
4485 const dsc* desc, ValueExprNode* node, bool forceVarChar)
4486 {
4487 return PASS1_set_parameter_type(dsqlScratch, arg, desc, node, forceVarChar);
44844488 }
44854489
44864490 void ExtractNode::genBlr(DsqlCompilerScratch* dsqlScratch)
59976001 }
59986002
59996003 bool GenIdNode::setParameterType(DsqlCompilerScratch* dsqlScratch,
6000 const dsc* desc, bool forceVarChar)
6001 {
6002 return PASS1_set_parameter_type(dsqlScratch, arg, desc, forceVarChar);
6004 const dsc* desc, ValueExprNode* node, bool forceVarChar)
6005 {
6006 return PASS1_set_parameter_type(dsqlScratch, arg, desc, node, forceVarChar);
60036007 }
60046008
60056009 void GenIdNode::genBlr(DsqlCompilerScratch* dsqlScratch)
66956699 parameter->par_name = parameter->par_alias = "CONSTANT";
66966700 }
66976701
6698 bool LiteralNode::setParameterType(DsqlCompilerScratch* /*dsqlScratch*/,
6699 const dsc* /*desc*/, bool /*forceVarChar*/)
6700 {
6701 return false;
6702 }
6703
67046702 void LiteralNode::genBlr(DsqlCompilerScratch* dsqlScratch)
67056703 {
67066704 if (litDesc.dsc_dtype == dtype_text)
73137311 }
73147312
73157313 bool NegateNode::setParameterType(DsqlCompilerScratch* dsqlScratch,
7316 const dsc* desc, bool forceVarChar)
7317 {
7318 return PASS1_set_parameter_type(dsqlScratch, arg, desc, forceVarChar);
7314 const dsc* desc, ValueExprNode* node, bool forceVarChar)
7315 {
7316 return PASS1_set_parameter_type(dsqlScratch, arg, desc, node, forceVarChar);
73197317 }
73207318
73217319 void NegateNode::genBlr(DsqlCompilerScratch* dsqlScratch)
78867884 }
78877885
78887886 bool ParameterNode::setParameterType(DsqlCompilerScratch* dsqlScratch,
7889 const dsc* desc, bool forceVarChar)
7887 const dsc* desc, ValueExprNode* node, bool forceVarChar)
78907888 {
78917889 thread_db* tdbb = JRD_get_thread_data();
78927890
78937891 const dsc oldDesc = dsqlParameter->par_desc;
78947892
7895 if (!desc)
7893 if (!desc && !node)
78967894 dsqlParameter->par_desc.makeNullString();
78977895 else
78987896 {
7897 if (!desc)
7898 {
7899 MAKE_desc(dsqlScratch, &node->nodDesc, node);
7900 desc = &node->nodDesc;
7901 }
7902
78997903 dsqlParameter->par_desc = *desc;
79007904
79017905 if (tdbb->getCharSet() != CS_NONE && tdbb->getCharSet() != CS_BINARY)
89518955 }
89528956
89538957 bool StrCaseNode::setParameterType(DsqlCompilerScratch* dsqlScratch,
8954 const dsc* desc, bool forceVarChar)
8955 {
8956 return PASS1_set_parameter_type(dsqlScratch, arg, desc, forceVarChar);
8958 const dsc* desc, ValueExprNode* node, bool forceVarChar)
8959 {
8960 return PASS1_set_parameter_type(dsqlScratch, arg, desc, node, forceVarChar);
89578961 }
89588962
89598963 void StrCaseNode::genBlr(DsqlCompilerScratch* dsqlScratch)
91679171 }
91689172
91699173 parameter->par_name = parameter->par_alias = alias;
9170 }
9171
9172 bool StrLenNode::setParameterType(DsqlCompilerScratch* dsqlScratch,
9173 const dsc* desc, bool forceVarChar)
9174 {
9175 return false;
91769174 }
91779175
91789176 void StrLenNode::genBlr(DsqlCompilerScratch* dsqlScratch)
98939891 }
98949892
98959893 bool SubstringNode::setParameterType(DsqlCompilerScratch* dsqlScratch,
9896 const dsc* desc, bool forceVarChar)
9897 {
9898 return PASS1_set_parameter_type(dsqlScratch, expr, desc, forceVarChar) |
9899 PASS1_set_parameter_type(dsqlScratch, start, desc, forceVarChar) |
9900 PASS1_set_parameter_type(dsqlScratch, length, desc, forceVarChar);
9894 const dsc* desc, ValueExprNode* node, bool forceVarChar)
9895 {
9896 return PASS1_set_parameter_type(dsqlScratch, expr, desc, node, forceVarChar) |
9897 PASS1_set_parameter_type(dsqlScratch, start, desc, node, forceVarChar) |
9898 PASS1_set_parameter_type(dsqlScratch, length, desc, node, forceVarChar);
99019899 }
99029900
99039901 void SubstringNode::genBlr(DsqlCompilerScratch* dsqlScratch)
1022710225 }
1022810226
1022910227 bool SubstringSimilarNode::setParameterType(DsqlCompilerScratch* dsqlScratch,
10230 const dsc* desc, bool forceVarChar)
10231 {
10232 return PASS1_set_parameter_type(dsqlScratch, expr, desc, forceVarChar) |
10233 PASS1_set_parameter_type(dsqlScratch, pattern, desc, forceVarChar) |
10234 PASS1_set_parameter_type(dsqlScratch, escape, desc, forceVarChar);
10228 const dsc* desc, ValueExprNode* node, bool forceVarChar)
10229 {
10230 return PASS1_set_parameter_type(dsqlScratch, expr, desc, node, forceVarChar) |
10231 PASS1_set_parameter_type(dsqlScratch, pattern, desc, node, forceVarChar) |
10232 PASS1_set_parameter_type(dsqlScratch, escape, desc, node, forceVarChar);
1023510233 }
1023610234
1023710235 void SubstringSimilarNode::genBlr(DsqlCompilerScratch* dsqlScratch)
1041110409 doDsqlPass(dsqlScratch, escape));
1041210410
1041310411 // ? SIMILAR FIELD case.
10414 PASS1_set_parameter_type(dsqlScratch, node->expr, node->pattern, true);
10412 PASS1_set_parameter_type(dsqlScratch, node->expr, NULL, node->pattern, true);
1041510413
1041610414 // FIELD SIMILAR ? case.
10417 PASS1_set_parameter_type(dsqlScratch, node->pattern, node->expr, true);
10415 PASS1_set_parameter_type(dsqlScratch, node->pattern, NULL, node->expr, true);
1041810416
1041910417 // X SIMILAR Y ESCAPE ? case.
10420 PASS1_set_parameter_type(dsqlScratch, node->escape, node->pattern, true);
10418 PASS1_set_parameter_type(dsqlScratch, node->escape, NULL, node->pattern, true);
1042110419
1042210420 return node;
1042310421 }
1061310611 for (unsigned int i = 0; i < inList->items.getCount(); ++i)
1061410612 {
1061510613 ValueExprNode* p = inList->items[i];
10616 PASS1_set_parameter_type(dsqlScratch, p, &p->nodDesc, false);
10614 PASS1_set_parameter_type(dsqlScratch, p, &p->nodDesc, NULL, false);
1061710615 }
1061810616 }
1061910617
1066810666 doDsqlPass(dsqlScratch, value), doDsqlPass(dsqlScratch, trimChars));
1066910667
1067010668 // Try to force trimChars to be same type as value: TRIM(? FROM FIELD)
10671 PASS1_set_parameter_type(dsqlScratch, node->trimChars, node->value, false);
10669 PASS1_set_parameter_type(dsqlScratch, node->trimChars, NULL, node->value, false);
1067210670
1067310671 return node;
1067410672 }
1067910677 }
1068010678
1068110679 bool TrimNode::setParameterType(DsqlCompilerScratch* dsqlScratch,
10682 const dsc* desc, bool forceVarChar)
10683 {
10684 return PASS1_set_parameter_type(dsqlScratch, value, desc, forceVarChar) |
10685 PASS1_set_parameter_type(dsqlScratch, trimChars, desc, forceVarChar);
10680 const dsc* desc, ValueExprNode* node, bool forceVarChar)
10681 {
10682 return PASS1_set_parameter_type(dsqlScratch, value, desc, node, forceVarChar) |
10683 PASS1_set_parameter_type(dsqlScratch, trimChars, desc, node, forceVarChar);
1068610684 }
1068710685
1068810686 void TrimNode::genBlr(DsqlCompilerScratch* dsqlScratch)
1147011468 }
1147111469
1147211470 if (pos < node->dsqlFunction->udf_arguments.getCount())
11473 PASS1_set_parameter_type(dsqlScratch, *ptr, &desc, false);
11471 PASS1_set_parameter_type(dsqlScratch, *ptr, &desc, NULL, false);
1147411472 else
1147511473 {
1147611474 // We should complain here in the future! The parameter is
1166411662 doDsqlPass(dsqlScratch, trueValue),
1166511663 doDsqlPass(dsqlScratch, falseValue));
1166611664
11667 PASS1_set_parameter_type(dsqlScratch, node->trueValue, node->falseValue, false);
11668 PASS1_set_parameter_type(dsqlScratch, node->falseValue, node->trueValue, false);
11665 PASS1_set_parameter_type(dsqlScratch, node->trueValue, NULL, node->falseValue, false);
11666 PASS1_set_parameter_type(dsqlScratch, node->falseValue, NULL, node->trueValue, false);
1166911667
1167011668 return node;
1167111669 }
1167611674 }
1167711675
1167811676 bool ValueIfNode::setParameterType(DsqlCompilerScratch* dsqlScratch,
11679 const dsc* desc, bool forceVarChar)
11680 {
11681 return PASS1_set_parameter_type(dsqlScratch, trueValue, desc, forceVarChar) |
11682 PASS1_set_parameter_type(dsqlScratch, falseValue, desc, forceVarChar);
11677 const dsc* desc, ValueExprNode* node, bool forceVarChar)
11678 {
11679 return PASS1_set_parameter_type(dsqlScratch, trueValue, desc, node, forceVarChar) |
11680 PASS1_set_parameter_type(dsqlScratch, falseValue, desc, node, forceVarChar);
1168311681 }
1168411682
1168511683 void ValueIfNode::genBlr(DsqlCompilerScratch* dsqlScratch)
5050 virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
5151 virtual void setParameterName(dsql_par* parameter) const;
5252 virtual bool setParameterType(DsqlCompilerScratch* dsqlScratch,
53 const dsc* desc, bool forceVarChar);
53 const dsc* desc, ValueExprNode* node, bool forceVarChar);
5454 virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
5555 virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc);
5656
175175 virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
176176 virtual void setParameterName(dsql_par* parameter) const;
177177 virtual bool setParameterType(DsqlCompilerScratch* dsqlScratch,
178 const dsc* desc, bool forceVarChar);
178 const dsc* desc, ValueExprNode* node, bool forceVarChar);
179179 virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
180180 virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc);
181181
213213 virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
214214 virtual void setParameterName(dsql_par* parameter) const;
215215 virtual bool setParameterType(DsqlCompilerScratch* dsqlScratch,
216 const dsc* desc, bool forceVarChar);
216 const dsc* desc, ValueExprNode* node, bool forceVarChar);
217217 virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
218218 virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc);
219219
297297 virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
298298 virtual void setParameterName(dsql_par* parameter) const;
299299 virtual bool setParameterType(DsqlCompilerScratch* dsqlScratch,
300 const dsc* desc, bool forceVarChar);
300 const dsc* desc, ValueExprNode* node, bool forceVarChar);
301301 virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
302302 virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc);
303303
462462 virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
463463 virtual void setParameterName(dsql_par* parameter) const;
464464 virtual bool setParameterType(DsqlCompilerScratch* dsqlScratch,
465 const dsc* desc, bool forceVarChar);
465 const dsc* desc, ValueExprNode* node, bool forceVarChar);
466466 virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
467467 virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc);
468468
581581 virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
582582 virtual void setParameterName(dsql_par* parameter) const;
583583 virtual bool setParameterType(DsqlCompilerScratch* dsqlScratch,
584 const dsc* desc, bool forceVarChar);
584 const dsc* desc, ValueExprNode* node, bool forceVarChar);
585585 virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
586586 virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc);
587587
685685 virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
686686 virtual void setParameterName(dsql_par* parameter) const;
687687 virtual bool setParameterType(DsqlCompilerScratch* dsqlScratch,
688 const dsc* desc, bool forceVarChar);
688 const dsc* desc, ValueExprNode* node, bool forceVarChar);
689689 virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
690690 virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc);
691691
752752 virtual Firebird::string internalPrint(NodePrinter& printer) const;
753753 virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
754754 virtual void setParameterName(dsql_par* parameter) const;
755 virtual bool setParameterType(DsqlCompilerScratch* dsqlScratch,
756 const dsc* desc, bool forceVarChar);
757755 virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
758756 virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc);
759757
918916 virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
919917 virtual void setParameterName(dsql_par* parameter) const;
920918 virtual bool setParameterType(DsqlCompilerScratch* dsqlScratch,
921 const dsc* desc, bool forceVarChar);
919 const dsc* desc, ValueExprNode* node, bool forceVarChar);
922920 virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
923921 virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc);
924922
10611059 }
10621060
10631061 virtual bool setParameterType(DsqlCompilerScratch* dsqlScratch,
1064 const dsc* desc, bool forceVarChar);
1062 const dsc* desc, ValueExprNode* node, bool forceVarChar);
10651063 virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
10661064 virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc);
10671065 virtual bool dsqlMatch(const ExprNode* other, bool ignoreMapCast) const;
12681266 virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
12691267 virtual void setParameterName(dsql_par* parameter) const;
12701268 virtual bool setParameterType(DsqlCompilerScratch* dsqlScratch,
1271 const dsc* desc, bool forceVarChar);
1269 const dsc* desc, ValueExprNode* node, bool forceVarChar);
12721270 virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
12731271 virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc);
12741272
12951293 virtual Firebird::string internalPrint(NodePrinter& printer) const;
12961294 virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
12971295 virtual void setParameterName(dsql_par* parameter) const;
1298 virtual bool setParameterType(DsqlCompilerScratch* dsqlScratch,
1299 const dsc* desc, bool forceVarChar);
13001296 virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
13011297 virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc);
13021298
13821378 virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
13831379 virtual void setParameterName(dsql_par* parameter) const;
13841380 virtual bool setParameterType(DsqlCompilerScratch* dsqlScratch,
1385 const dsc* desc, bool forceVarChar);
1381 const dsc* desc, ValueExprNode* node, bool forceVarChar);
13861382 virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
13871383 virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc);
13881384
14131409 virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
14141410 virtual void setParameterName(dsql_par* parameter) const;
14151411 virtual bool setParameterType(DsqlCompilerScratch* dsqlScratch,
1416 const dsc* desc, bool forceVarChar);
1412 const dsc* desc, ValueExprNode* node, bool forceVarChar);
14171413 virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
14181414 virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc);
14191415
14711467 virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
14721468 virtual void setParameterName(dsql_par* parameter) const;
14731469 virtual bool setParameterType(DsqlCompilerScratch* dsqlScratch,
1474 const dsc* desc, bool forceVarChar);
1470 const dsc* desc, ValueExprNode* node, bool forceVarChar);
14751471 virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
14761472 virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc);
14771473
15461542 virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
15471543 virtual void setParameterName(dsql_par* parameter) const;
15481544 virtual bool setParameterType(DsqlCompilerScratch* dsqlScratch,
1549 const dsc* desc, bool forceVarChar);
1545 const dsc* desc, ValueExprNode* node, bool forceVarChar);
15501546 virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
15511547 virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc);
15521548
782782 }
783783
784784 virtual bool setParameterType(DsqlCompilerScratch* /*dsqlScratch*/,
785 const dsc* /*desc*/, bool /*forceVarChar*/)
785 const dsc* /*desc*/, ValueExprNode* /*node*/, bool /*forceVarChar*/)
786786 {
787787 return false;
788788 }
322322 dsqlValidateTarget(node->asgnTo);
323323
324324 // Try to force asgnFrom to be same type as asgnTo eg: ? = FIELD case
325 PASS1_set_parameter_type(dsqlScratch, node->asgnFrom, node->asgnTo, false);
325 PASS1_set_parameter_type(dsqlScratch, node->asgnFrom, NULL, node->asgnTo, false);
326326
327327 // Try to force asgnTo to be same type as asgnFrom eg: FIELD = ? case
328328 // Try even when the above call succeeded, because "asgnTo" may
329329 // have sub-expressions that should be resolved.
330 PASS1_set_parameter_type(dsqlScratch, node->asgnTo, node->asgnFrom, false);
330 PASS1_set_parameter_type(dsqlScratch, node->asgnTo, NULL, node->asgnFrom, false);
331331
332332 return node;
333333 }
27042704 DEV_BLKCHK(field, dsql_type_fld);
27052705 DEV_BLKCHK(*ptr, dsql_type_nod);
27062706 MAKE_desc_from_field(&desc_node, field);
2707 PASS1_set_parameter_type(dsqlScratch, *ptr, &desc_node, false);
2707 PASS1_set_parameter_type(dsqlScratch, *ptr, &desc_node, NULL, false);
27082708 }
27092709 }
27102710
39503950
39513951 newParam->type->flags |= FLD_nullable;
39523952 MAKE_desc_from_field(&desc_node, newParam->type);
3953 PASS1_set_parameter_type(dsqlScratch, temp, &desc_node, false);
3953 PASS1_set_parameter_type(dsqlScratch, temp, &desc_node, NULL, false);
39543954 } // end scope
39553955
39563956 if (param != parameters.begin())
52595259
52605260 for (FB_SIZE_T i = 0; i < assignStatements->statements.getCount(); ++i)
52615261 {
5262 if (!PASS1_set_parameter_type(dsqlScratch, orgValues[i], newValues[i], false))
5263 PASS1_set_parameter_type(dsqlScratch, newValues[i], orgValues[i], false);
5262 if (!PASS1_set_parameter_type(dsqlScratch, orgValues[i], NULL, newValues[i], false))
5263 PASS1_set_parameter_type(dsqlScratch, newValues[i], NULL, orgValues[i], false);
52645264
52655265 AssignmentNode* assign = FB_NEW_POOL(pool) AssignmentNode(pool);
52665266 assign->asgnFrom = orgValues[i];
57965796 ValueExprNode* const sub1 = orgValues[j];
57975797 ValueExprNode* const sub2 = newValues[j];
57985798
5799 if (!PASS1_set_parameter_type(dsqlScratch, sub1, sub2, false))
5800 PASS1_set_parameter_type(dsqlScratch, sub2, sub1, false);
5799 if (!PASS1_set_parameter_type(dsqlScratch, sub1, NULL, sub2, false))
5800 PASS1_set_parameter_type(dsqlScratch, sub2, NULL, sub1, false);
58015801
58025802 AssignmentNode* assign = FB_NEW_POOL(pool) AssignmentNode(pool);
58035803 assign->asgnFrom = sub1;
65686568 temp->asgnTo = *ptr;
65696569 assignStatements->statements.add(temp);
65706570
6571 PASS1_set_parameter_type(dsqlScratch, *ptr2, temp->asgnTo, false);
6571 PASS1_set_parameter_type(dsqlScratch, *ptr2, NULL, temp->asgnTo, false);
65726572 }
65736573 }
65746574
544544 {
545545 DEV_BLKCHK(field, dsql_type_fld);
546546 MAKE_desc_from_field(&desc_node, field);
547 PASS1_set_parameter_type(dsqlScratch, *input, &desc_node, false);
547 PASS1_set_parameter_type(dsqlScratch, *input, &desc_node, NULL, false);
548548 }
549549 }
550550 }
15091509 descNode.makeInt64(0);
15101510
15111511 rse->dsqlFirst = Node::doDsqlPass(dsqlScratch, firstNode, false);
1512 PASS1_set_parameter_type(dsqlScratch, rse->dsqlFirst, &descNode, false);
1512 PASS1_set_parameter_type(dsqlScratch, rse->dsqlFirst, &descNode, NULL, false);
15131513
15141514 rse->dsqlSkip = Node::doDsqlPass(dsqlScratch, skipNode, false);
1515 PASS1_set_parameter_type(dsqlScratch, rse->dsqlSkip, &descNode, false);
1515 PASS1_set_parameter_type(dsqlScratch, rse->dsqlSkip, &descNode, NULL, false);
15161516 }
15171517
15181518
28982898
28992899 // Setup the datatype of a parameter.
29002900 bool PASS1_set_parameter_type(DsqlCompilerScratch* dsqlScratch, ValueExprNode* inNode,
2901 const dsc* desc, bool force_varchar)
2902 {
2903 return inNode && inNode->setParameterType(dsqlScratch, desc, force_varchar);
2904 }
2905
2906 // Setup the datatype of a parameter.
2907 bool PASS1_set_parameter_type(DsqlCompilerScratch* dsqlScratch, ValueExprNode* inNode,
2908 ValueExprNode* node, bool force_varchar)
2909 {
2910 if (!inNode)
2911 return false;
2912
2913 MAKE_desc(dsqlScratch, &node->nodDesc, node);
2914 return inNode->setParameterType(dsqlScratch, &node->nodDesc, force_varchar);
2901 const dsc* desc, ValueExprNode* node, bool force_varchar)
2902 {
2903 return inNode && inNode->setParameterType(dsqlScratch, desc, node, force_varchar);
29152904 }
29162905
29172906
5353 Jrd::ValueListNode*, Jrd::ValueListNode*);
5454 Jrd::RecordSourceNode* PASS1_relation(Jrd::DsqlCompilerScratch*, Jrd::RecordSourceNode*);
5555 Jrd::RseNode* PASS1_rse(Jrd::DsqlCompilerScratch*, Jrd::SelectExprNode*, bool);
56 bool PASS1_set_parameter_type(Jrd::DsqlCompilerScratch*, Jrd::ValueExprNode*, const dsc*, bool);
57 bool PASS1_set_parameter_type(Jrd::DsqlCompilerScratch*, Jrd::ValueExprNode*, Jrd::ValueExprNode*, bool);
56 bool PASS1_set_parameter_type(Jrd::DsqlCompilerScratch*, Jrd::ValueExprNode*, const dsc*, Jrd::ValueExprNode*, bool);
5857 Jrd::ValueListNode* PASS1_sort(Jrd::DsqlCompilerScratch*, Jrd::ValueListNode*, Jrd::ValueListNode*);
5958
6059 #endif // DSQL_PASS1_PROTO_H
509509 }
510510
511511 if (sort)
512 analyzeNavigation();
512 analyzeNavigation(inversions);
513513
514514 #ifdef OPT_DEBUG_RETRIEVAL
515515 // Debug
608608 if (!navigationCandidate)
609609 return NULL;
610610
611 IndexScratch* const scratch = navigationCandidate->scratch;
612
611613 // Looks like we can do a navigational walk. Flag that
612614 // we have used this index for navigation, and allocate
613615 // a navigational rsb for it.
614 navigationCandidate->idx->idx_runtime_flags |= idx_navigate;
616 scratch->idx->idx_runtime_flags |= idx_navigate;
615617
616618 const USHORT key_length =
617 ROUNDUP(BTR_key_length(tdbb, relation, navigationCandidate->idx), sizeof(SLONG));
618
619 InversionNode* const index_node = makeIndexScanNode(navigationCandidate);
619 ROUNDUP(BTR_key_length(tdbb, relation, scratch->idx), sizeof(SLONG));
620
621 InversionNode* const index_node = makeIndexScanNode(scratch);
620622
621623 return FB_NEW_POOL(*tdbb->getDefaultPool())
622624 IndexTableScan(csb, getAlias(), stream, relation, index_node, key_length);
623625 }
624626
625 void OptimizerRetrieval::analyzeNavigation()
627 void OptimizerRetrieval::analyzeNavigation(const InversionCandidateList& inversions)
626628 {
627629 /**************************************
628630 *
799801 if (!usableIndex)
800802 continue;
801803
804 // Lookup the inversion candidate matching our navigational index
805
806 InversionCandidate* candidate = NULL;
807
808 for (InversionCandidate* const* iter = inversions.begin();
809 iter != inversions.end(); ++iter)
810 {
811 if ((*iter)->scratch == indexScratch)
812 {
813 candidate = *iter;
814 break;
815 }
816 }
817
818 if (candidate && !optimizer->optimizeFirstRows)
819 {
820 // Check whether the navigational index has any matches shared with other inversion
821 // candidates. If so, compare inversions and decide whether navigation is acceptable.
822
823 for (const InversionCandidate* const* iter = inversions.begin();
824 iter != inversions.end(); ++iter)
825 {
826 const InversionCandidate* const otherCandidate = *iter;
827
828 if (otherCandidate != candidate)
829 {
830 for (BoolExprNode* const* iter2 = otherCandidate->matches.begin();
831 iter2 != otherCandidate->matches.end(); ++iter2)
832 {
833 if (candidate->matches.exist(*iter2))
834 {
835 usableIndex = betterInversion(candidate, otherCandidate);
836 break;
837 }
838 }
839 }
840
841 if (!usableIndex)
842 break;
843 }
844 }
845
846 if (!usableIndex)
847 continue;
848
802849 // Looks like we can do a navigational walk. Remember this candidate
803850 // and compare it against other possible candidates.
804851
852 if (!candidate)
853 {
854 // If no inversion candidate is found, create a fake one representing full index scan
855
856 candidate = FB_NEW_POOL(pool) InversionCandidate(pool);
857 candidate->cost = indexScratch->cardinality;
858 candidate->indexes = 1;
859 candidate->scratch = indexScratch;
860 candidate->nonFullMatchedSegments = (int) indexScratch->segments.getCount();
861 }
862
805863 if (!navigationCandidate)
806 navigationCandidate = indexScratch;
807 else
808 {
809 int count1 = MAX(indexScratch->lowerCount, indexScratch->upperCount);
810 int count2 = MAX(navigationCandidate->lowerCount, navigationCandidate->upperCount);
811
812 if (count1 > count2)
813 navigationCandidate = indexScratch;
814 else if (count1 == count2)
815 {
816 count1 = (int) indexScratch->segments.getCount();
817 count2 = (int) navigationCandidate->segments.getCount();
818
819 if (count1 < count2)
820 navigationCandidate = indexScratch;
821 else if (count1 == count2)
864 navigationCandidate = candidate;
865 else if (betterInversion(candidate, navigationCandidate))
866 navigationCandidate = candidate;
867 }
868 }
869
870 bool OptimizerRetrieval::betterInversion(const InversionCandidate* inv1, const InversionCandidate* inv2) const
871 {
872 // Return true if inversion1 is *better* than inversion2.
873 // It's mostly about the retrieval cost, but other aspects are also taken into account.
874
875 if (inv1->unique && !inv2->unique)
876 {
877 // A unique full equal match is better than anything else.
878 return true;
879 }
880
881 if (inv1->unique == inv2->unique)
882 {
883 if (inv1->dependencies > inv2->dependencies)
884 {
885 // Index used for a relationship must be always prefered to
886 // the filtering ones, otherwise the nested loop join has
887 // no chances to be better than a sort merge.
888 // An alternative (simplified) condition might be:
889 // currentInv->dependencies > 0
890 // && bestCandidate->dependencies == 0
891 // but so far I tend to think that the current one is better.
892 return true;
893 }
894
895 if (inv1->dependencies == inv2->dependencies)
896 {
897 const double cardinality =
898 MAX(csb->csb_rpt[stream].csb_cardinality, MINIMUM_CARDINALITY);
899
900 const double cost1 =
901 inv1->cost + (inv1->selectivity * cardinality);
902 const double cost2 =
903 inv2->cost + (inv2->selectivity * cardinality);
904
905 // Do we have very similar costs?
906 double diffCost = 0;
907 if (!cost1 && !cost2)
908 {
909 // Two zero costs should be handled as being the same
910 // (other comparison criteria should be applied, see below).
911 diffCost = 1;
912 }
913 else if (cost1)
914 {
915 // Calculate the difference
916 diffCost = cost2 / cost1;
917 }
918
919 if ((diffCost >= 0.98) && (diffCost <= 1.02))
920 {
921 // If the "same" costs then compare with the nr of unmatched segments,
922 // how many indexes and matched segments. First compare number of indexes.
923 int compareSelectivity = (inv1->indexes - inv2->indexes);
924
925 if (compareSelectivity == 0)
822926 {
823 count1 = BTR_key_length(tdbb, relation, indexScratch->idx);
824 count2 = BTR_key_length(tdbb, relation, navigationCandidate->idx);
825
826 if (count1 < count2)
827 navigationCandidate = indexScratch;
927 // For the same number of indexes compare number of matched segments.
928 // Note the inverted condition: the more matched segments the better.
929 compareSelectivity =
930 (inv2->matchedSegments - inv1->matchedSegments);
931
932 if (compareSelectivity == 0)
933 {
934 // For the same number of matched segments
935 // compare ones that aren't full matched
936 compareSelectivity =
937 (inv1->nonFullMatchedSegments - inv2->nonFullMatchedSegments);
938 }
828939 }
829 }
830 }
831 }
940
941 if (compareSelectivity < 0)
942 return true;
943 }
944 else if (cost1 < cost2)
945 return true;
946 }
947 }
948
949 return false;
832950 }
833951
834952 void OptimizerRetrieval::getInversionCandidates(InversionCandidateList* inversions,
12581376 // Force to always choose at least one index
12591377 bool firstCandidate = true;
12601378
1261 FB_SIZE_T i = 0;
12621379 InversionCandidate* invCandidate = NULL;
1263 InversionCandidate** inversion = inversions->begin();
1264 for (i = 0; i < inversions->getCount(); i++)
1265 {
1266 inversion[i]->used = false;
1267 const IndexScratch* const indexScratch = inversion[i]->scratch;
1380
1381 for (InversionCandidate** iter = inversions->begin();
1382 iter != inversions->end(); ++iter)
1383 {
1384 InversionCandidate* const inversion = *iter;
1385
1386 inversion->used = (inversion == navigationCandidate);
1387
1388 const IndexScratch* const indexScratch = inversion->scratch;
12681389
12691390 if (indexScratch &&
1270 (indexScratch == navigationCandidate ||
1271 (indexScratch->idx->idx_runtime_flags & idx_plan_dont_use)))
1272 {
1273 inversion[i]->used = true;
1391 (indexScratch->idx->idx_runtime_flags & idx_plan_dont_use))
1392 {
1393 inversion->used = true;
12741394 }
12751395 }
12761396
12771397 // The matches returned in this inversion are always sorted.
1278 SortedArray<BoolExprNode*> matches, navigationMatches;
1398 SortedArray<BoolExprNode*> matches;
12791399
12801400 if (navigationCandidate)
12811401 {
1282 const int matchedSegments =
1283 MAX(navigationCandidate->lowerCount, navigationCandidate->upperCount);
1284
1285 fb_assert(matchedSegments <= (int) navigationCandidate->segments.getCount());
1286
1287 for (int segno = 0; segno < matchedSegments; segno++)
1288 {
1289 const IndexScratchSegment* const segment = navigationCandidate->segments[segno];
1290
1291 for (FB_SIZE_T j = 0; j < segment->matches.getCount(); j++)
1292 {
1293 if (!navigationMatches.exist(segment->matches[j]))
1294 navigationMatches.add(segment->matches[j]);
1295 }
1296 }
1297
1298 matches.join(navigationMatches);
1299
1300 // If the navigational candidate includes any matching segments,
1301 // reset the selectivity/cost prerequisites to account these matches
1302 if (matchedSegments)
1303 {
1304 totalSelectivity = navigationCandidate->selectivity;
1305 totalIndexCost = DEFAULT_INDEX_COST + totalSelectivity * navigationCandidate->cardinality;
1306 previousTotalCost = totalIndexCost + totalSelectivity * streamCardinality;
1402 matches.join(navigationCandidate->matches);
1403
1404 // Reset the selectivity/cost prerequisites to account the navigational candidate
1405 totalSelectivity = navigationCandidate->selectivity;
1406 totalIndexCost = navigationCandidate->cost;
1407 previousTotalCost = totalIndexCost + totalSelectivity * streamCardinality;
1408
1409 if (navigationCandidate->matchedSegments)
13071410 firstCandidate = false;
1308 }
1309 }
1310
1311 for (i = 0; i < inversions->getCount(); i++)
1411 }
1412
1413 for (FB_SIZE_T i = 0; i < inversions->getCount(); i++)
13121414 {
13131415 // Initialize vars before walking through candidates
13141416 InversionCandidate* bestCandidate = NULL;
13161418
13171419 for (FB_SIZE_T currentPosition = 0; currentPosition < inversions->getCount(); ++currentPosition)
13181420 {
1319 InversionCandidate* currentInv = inversion[currentPosition];
1421 InversionCandidate* currentInv = (*inversions)[currentPosition];
13201422 if (!currentInv->used)
13211423 {
13221424 // If this is a unique full equal matched inversion we're done, so
13231425 // we can make the inversion and return it.
1324 if (currentInv->unique && currentInv->dependencies && !currentInv->condition &&
1325 currentInv->scratch != navigationCandidate)
1426 if (currentInv->unique && currentInv->dependencies && !currentInv->condition)
13261427 {
13271428 if (!invCandidate)
13281429 invCandidate = FB_NEW_POOL(pool) InversionCandidate(pool);
13671468 if (matches.exist(currentInv->matches[k]))
13681469 {
13691470 anyMatchAlreadyUsed = true;
1370 if (navigationMatches.exist(currentInv->matches[k]))
1471
1472 if (navigationCandidate &&
1473 navigationCandidate->matches.exist(currentInv->matches[k]))
1474 {
13711475 matchUsedByNavigation = true;
1476 }
1477
13721478 break;
13731479 }
13741480 }
13761482 if (anyMatchAlreadyUsed && !customPlan)
13771483 {
13781484 currentInv->used = true;
1485
13791486 if (matchUsedByNavigation)
13801487 continue;
1488
13811489 // If a match on this index was already used by another
13821490 // index, add also the other matches from this index.
13831491 for (FB_SIZE_T j = 0; j < currentInv->matches.getCount(); j++)
13851493 if (!matches.exist(currentInv->matches[j]))
13861494 matches.add(currentInv->matches[j]);
13871495 }
1496
13881497 // Restart loop, because other indexes could also be excluded now.
13891498 restartLoop = true;
13901499 break;
14121521 break;
14131522 }
14141523
1415 if (currentInv->unique && !bestCandidate->unique)
1416 {
1417 // A unique full equal match is better than anything else.
1524 if (betterInversion(currentInv, bestCandidate))
14181525 bestCandidate = currentInv;
1419 }
1420 else if (currentInv->unique == bestCandidate->unique)
1421 {
1422 if (currentInv->dependencies > bestCandidate->dependencies)
1423 {
1424 // Index used for a relationship must be always prefered to
1425 // the filtering ones, otherwise the nested loop join has
1426 // no chances to be better than a sort merge.
1427 // An alternative (simplified) condition might be:
1428 // currentInv->dependencies > 0
1429 // && bestCandidate->dependencies == 0
1430 // but so far I tend to think that the current one is better.
1431 bestCandidate = currentInv;
1432 }
1433 else if (currentInv->dependencies == bestCandidate->dependencies)
1434 {
1435
1436 const double bestCandidateCost =
1437 bestCandidate->cost + (bestCandidate->selectivity * streamCardinality);
1438 const double currentCandidateCost =
1439 currentInv->cost + (currentInv->selectivity * streamCardinality);
1440
1441 // Do we have very similar costs?
1442 double diffCost = currentCandidateCost;
1443 if (!diffCost && !bestCandidateCost)
1444 {
1445 // Two zero costs should be handled as being the same
1446 // (other comparison criteria should be applied, see below).
1447 diffCost = 1;
1448 }
1449 else if (diffCost)
1450 {
1451 // Calculate the difference.
1452 diffCost = bestCandidateCost / diffCost;
1453 }
1454 else {
1455 diffCost = 0;
1456 }
1457
1458 if ((diffCost >= 0.98) && (diffCost <= 1.02))
1459 {
1460 // If the "same" costs then compare with the nr of unmatched segments,
1461 // how many indexes and matched segments. First compare number of indexes.
1462 int compareSelectivity = (currentInv->indexes - bestCandidate->indexes);
1463 if (compareSelectivity == 0)
1464 {
1465 // For the same number of indexes compare number of matched segments.
1466 // Note the inverted condition: the more matched segments the better.
1467 compareSelectivity =
1468 (bestCandidate->matchedSegments - currentInv->matchedSegments);
1469 if (compareSelectivity == 0)
1470 {
1471 // For the same number of matched segments
1472 // compare ones that aren't full matched
1473 compareSelectivity =
1474 (currentInv->nonFullMatchedSegments - bestCandidate->nonFullMatchedSegments);
1475 }
1476 }
1477 if (compareSelectivity < 0) {
1478 bestCandidate = currentInv;
1479 }
1480 }
1481 else if (currentCandidateCost < bestCandidateCost)
1482 {
1483 // How lower the cost the better.
1484 bestCandidate = currentInv;
1485 }
1486 }
1487 }
14881526 }
14891527 }
14901528 }
16361674
16371675 // If we have no index used for filtering, but there's a navigational walk,
16381676 // set up the inversion candidate appropriately.
1677
16391678 if (navigationCandidate)
16401679 {
16411680 if (!invCandidate)
16421681 invCandidate = FB_NEW_POOL(pool) InversionCandidate(pool);
16431682
1683 invCandidate->unique = navigationCandidate->unique;
16441684 invCandidate->selectivity *= navigationCandidate->selectivity;
1645 invCandidate->cost += DEFAULT_INDEX_COST +
1646 navigationCandidate->cardinality * navigationCandidate->selectivity;
1685 invCandidate->cost += navigationCandidate->cost;
16471686 ++invCandidate->indexes;
16481687 invCandidate->navigated = true;
16491688 }
16501689
1651 if (invCandidate && matches.getCount())
1690 if (invCandidate)
16521691 invCandidate->matches.join(matches);
16531692
16541693 return invCandidate;
179179 IndexTableScan* getNavigation();
180180
181181 protected:
182 void analyzeNavigation();
182 void analyzeNavigation(const InversionCandidateList& inversions);
183 bool betterInversion(const InversionCandidate* inv1, const InversionCandidate* inv2) const;
183184 InversionNode* composeInversion(InversionNode* node1, InversionNode* node2,
184185 InversionNode::Type node_type) const;
185186 const Firebird::string& getAlias();
221222 bool outerFlag;
222223 bool createIndexScanNodes;
223224 bool setConjunctionsMatched;
224 IndexScratch* navigationCandidate;
225 InversionCandidate* navigationCandidate;
225226 };
226227
227228 class IndexRelationship
22 *** DO NOT EDIT ***
33 TO CHANGE ANY INFORMATION IN HERE PLEASE
44 EDIT src/misc/writeBuildNum.sh
5 FORMAL BUILD NUMBER:33077
5 FORMAL BUILD NUMBER:33083
66 */
77
8 #define PRODUCT_VER_STRING "3.0.5.33077"
9 #define FILE_VER_STRING "WI-V3.0.5.33077"
10 #define LICENSE_VER_STRING "WI-V3.0.5.33077"
11 #define FILE_VER_NUMBER 3, 0, 5, 33077
8 #define PRODUCT_VER_STRING "3.0.5.33083"
9 #define FILE_VER_STRING "WI-V3.0.5.33083"
10 #define LICENSE_VER_STRING "WI-V3.0.5.33083"
11 #define FILE_VER_NUMBER 3, 0, 5, 33083
1212 #define FB_MAJOR_VER "3"
1313 #define FB_MINOR_VER "0"
1414 #define FB_REV_NO "5"
15 #define FB_BUILD_NO "33077"
15 #define FB_BUILD_NO "33083"
1616 #define FB_BUILD_TYPE "V"
1717 #define FB_BUILD_SUFFIX "Firebird 3.0"
12961296 if (!*object_name)
12971297 return 0;
12981298
1299 const Jrd::SecurityClass* s_class = SCL_recompute_class(tdbb, object_name);
1299 const Jrd::SecurityClass* s_class = SCL_get_class(tdbb, object_name);
13001300 if (s_class)
13011301 return s_class->scl_flags;
13021302
88 MajorVer=3
99 MinorVer=0
1010 RevNo=5
11 BuildNum=33077
11 BuildNum=33083
1212
1313 NowAt=`pwd`
1414 cd `dirname $0`
639639 &authPort->port_srv_auth_block->authBlockWriter);
640640 authPort->port_srv_auth_block->setPluginName(authItr->name());
641641
642 if (forceNext)
643 flags = NO_FLAGS;
644
642645 cstring* s;
643646
644647 switch (authResult)