IHqlExpression * CMemberInfo::addDatasetLimits(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * _value) { LinkedHqlExpr value = _value; IHqlExpression * choosen = column->queryAttribute(choosenAtom); if (choosen) { LinkedHqlExpr choosenValue = choosen->queryChild(0); if (!choosenValue->queryValue()) { OwnedHqlExpr self = container->getRelativeSelf(); OwnedHqlExpr absoluteExpr = replaceSelector(choosenValue, querySelfReference(), self); choosenValue.setown(selector->queryRootRow()->bindToRow(absoluteExpr, querySelfReference())); } else { if (hasNoMoreRowsThan(value, getIntValue(choosenValue))) choosenValue.clear(); } if (choosenValue) value.setown(createDataset(no_choosen, LINK(value), LINK(choosenValue))); } IHqlExpression * maxCount = queryAttributeChild(column, maxCountAtom, 0); if (maxCount && !hasNoMoreRowsThan(value, getIntValue(maxCount))) { //Generate a limit test if there isn't a limit that ensures it is small enough StringBuffer failText, columnText; expandSelectPathText(columnText, true).toLowerCase(); failText.appendf("Too many rows assigned to field %s", columnText.str()); OwnedHqlExpr fail = translator.createFailAction(failText.str(), maxCount, NULL, translator.queryCurrentActivityId(ctx)); value.setown(createDataset(no_limit, LINK(value), createComma(LINK(maxCount), LINK(fail)))); } return value.getClear(); }
void CChildLinkedDatasetColumnInfo::setColumn(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * _value) { OwnedHqlExpr addressSize = getColumnAddress(translator, ctx, selector, sizetType, 0); OwnedHqlExpr addressData = getColumnAddress(translator, ctx, selector, queryType(), sizeof(size32_t)); ITypeInfo * resultType = queryType(); LinkedHqlExpr value = _value; ITypeInfo * valueType = value->queryType(); assertRecordTypesMatch(resultType, valueType); value.setown(addDatasetLimits(translator, ctx, selector, value)); CHqlBoundTarget boundTarget; boundTarget.count.setown(convertAddressToValue(addressSize, sizetType)); boundTarget.expr.setown(convertAddressToValue(addressData, queryType())); if (value->getOperator() == no_null) value.setown(createNullExpr(column)); translator.buildDatasetAssign(ctx, boundTarget, value); }
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, 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)); }