void CChildLinkedDatasetColumnInfo::buildDeserialize(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper, IAtom * serializeFormat) { if (isConditional()) checkAssignOk(translator, ctx, selector, queryZero(), sizeof(size32_t) + sizeof(byte * *)); OwnedHqlExpr addressSize = getColumnAddress(translator, ctx, selector, sizetType, 0); OwnedHqlExpr addressData = getColumnAddress(translator, ctx, selector, queryType(), sizeof(size32_t)); IHqlExpression * record = column->queryRecord(); CHqlBoundTarget boundTarget; boundTarget.count.setown(convertAddressToValue(addressSize, sizetType)); boundTarget.expr.setown(convertAddressToValue(addressData, queryType())); IIdAtom * func = NULL; HqlExprArray args; args.append(*translator.createSerializer(ctx, record, serializeFormat, deserializerAtom)); if (column->isDictionary()) { if (serializeFormat == diskAtom) { func = deserializeChildDictionaryFromDatasetFromStreamId; StringBuffer lookupHelperName; translator.buildDictionaryHashClass(record, lookupHelperName); args.append(*createQuoted(lookupHelperName.str(), makeBoolType())); } else func = deserializeChildDictionaryFromStreamId; } else func = deserializeChildRowsetFromStreamId; args.append(*LINK(helper)); OwnedHqlExpr call = translator.bindFunctionCall(func, args, queryType()); translator.buildExprAssign(ctx, boundTarget, call); }
//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); }
DataSourceMetaData::DataSourceMetaData(IHqlExpression * _record, byte _numFieldsToIgnore, bool _randomIsOk, bool _isGrouped, unsigned _keyedSize) { init(); numFieldsToIgnore = _numFieldsToIgnore; randomIsOk = _randomIsOk; isStoredFixedWidth = true; //MORE: Blobs aren't handled correctly in indexes.... maxRecordSize = ::getMaxRecordSize(_record, MAX_RECORD_SIZE); keyedSize = _keyedSize; gatherFields(_record, false); if (_isGrouped) { Owned<ITypeInfo> type = makeBoolType(); addSimpleField("__groupfollows__", NULL, type); maxRecordSize++; } if (isStoredFixedWidth) assertex(storedFixedSize == maxRecordSize); }
//MORE: Really this should create no_selects for the sub records, but pass on that for the moment. void DataSourceMetaData::gatherFields(IHqlExpression * expr, bool isConditional) { switch (expr->getOperator()) { case no_record: gatherChildFields(expr, isConditional); break; case no_ifblock: { OwnedITypeInfo boolType = makeBoolType(); OwnedITypeInfo voidType = makeVoidType(); isStoredFixedWidth = false; fields.append(*new DataSourceMetaItem(FVFFbeginif, NULL, NULL, boolType)); gatherChildFields(expr->queryChild(1), true); fields.append(*new DataSourceMetaItem(FVFFendif, NULL, NULL, voidType)); break; } case no_field: { if (expr->hasProperty(__ifblockAtom)) break; Linked<ITypeInfo> type = expr->queryType(); IAtom * name = expr->queryName(); IHqlExpression * nameAttr = expr->queryProperty(namedAtom); StringBuffer outname; if (nameAttr && nameAttr->queryChild(0)->queryValue()) nameAttr->queryChild(0)->queryValue()->getStringValue(outname); else outname.append(name).toLowerCase(); StringBuffer xpathtext; const char * xpath = NULL; IHqlExpression * xpathAttr = expr->queryProperty(xpathAtom); if (xpathAttr && xpathAttr->queryChild(0)->queryValue()) xpath = xpathAttr->queryChild(0)->queryValue()->getStringValue(xpathtext); if (isKey() && expr->hasProperty(blobAtom)) type.setown(makeIntType(8, false)); type_t tc = type->getTypeCode(); if (tc == type_row) { OwnedITypeInfo voidType = makeVoidType(); fields.append(*new DataSourceMetaItem(FVFFbeginrecord, outname, xpath, voidType)); gatherChildFields(expr->queryRecord(), isConditional); fields.append(*new DataSourceMetaItem(FVFFendrecord, outname, xpath, voidType)); } else if ((tc == type_table) || (tc == type_groupedtable)) { isStoredFixedWidth = false; fields.append(*new DataSourceDatasetItem(outname, xpath, expr)); } else if (tc == type_set) { isStoredFixedWidth = false; fields.append(*new DataSourceSetItem(outname, xpath, type)); } else { if (type->getTypeCode() == type_alien) { IHqlAlienTypeInfo * alien = queryAlienType(type); type.set(alien->queryPhysicalType()); } addSimpleField(outname, xpath, type); } break; } } }
//MORE: Really this should create no_selects for the sub records, but pass on that for the moment. void DataSourceMetaData::gatherFields(IHqlExpression * expr, bool isConditional, bool *pMixedContent) { switch (expr->getOperator()) { case no_record: gatherChildFields(expr, isConditional, pMixedContent); break; case no_ifblock: { OwnedITypeInfo boolType = makeBoolType(); OwnedITypeInfo voidType = makeVoidType(); isStoredFixedWidth = false; fields.append(*new DataSourceMetaItem(FVFFbeginif, NULL, NULL, boolType)); gatherChildFields(expr->queryChild(1), true, pMixedContent); fields.append(*new DataSourceMetaItem(FVFFendif, NULL, NULL, voidType)); break; } case no_field: { if (expr->hasAttribute(__ifblockAtom)) break; Linked<ITypeInfo> type = expr->queryType(); IAtom * name = expr->queryName(); IHqlExpression * nameAttr = expr->queryAttribute(namedAtom); StringBuffer outname; if (nameAttr && nameAttr->queryChild(0)->queryValue()) nameAttr->queryChild(0)->queryValue()->getStringValue(outname); else outname.append(name).toLowerCase(); StringBuffer xpathtext; const char * xpath = NULL; IHqlExpression * xpathAttr = expr->queryAttribute(xpathAtom); if (xpathAttr && xpathAttr->queryChild(0)->queryValue()) xpath = xpathAttr->queryChild(0)->queryValue()->getStringValue(xpathtext); unsigned flag = FVFFnone; if (isKey() && expr->hasAttribute(blobAtom)) { type.setown(makeIntType(8, false)); flag = FVFFblob; } type_t tc = type->getTypeCode(); if (tc == type_row) { OwnedITypeInfo voidType = makeVoidType(); Owned<DataSourceMetaItem> begin = new DataSourceMetaItem(FVFFbeginrecord, outname, xpath, voidType); //inherit mixed content from child row with xpath('') bool *pItemMixedContent = (pMixedContent && xpath && !*xpath) ? pMixedContent : &(begin->hasMixedContent); fields.append(*begin.getClear()); gatherChildFields(expr->queryRecord(), isConditional, pItemMixedContent); fields.append(*new DataSourceMetaItem(FVFFendrecord, outname, xpath, voidType)); } else if ((tc == type_dictionary) || (tc == type_table) || (tc == type_groupedtable)) { isStoredFixedWidth = false; Owned<DataSourceDatasetItem> ds = new DataSourceDatasetItem(outname, xpath, expr); if (pMixedContent && xpath && !*xpath) *pMixedContent = ds->queryChildMeta()->hasMixedContent; fields.append(*ds.getClear()); } else if (tc == type_set) { isStoredFixedWidth = false; if (pMixedContent && xpath && !*xpath) *pMixedContent = true; fields.append(*new DataSourceSetItem(outname, xpath, type)); } else { if (type->getTypeCode() == type_alien) { IHqlAlienTypeInfo * alien = queryAlienType(type); type.set(alien->queryPhysicalType()); } if (pMixedContent && xpath && !*xpath) *pMixedContent = true; addSimpleField(outname, xpath, type, flag); } break; } } }