浏览代码

Fix gh-1169 Allow user to supply hint for num rows

- Extended the hint syntax to allow identifiers as the parameters to
  hints.
- Added hint(output(tiny|group|few|memory|[m]..n) to allow an
  indication of the number of output records.
- E.g., JOIN(a,b,left.x=right.y,hint(output(0..2000)));

Signed-off-by: Gavin Halliday <gavin.halliday@lexisnexis.com>
Gavin Halliday 13 年之前
父节点
当前提交
ed2883fa7d
共有 6 个文件被更改,包括 66 次插入6 次删除
  1. 4 0
      ecl/hql/hqlatoms.cpp
  2. 2 0
      ecl/hql/hqlatoms.hpp
  3. 45 1
      ecl/hql/hqlattr.cpp
  4. 10 2
      ecl/hql/hqlgram.y
  5. 3 1
      ecl/hqlcpp/hqlhtcpp.cpp
  6. 2 2
      ecl/regress/hint3.ecl

+ 4 - 0
ecl/hql/hqlatoms.cpp

@@ -206,6 +206,7 @@ _ATOM _metadata_Atom;
 _ATOM methodAtom;
 _ATOM minAtom;
 _ATOM minimalAtom;
+_ATOM memoryAtom;
 _ATOM moduleAtom;
 _ATOM mofnAtom;
 _ATOM nameAtom;
@@ -340,6 +341,7 @@ _ATOM thresholdAtom;
 _ATOM timeoutAtom;
 _ATOM timeLimitAtom;
 _ATOM timestampAtom;
+_ATOM tinyAtom;
 _ATOM trimAtom;
 _ATOM trueAtom;
 _ATOM tomitaAtom;
@@ -577,6 +579,7 @@ MODULE_INIT(INIT_PRIORITY_HQLATOM)
     MAKEATOM(maxCount);
     MAKEATOM(maxLength);
     MAKEATOM(maxSize);
+    MAKEATOM(memory);
     MAKEATOM(merge);
     MAKEATOM(mergeTransform);
     MAKESYSATOM(metadata);
@@ -716,6 +719,7 @@ MODULE_INIT(INIT_PRIORITY_HQLATOM)
     MAKEATOM(timeout);
     MAKEATOM(timeLimit);
     MAKEATOM(timestamp);
+    MAKEATOM(tiny);
     MAKEATOM(tomita);
     MAKEATOM(top);
     MAKEATOM(trim);

+ 2 - 0
ecl/hql/hqlatoms.hpp

@@ -204,6 +204,7 @@ extern HQL_API _ATOM maxAtom;
 extern HQL_API _ATOM maxCountAtom;
 extern HQL_API _ATOM maxLengthAtom;
 extern HQL_API _ATOM maxSizeAtom;
+extern HQL_API _ATOM memoryAtom;
 extern HQL_API _ATOM mergeAtom;
 extern HQL_API _ATOM mergeTransformAtom;
 extern HQL_API _ATOM _metadata_Atom;
@@ -344,6 +345,7 @@ extern HQL_API _ATOM thresholdAtom;
 extern HQL_API _ATOM timeoutAtom;
 extern HQL_API _ATOM timeLimitAtom;
 extern HQL_API _ATOM timestampAtom;
+extern HQL_API _ATOM tinyAtom;
 extern HQL_API _ATOM tomitaAtom;
 extern HQL_API _ATOM topAtom;
 extern HQL_API _ATOM trimAtom;

+ 45 - 1
ecl/hql/hqlattr.cpp

@@ -2123,6 +2123,7 @@ public:
     void applyChoosen(__int64 limit, bool isLocal);
     void combineAlternatives(const HqlRowCountInfo & other);
     void combineBoth(const HqlRowCountInfo & other);
+    bool extractHint(IHqlExpression * hint);
     void limitMin(__int64 value);
     void setEstimate(__int64 n);
     void scaleFixed(__int64 scale);
@@ -2223,6 +2224,45 @@ void HqlRowCountInfo::combineBoth(const HqlRowCountInfo & other)
         magnitude = other.magnitude;
 }
 
