bool isSelectSortedTop(IHqlExpression * selectExpr) { IHqlExpression * index = selectExpr->queryChild(1); if (matchesConstantValue(index, 1)) { IHqlExpression * ds = selectExpr->queryChild(0); return ((ds->getOperator() == no_sort) || (ds->getOperator() == no_topn)); } return false; }
ForEachChild(i, record) { IHqlExpression * cur = record->queryChild(i); switch (cur->getOperator()) { case no_record: //MORE: If this is a public symbol it should be expanded, otherwise it will be elsewhere. expandRecordSymbolsMeta(metaTree, cur); break; case no_field: { IPropertyTree * field = metaTree->addPropTree("Field"); field->setProp("@name", str(cur->queryId())); StringBuffer ecltype; cur->queryType()->getECLType(ecltype); field->setProp("@type", ecltype); break; } case no_ifblock: { IPropertyTree * block = metaTree->addPropTree("IfBlock"); expandRecordSymbolsMeta(block, cur->queryChild(1)); break; } case no_attr: case no_attr_link: case no_attr_expr: { IPropertyTree * attr = metaTree->addPropTree("Attr"); attr->setProp("@name", str(cur->queryName())); break; } } }
ForEachItemIn(i2, expandedOrder) { IHqlExpression * cur = &expandedOrder.item(i2); if (explicitStepped) { if (!extractCondition(stepArgs, cur)) { StringBuffer s; if (cur->getOperator() == no_select) s.append(cur->queryChild(1)->queryName()); else getExprECL(cur, s); throwError1(HQLERR_SteppingNotMatchSortCondition, s.str()); } if (stepArgs.ordinality() == 0) break; } else { if (!extractCondition(args, cur)) break; foundStepped = true; } if (compareLhs) break; }
ForEachChild(i, record) { IHqlExpression * cur = record->queryChild(i); switch (cur->getOperator()) { case no_record: expandFieldNames(errorProcessor, out, cur, prefix, sep, formatFunc); break; case no_ifblock: expandFieldNames(errorProcessor, out, cur->queryChild(1), prefix, sep, formatFunc); break; case no_field: { StringBuffer lowerName; lowerName.append(cur->queryName()).toLowerCase(); if (formatFunc) { HqlExprArray args; args.append(*createConstant(lowerName.str())); OwnedHqlExpr bound = createBoundFunction(NULL, formatFunc, args, NULL, true); OwnedHqlExpr folded = foldHqlExpression(errorProcessor, bound, NULL, HFOthrowerror|HFOfoldimpure|HFOforcefold); assertex(folded->queryValue()); lowerName.clear(); getStringValue(lowerName, folded); } switch (cur->queryType()->getTypeCode()) { case type_record: case type_row: { unsigned len = prefix.length(); prefix.append(lowerName).append("."); expandFieldNames(errorProcessor, out, cur->queryRecord(), prefix, sep, formatFunc); prefix.setLength(len); break; } default: { if (out.length()) out.append(sep); out.append(prefix).append(lowerName); break; } } break; } } }
IHqlExpression* HqlGram::processAbstractDataset(IHqlExpression* _expr, IHqlExpression* formal, IHqlExpression* actual, IHqlExpression * mapping, const attribute& errpos, bool errorIfNotFound, bool & hadError) { LinkedHqlExpr transformed = _expr; IHqlExpression* formalRecord = formal->queryRecord(); IHqlExpression* actualRecord = actual->queryRecord(); assertex(formalRecord && actualRecord); hadError = false; IHqlSimpleScope *actualScope = actualRecord->querySimpleScope(); unsigned numChildren = formalRecord->numChildren(); for (unsigned idx = 0; idx < numChildren; idx++) { IHqlExpression* kid = formalRecord->queryChild(idx); if ((kid->getOperator() == no_ifblock) || kid->isAttribute()) continue; IIdAtom * name = kid->queryId(); IIdAtom * mapto = fieldMapTo(mapping, name); OwnedHqlExpr match = actualScope->lookupSymbol(mapto); if (match) { if (!kid->queryType()->assignableFrom(match->queryType())) { StringBuffer fromType, toType; getFriendlyTypeStr(kid,fromType); getFriendlyTypeStr(match,toType); reportError(ERR_DSPARAM_TYPEMISMATCH, errpos, "Can not mapping type %s(field '%s') to %s(field '%s')", fromType.str(), str(kid->queryName()), toType.str(), str(match->queryName())); hadError = true; } //MORE: This should really be mapped in a single go if (transformed) transformed.setown(bindField(transformed, kid, match)); } else if (errorIfNotFound) { reportError(ERR_DSPARM_MISSINGFIELD,errpos,"Dataset %s has no field named '%s'", str(actual->queryName()), str(mapto)); hadError = true; } } return transformed.getClear(); }
IHqlExpression * HqlCppCaseInfo::buildIndexedMap(BuildCtx & ctx, IHqlExpression * test, unsigned lower, unsigned upper) { ITypeInfo * compareType = test->queryType()->queryPromotedType(); type_t compareTypeCode = compareType->getTypeCode(); HqlExprArray values; IHqlExpression * dft = queryActiveTableSelector(); // value doesn't matter as long as it will not occur unsigned num = (upper-lower+1); values.ensure(num); unsigned idx; for (idx = 0; idx < num; idx++) values.append(*LINK(dft)); ForEachItemIn(idx2, pairs) { IHqlExpression & cur = pairs.item(idx2); IValue * value = cur.queryChild(0)->queryValue(); unsigned replaceIndex; switch (compareTypeCode) { case type_int: replaceIndex = (int)value->getIntValue()-lower; break; case type_string: { StringBuffer temp; value->getStringValue(temp); replaceIndex = (int)(unsigned char)temp.charAt(0)-lower; break; } default: throwUnexpectedType(compareType); } IHqlExpression * mapTo = cur.queryChild(1); if (mapTo->getOperator() != no_constant) throwUnexpected(); if (replaceIndex >= num) translator.reportWarning(CategoryIgnored, HQLWRN_CaseCanNeverMatch, "CASE entry %d can never match the test condition", replaceIndex); else values.replace(*LINK(mapTo),replaceIndex); }
//Optimize IF(a,b,c) op x to IF(a,b op x, c OP x) //But be careful because it uncommons attributes increasing the size of the queries. static IHqlExpression * peepholeOptimizeCompare(BuildCtx & ctx, IHqlExpression * expr) { IHqlExpression * lhs = expr->queryChild(0); if (ctx.queryMatchExpr(lhs)) return LINK(expr); IHqlExpression * rhs = expr->queryChild(1); if (!rhs->isConstant() || (lhs->getOperator() != no_if)) return LINK(expr); IHqlExpression * ifCond = lhs->queryChild(0); IHqlExpression * ifTrue = lhs->queryChild(1); IHqlExpression * ifFalse = lhs->queryChild(2); assertex(ifFalse); node_operator op = expr->getOperator(); OwnedHqlExpr newTrue = createValue(op, makeBoolType(), LINK(ifTrue), LINK(rhs)); OwnedHqlExpr newFalse = createValue(op, makeBoolType(), LINK(ifFalse), LINK(rhs)); OwnedHqlExpr newIf = createValue(no_if, makeBoolType(), LINK(ifCond), peepholeOptimize(ctx, newTrue), peepholeOptimize(ctx, newFalse)); return expr->cloneAllAnnotations(newIf); }
IHqlExpression * PositionTransformer::createTransformed(IHqlExpression * _expr) { OwnedHqlExpr transformed = NewHqlTransformer::createTransformed(_expr); switch (transformed->getOperator()) { case no_table: { IHqlExpression * mode = transformed->queryChild(2); HqlExprArray fields; HqlExprArray args; if (mode->getOperator() == no_thor) { unwindChildren(fields, transformed->queryChild(1)); IHqlExpression * filePosAttr = createComma(createAttribute(virtualAtom, createAttribute(filepositionAtom)), insertedAttr.getLink()); IHqlExpression * sizeofAttr = createComma(createAttribute(virtualAtom, createAttribute(sizeofAtom)), insertedAttr.getLink()); fields.append(*createField(fileposName, makeIntType(8, false), NULL, filePosAttr)); fields.append(*createField(recordlenName, makeIntType(2, false), NULL, sizeofAttr)); unwindChildren(args, transformed); args.replace(*createRecord(fields), 1); return transformed->clone(args); } } break; case no_iterate: case no_hqlproject: { HqlExprArray args; HqlExprArray assigns; IHqlExpression * transform = transformed->queryChild(1); unwindChildren(args, transformed); unwindChildren(assigns, transform); IHqlExpression * inRecord = transformed->queryChild(0)->queryRecord(); IHqlExpression * outRecord = transform->queryRecord(); HqlExprArray fields; unwindChildren(fields, outRecord); ForEachChild(idx, inRecord) { IHqlExpression * child = inRecord->queryChild(idx); if (child->hasProperty(insertedAtom)) { IHqlExpression * newTarget = createField(child->queryName(), child->getType(), LINK(child), insertedAttr.getLink()); fields.append(*newTarget); assigns.append(*createValue(no_assign, makeVoidType(), newTarget, createSelectExpr(createValue(no_left), LINK(newTarget)))); } } IHqlExpression * newRecord = createRecord(fields); args.replace(*createValue(no_transform, newRecord->getType(), assigns), 1); return transformed->clone(args); } break; case no_join: //only ok if join first case no_rollup: case no_newaggregate: case no_aggregate: fail(); break; case no_usertable: case no_selectfields: { IHqlExpression * grouping = transformed->queryChild(2); if (grouping && (grouping->getOperator() != no_attr)) fail(); IHqlExpression * record = transformed->queryRecord(); HqlExprArray fields; unwindChildren(fields, transformed->queryChild(1)); ForEachChild(idx, record) { IHqlExpression * child = record->queryChild(idx); if (child->hasProperty(insertedAtom)) fields.append(*createField(child->queryName(), child->getType(), LINK(child), insertedAttr.getLink())); } HqlExprArray args; unwindChildren(args, transformed); args.replace(*createRecord(fields), 1); return transformed->clone(args); }
IHqlExpression * HqlCppCaseInfo::buildIndexedMap(BuildCtx & ctx, const CHqlBoundExpr & test) { ITypeInfo * compareType = test.queryType()->queryPromotedType(); type_t compareTypeCode = compareType->getTypeCode(); HqlExprArray values; IHqlExpression * dft = queryActiveTableSelector(); // value doesn't matter as long as it will not occur __int64 lower = getIntValue(lowerTableBound, 0); unsigned num = (getIntValue(upperTableBound, 0)-lower)+1; CHqlBoundExpr indexExpr; switch (compareTypeCode) { case type_int: indexExpr.set(test); break; case type_string: indexExpr.expr.setown(createValue(no_index, makeCharType(), LINK(test.expr), getZero())); indexExpr.expr.setown(createValue(no_cast, makeIntType(1, false), LINK(indexExpr.expr))); break; default: throwUnexpectedType(compareType); } if (useRangeIndex && (num != 1)) translator.ensureSimpleExpr(ctx, indexExpr); OwnedHqlExpr mapped; ITypeInfo * retType = resultType; //if num == pairs.ordinality() and all results are identical, avoid the table lookup. if (allResultsMatch && (num == pairs.ordinality())) { mapped.set(pairs.item(0).queryChild(1)); } else { values.ensure(num); unsigned idx; for (idx = 0; idx < num; idx++) values.append(*LINK(dft)); ForEachItemIn(idx2, pairs) { IHqlExpression & cur = pairs.item(idx2); IValue * value = cur.queryChild(0)->queryValue(); unsigned replaceIndex; switch (compareTypeCode) { case type_int: replaceIndex = (unsigned)(value->getIntValue()-lower); break; case type_string: { StringBuffer temp; value->getStringValue(temp); replaceIndex = (unsigned)((unsigned char)temp.charAt(0)-lower); break; } default: throwUnexpectedType(compareType); } IHqlExpression * mapTo = cur.queryChild(1); if (mapTo->getOperator() != no_constant) throwUnexpected(); if (replaceIndex >= num) translator.reportWarning(CategoryIgnored, HQLWRN_CaseCanNeverMatch, "CASE entry %d can never match the test condition", replaceIndex); else values.replace(*LINK(mapTo),replaceIndex); } //Now replace the placeholders with the default values. for (idx = 0; idx < num; idx++) { if (&values.item(idx) == dft) values.replace(*defaultValue.getLink(),idx); } // use a var string type to get better C++ generated... ITypeInfo * storeType = getArrayElementType(resultType); ITypeInfo * listType = makeArrayType(storeType, values.ordinality()); OwnedHqlExpr lvalues = createValue(no_list, listType, values); CHqlBoundExpr boundTable; translator.buildExpr(ctx, lvalues, boundTable); LinkedHqlExpr tableIndex = indexExpr.expr; if (getIntValue(lowerTableBound, 0)) tableIndex.setown(createValue(no_sub, tableIndex->getType(), LINK(tableIndex), LINK(lowerTableBound))); IHqlExpression * ret = createValue(no_index, LINK(retType), LINK(boundTable.expr), LINK(tableIndex)); mapped.setown(createTranslatedOwned(ret)); }