+bool HqlRowCountInfo::extractHint(IHqlExpression * hint)
+{
+    IHqlExpression * arg = hint->queryChild(0);
+    if (!arg)
+        return false;
+    switch (arg->getOperator())
+    {
+    case no_constant:
+        setN(getIntValue(arg));
+        return true;
+    case no_rangeto:
+        setRange(0, getIntValue(arg->queryChild(0)));
+        return true;
+    case no_range:
+        setRange(getIntValue(arg->queryChild(0)), getIntValue(arg->queryChild(1)));
+        return true;
+    case no_attr:
+        {
+            _ATOM name = arg->queryName();
+            RowCountMagnitude magnitude = RCMnone;
+            if (name == tinyAtom)
+                magnitude = RCMtiny;
+            else if (name == groupAtom)
+                magnitude = RCMgroup;
+            else if (name == fewAtom)
+                magnitude = RCMfew;
+            else if (name == memoryAtom)
+                magnitude = RCMmemory;
+            if (magnitude != RCMnone)
+            {
+                setUnknown(magnitude);
+                return true;
+            }
+            break;
+        }
+    }
+    return false;
+}
+
 void HqlRowCountInfo::getText(StringBuffer & text) const
 {
     min->queryValue()->generateECL(text);
@@ -2305,6 +2345,10 @@ void retrieveRowInformation(HqlRowCountInfo & info, IHqlExpression * expr)
 IHqlExpression * calcRowInformation(IHqlExpression * expr)
 {
     HqlRowCountInfo info;
+    IHqlExpression * hint = queryHint(expr, outputAtom);
+    if (hint && info.extractHint(hint))
+        return info.createRecordCountAttr();
+
     IHqlExpression * ds = expr->queryChild(0);
     node_operator op  = expr->getOperator();
     switch (op)
@@ -2822,7 +2866,7 @@ IHqlExpression * calcRowInformation(IHqlExpression * expr)
 }
 
 static IHqlExpression * evaluateAttrRecordCount(IHqlExpression * expr) 
-{ 
+{
     IHqlExpression * info = calcRowInformation(expr);
     return meta.addAttributeOwn(expr, info);
 }

+ 10 - 2
ecl/hql/hqlgram.y

@@ -2775,12 +2775,12 @@ hintList
     ;
 
 hintItem
-    : UNKNOWN_ID
+    : hintName
                         {
                             $$.setExpr(createExprAttribute($1.getName()));
                             $$.setPosition($1);
                         }
-    | UNKNOWN_ID '(' beginList hintExprList ')'
+    | hintName '(' beginList hintExprList ')'
                         {
                             HqlExprArray args;
                             parser->endList(args);
@@ -2789,6 +2789,10 @@ hintItem
                         }
     ;
 
+hintName
+    : UNKNOWN_ID
+    | OUTPUT            {   $$.setName(outputAtom); }
+    ;
 
 hintExprList
     : hintExpr
@@ -2824,6 +2828,10 @@ hintExpr
                             parser->normalizeExpression($1);
                             $$.setExpr(createValue(no_rangefrom, makeNullType(), $1.getExpr()));
                         }
+    | UNKNOWN_ID
+                        {
+                            $$.setExpr(createAttribute($1.getName()), $1);
+                        }
     ;
 
 expireAttr

+ 3 - 1
ecl/hqlcpp/hqlhtcpp.cpp

@@ -80,7 +80,6 @@
 //#define _SR6_
 
 #define MAX_CSV_RECORD_SIZE     4096
-#define MIN_HEADER_SIZE 225  // Stolen from Hozed sources
 
 #define ECLRTL_LIB          "eclrtl"
 
@@ -2018,6 +2017,9 @@ static void expandHintValue(StringBuffer & s, IHqlExpression * expr)
             s.append("]");
             break;
         }
+    case no_attr:
+        s.append(expr->queryName());
+        break;
     default:
         s.append("?");
         break;

+ 2 - 2
ecl/regress/hint3.ecl

@@ -28,5 +28,5 @@ integer2        age := 25;
 namesTable := dataset('names', namesRecord, thor);
 
 s1 := sort(namesTable, surname, forename);
-j1 := join(s1, s1, left.surname = right.surname and left.forename = right.forename, hint(spill));
-output(sort(j1, age));
+j1 := join(s1, s1, left.surname = right.surname and left.forename = right.forename, hint(spill),hint(output(few)));
+output(sort(j1, age, hint(output(10..20))));