public void GetOutputStructure_Correct1Superset1SubsetExpr_SupersetModified(params TestExprType[] types) { foreach (string opSymbol in this._operators) { IExpression arithmeticExpr = TestExprFactory.GetExpression(types); arithmeticExpr.OperatorDefinition = ModelResolvers.OperatorResolver(opSymbol); arithmeticExpr.Operands["ds_1"].Structure.Identifiers.Add(new StructureComponent(BasicDataType.Integer, "Id2")); IDataStructure expectedStructure = arithmeticExpr.Operands[$"ds_1"].Structure.GetCopy(); for (int i = 0; i < expectedStructure.Measures.Count; i++) { BasicDataType dataType = arithmeticExpr.Operands[$"ds_2"].Structure.Measures[i].ValueDomain.DataType; if (dataType == BasicDataType.Number) { expectedStructure.Measures[i].ValueDomain = new ValueDomain(dataType); } if (expectedStructure.Measures[i].ValueDomain.DataType == BasicDataType.None) { expectedStructure.Measures[i].ValueDomain = new ValueDomain(BasicDataType.Integer); } } IDataStructure dataStructure = arithmeticExpr.OperatorDefinition.GetOutputStructure(arithmeticExpr); Assert.True(expectedStructure.EqualsObj(dataStructure)); } }
/// <summary> /// Initializes a new instance of the <see cref="DataStructure"/> class <b>for a single component structure.</b>. /// </summary> /// <param name="compName">The name of the component.</param> /// <param name="compType">The component type.</param> /// <param name="dataType">The data type of the component.</param> /// <param name="logger">The errors logger.</param> public DataStructure(string compName, ComponentType compType, BasicDataType dataType, ILogger <IDataStructure> logger = null) : this(logger) { switch (compType) { case ComponentType.Identifier: this.identifiers = new List <StructureComponent>() { new StructureComponent(dataType, compName) }; break; case ComponentType.Measure: this.measures = new List <StructureComponent>() { new StructureComponent(dataType, compName) }; break; case ComponentType.NonViralAttribute: this.nonViralAttributes = new List <StructureComponent>() { new StructureComponent(dataType, compName) }; break; case ComponentType.ViralAttribute: this.viralAttributes = new List <StructureComponent>() { new StructureComponent(dataType, compName) }; break; default: throw new ArgumentOutOfRangeException("compType", "Wrong component type."); } }
/// <summary> /// Gets the variable name of a basic data type. /// </summary> /// <param name="instance">The basic data type to get a variable name from.</param> /// <returns>The variable name of a basic data type.</returns> public static string GetVariableName(this BasicDataType instance) { switch (instance) { case BasicDataType.Integer: return("int_var"); case BasicDataType.Number: return("num_var"); case BasicDataType.String: return("string_var"); case BasicDataType.Boolean: return("bool_var"); case BasicDataType.Time: return("time_var"); case BasicDataType.Date: return("date_var"); case BasicDataType.TimePeriod: return("period_var"); case BasicDataType.Duration: return("duration_var"); case BasicDataType.None: return("NULL"); default: throw new ArgumentOutOfRangeException("instance", "Unknown data type."); } }
/// <summary> /// Maps a SDMX text data type to a VTL 2.0 data type. /// </summary> /// <param name="type">The type of the SDMX text data.</param> /// <returns>The basic VTL 2.0 data type.</returns> private BasicDataType mappingSDMX(TextEnumType type) { BasicDataType basicDataType = type switch { TextEnumType.Null => BasicDataType.None, TextEnumType.Alpha => BasicDataType.String, TextEnumType.Alphanumeric => BasicDataType.String, TextEnumType.AttachmentConstraintReference => BasicDataType.None, TextEnumType.BasicTimePeriod => BasicDataType.Date, TextEnumType.String => BasicDataType.String, TextEnumType.BigInteger => BasicDataType.Integer, TextEnumType.Integer => BasicDataType.Integer, TextEnumType.Long => BasicDataType.Integer, TextEnumType.Short => BasicDataType.Integer, TextEnumType.Decimal => BasicDataType.Number, TextEnumType.Float => BasicDataType.Number, TextEnumType.Double => BasicDataType.Number, TextEnumType.Boolean => BasicDataType.Boolean, TextEnumType.DateTime => BasicDataType.Date, TextEnumType.Date => BasicDataType.Date, TextEnumType.Time => BasicDataType.String, TextEnumType.Year => BasicDataType.String, TextEnumType.Month => BasicDataType.String, TextEnumType.Numeric => BasicDataType.String, TextEnumType.Day => BasicDataType.String, TextEnumType.MonthDay => BasicDataType.String, TextEnumType.YearMonth => BasicDataType.String, TextEnumType.Duration => BasicDataType.Duration, TextEnumType.Uri => BasicDataType.String, TextEnumType.Timespan => BasicDataType.String, TextEnumType.Count => BasicDataType.Integer, TextEnumType.DataSetReference => BasicDataType.None, TextEnumType.InclusiveValueRange => BasicDataType.Number, TextEnumType.ExclusiveValueRange => BasicDataType.Number, TextEnumType.Incremental => BasicDataType.Number, TextEnumType.ObservationalTimePeriod => BasicDataType.Time, TextEnumType.KeyValues => BasicDataType.None, TextEnumType.TimePeriod => BasicDataType.TimePeriod, TextEnumType.GregorianDay => BasicDataType.Date, TextEnumType.GregorianTimePeriod => BasicDataType.Date, TextEnumType.GregorianYear => BasicDataType.Date, TextEnumType.GregorianYearMonth => BasicDataType.Date, TextEnumType.ReportingDay => BasicDataType.TimePeriod, TextEnumType.ReportingMonth => BasicDataType.TimePeriod, TextEnumType.ReportingQuarter => BasicDataType.TimePeriod, TextEnumType.ReportingSemester => BasicDataType.TimePeriod, TextEnumType.ReportingTimePeriod => BasicDataType.TimePeriod, TextEnumType.ReportingTrimester => BasicDataType.TimePeriod, TextEnumType.ReportingWeek => BasicDataType.TimePeriod, TextEnumType.ReportingYear => BasicDataType.TimePeriod, TextEnumType.StandardTimePeriod => BasicDataType.Time, TextEnumType.TimesRange => BasicDataType.Time, TextEnumType.IdentifiableReference => BasicDataType.None, TextEnumType.Xhtml => BasicDataType.None, _ => throw new ArgumentOutOfRangeException("type") }; return(basicDataType); } }
/// <summary> /// Initializes a new instance of the <see cref="ValueDomain"/> class. /// </summary> /// <param name="dataType">The type of the data.</param> /// <param name="signature">The domain signature.</param> public ValueDomain(BasicDataType dataType, string signature = null) { this.DataType = dataType; this.Signature = signature ?? $"{dataType.GetName().ToLower()}_default"; if (this.Signature == "none") { this.Signature = "null_default"; } }
public string Render(IExpression expr, StructureComponent component = null) { BasicDataType type = expr.Structure.Components[0].ValueDomain.DataType; if (type == BasicDataType.None) { return("NULL"); } if (type == BasicDataType.String) { string str = expr.ExpressionText; if (str.First() == '"' && str.Last() == '"' && str.Length >= 2) { str = str.Remove(str.Length - 1).Remove(0, 1); str = str.Replace("'", "''"); //TODO: replacement of '"' return($"'{str}'"); } } if (type.In(BasicDataType.Time, BasicDataType.Date, BasicDataType.TimePeriod, BasicDataType.Duration)) { string str = expr.ExpressionText; if (str.Length >= 3 && str[0] == 't' && str[1] == '"' && str.Last() == '"') { str = str.Remove(str.Length - 1).Remove(0, 2); str = str.Replace("'", "''"); //TODO: replacement of '"' return($"'{str}'"); } } if (type == BasicDataType.Boolean) { if (expr.ExpressionText == "true") { return("1"); } return("0"); } return(expr.ExpressionText); }
/// <summary> /// Checks if the data type is equal to another. /// </summary> /// <param name="instance">The compared data type.</param> /// <param name="dataType">The data type to compare.</param> /// <param name="allNumsEqual">Specifies if an integer data type is equal to a number data type.</param> /// <param name="allEqualsToNull">Specifies if a none data type is equal to other.</param> /// <returns>Value specyfing equality.</returns> public static bool EqualsObj(this BasicDataType instance, BasicDataType dataType, bool allNumsEqual = true, bool allEqualsToNull = true) { if (instance != dataType && (!allNumsEqual || ( !(instance == BasicDataType.Integer && dataType == BasicDataType.Number) && !(instance == BasicDataType.Number && dataType == BasicDataType.Integer))) && (!allEqualsToNull || (instance != BasicDataType.None && dataType != BasicDataType.None)) ) { return(false); } return(true); }
public void InferStructure() { this.Structure = this._dsResolver(); if (this.Variables.Count > 0) { foreach (string variableName in this.Variables.Keys) { IEnumerable <StructureComponent> comps = this.RulesCollection.SelectMany(rule => this.GetComponentsFromDescendantExprs(rule, variableName)); BasicDataType dataType = comps.FirstOrDefault(comp => comp.ValueDomain.DataType != BasicDataType.None)?.ValueDomain.DataType ?? BasicDataType.None; foreach (StructureComponent comp in comps) { if (comp.ValueDomain.DataType != dataType) { if (dataType == BasicDataType.Integer && comp.ValueDomain.DataType == BasicDataType.Number) { comp.ValueDomain = new ValueDomain(dataType); } else if (comp.ValueDomain.DataType == BasicDataType.None) { comp.ValueDomain = new ValueDomain(dataType); } else if (dataType == BasicDataType.None) { dataType = comp.ValueDomain.DataType; } else { throw new InvalidOperationException($"Something went wrong during a types inference of ruleset {this.Name}."); } } } this.Structure.Measures.Add(comps.First()); } } else { foreach (string valueDomainName in this.ValueDomains.Keys) { IEnumerable <StructureComponent> comps = this.RulesCollection.SelectMany(rule => this.GetComponentsFromDescendantExprs(rule, valueDomainName)); this.Structure.Measures.Add(comps.First()); } } }
public override IDataStructure GetDatasetStructure(string datasetName) { string @namespace; this.SplitDatasetName(datasetName, out @namespace, out datasetName); if (@namespace != this.Namespace) { return(null); } ISet <IMaintainableObject> maintainable = this.GetMaintainableObjects(); DataStructureObjectCore datastructure = (DataStructureObjectCore)maintainable.SingleOrDefault(m => m.StructureType.StructureType == "Data Structure Definition" && m.Id == datasetName); if (datastructure == null) { return(null); } DataStructure dataStructure = new DataStructure(); foreach (IDimension dimension in datastructure.DimensionList.Dimensions) { BasicDataType type = dimension.Representation?.TextFormat != null?this.mappingSDMX(dimension.Representation.TextFormat.TextType.EnumType) : BasicDataType.String; dataStructure.Identifiers.Add(new StructureComponent(type, dimension.Id, ComponentType.Identifier)); } IPrimaryMeasure primaryMeasure = datastructure.PrimaryMeasure; BasicDataType measureType = primaryMeasure.Representation?.TextFormat != null?this.mappingSDMX(primaryMeasure.Representation.TextFormat.TextType.EnumType) : BasicDataType.Number; dataStructure.Measures.Add(new StructureComponent(measureType, primaryMeasure.Id, ComponentType.Measure)); foreach (IAttributeObject attribute in datastructure.AttributeList.Attributes) { BasicDataType type = attribute.Representation?.TextFormat != null?this.mappingSDMX(attribute.Representation.TextFormat.TextType.EnumType) : BasicDataType.String; dataStructure.ViralAttributes.Add(new StructureComponent(type, attribute.Id, ComponentType.ViralAttribute)); } return(dataStructure); }
public void GetOutputStructure_WrongNoParamDatasetClauseExpr_ThrowsException(BasicDataType type) { foreach (string name in DatasetClauseOperator.ClauseNames) { IExpression datasetClauseExpr = ModelResolvers.ExprResolver(); IExpression datasetExpr = ModelResolvers.ExprResolver(); IExpression clauseExpr = TestExprFactory.GetExpression(name, ExpressionFactoryNameTarget.ResultName); IExpression periodIndicatorExpr = TestExprFactory.GetExpression("period_indicator", ExpressionFactoryNameTarget.OperatorSymbol); datasetClauseExpr.AddOperand("ds_1", datasetExpr); datasetClauseExpr.AddOperand("ds_2", clauseExpr); clauseExpr.AddOperand("ds_1", periodIndicatorExpr); datasetExpr.Structure = ModelResolvers.DsResolver(); datasetExpr.Structure.Identifiers.Add(new StructureComponent(BasicDataType.Integer, "Id1")); datasetExpr.Structure.Identifiers.Add(new StructureComponent(type, "Id2")); datasetExpr.Structure.Measures.Add(new StructureComponent(BasicDataType.String, "Me1")); Assert.ThrowsAny <VtlOperatorError>(() => { periodIndicatorExpr.OperatorDefinition.GetOutputStructure(periodIndicatorExpr); }); } }
private void StartTest(bool arg2_isComp, string opSymbol, ComponentType compType, TestExprType[] dataTypes) { IExpression expr1 = TestExprFactory.GetExpression(dataTypes[0]); IExpression expr2 = TestExprFactory.GetExpression(dataTypes[1]); expr1.ExpressionText = expr1.Structure.Components[0].ComponentName = "Component"; expr1.OperatorDefinition = ModelResolvers.OperatorResolver("comp"); if (arg2_isComp) { expr2.ExpressionText = expr2.Structure.Components[0].ComponentName = "Component"; expr2.OperatorDefinition = ModelResolvers.OperatorResolver("comp"); } IExpression compCreateExpr = TestExprFactory.FoldExpression(expr1, expr2); compCreateExpr.OperatorDefinition = ModelResolvers.OperatorResolver(opSymbol); compCreateExpr.OperatorDefinition.Keyword = this.GetKeywordByCompType(compType); compCreateExpr.Structure = compCreateExpr.OperatorDefinition.GetOutputStructure(compCreateExpr); StructureComponent[] components = this.GetComponentsByCompType(compCreateExpr.Structure, compType); for (int i = 0; i < compCreateExpr.Structure.Components.Count; i++) { Assert.True(compCreateExpr.Structure.Components[i].ComponentName == expr1.Structure.Components[i].ComponentName); } BasicDataType type = expr2.Structure.Components[0].ValueDomain.DataType; if (type == BasicDataType.None || (type == BasicDataType.Integer && expr1.Structure.Components[0].ValueDomain.DataType == BasicDataType.Number)) { type = expr1.Structure.Components[0].ValueDomain.DataType; } Assert.Equal(components.Length, expr2.Structure.Components.Count); Assert.Equal(components[0].ValueDomain.DataType, type); }
public void GetOutputStructure_1TimeIdentifierExpr_DataStructure(string symbol, BasicDataType timeType) { IExpression timeExpr = ModelResolvers.ExprResolver(); timeExpr.OperatorDefinition = ModelResolvers.OperatorResolver(symbol); IExpression timeDsExpr = ModelResolvers.ExprResolver(); timeDsExpr.Structure = ModelResolvers.DsResolver("Id1", ComponentType.Identifier, timeType); timeDsExpr.Structure.Identifiers.Add(new StructureComponent(BasicDataType.Integer, "Id2")); timeExpr.AddOperand("ds_1", timeDsExpr); IDataStructure dataStructure = timeExpr.OperatorDefinition.GetOutputStructure(timeExpr); Assert.True(timeDsExpr.Structure.EqualsObj(dataStructure)); }
public IDataStructure GetOutputStructure(IExpression expression) { if (expression.IsApplyComponent) { return(this._joinApplyMeasuresOp.GetMeasuresStructure(expression)); } IExpression expr1 = expression.OperandsCollection.ToArray()[0]; IExpression expr2 = expression.OperandsCollection.ToArray()[1]; IExpression expr3 = expression.OperandsCollection.ToArray()[2]; IDataStructure structure; if (!expr2.IsScalar) { throw new VtlOperatorError(expression, this.Name, "Second parameter must be scalar expression."); } if (!expr3.IsScalar) { throw new VtlOperatorError(expression, this.Name, "Third parameter must be scalar expression."); } BasicDataType type = expr2.Structure.Components[0].ValueDomain.DataType; if (type == BasicDataType.None) { type = expr3.Structure.Components[0].ValueDomain.DataType; } if (!expr3.Structure.Components[0].ValueDomain.DataType.EqualsObj(type) && !BasicDataType.None.In(expr3.Structure.Components[0].ValueDomain.DataType, type)) { throw new VtlOperatorError(expression, this.Name, "Second and third parameter must have the same data types."); } if (expr1.IsScalar) { if (!expr1.Structure.Components[0].ValueDomain.DataType.EqualsObj(type) && !BasicDataType.None.In(expr1.Structure.Components[0].ValueDomain.DataType, type)) { throw new VtlOperatorError(expression, this.Name, "First parameter must have the same data type as second and third parameter."); } return(this._dsResolver("bool_var", ComponentType.Measure, BasicDataType.Boolean)); } else { if (expr1.Structure.Measures.Count > 1) { throw new VtlOperatorError(expression, this.Name, "Expected structure with only one measure."); } if (!expr1.Structure.Measures[0].ValueDomain.DataType.EqualsObj(type) && !BasicDataType.None.In(expr1.Structure.Measures[0].ValueDomain.DataType, type)) { throw new VtlOperatorError(expression, this.Name, "First parameter must have the same data type as second and third parameter."); } } structure = expr1.Structure.GetCopy(); structure.Measures[0].ComponentName = "bool_var"; structure.Measures[0].ValueDomain = new ValueDomain(BasicDataType.Boolean); return(structure); }
/// <summary> /// Initialises a new instance of the <see cref="StructureComponent"/> class. /// </summary> /// <param name="dataType">The data type.</param> /// <param name="name">The component name.</param> /// <param name="compType">The component type.</param> public StructureComponent(BasicDataType dataType, string name = "VALUE", ComponentType compType = ComponentType.Measure) : this(new ValueDomain(dataType), name, compType) { }
/// <summary> /// Gets the structure of the resulting operator parameter for specified operands. /// </summary> /// <param name="expression">The expression.</param> /// <returns>A dynamically defined structure of the output parameter for the given input parameters.</returns> public IDataStructure GetOutputStructure(IExpression expression) { IExpression expr1 = expression.Operands["ds_1"]; IExpression expr2 = expression.Operands["ds_2"]; BasicDataType type1 = expr1.Structure.Components[0].ValueDomain.DataType; BasicDataType type2 = expr2.Structure.Components[0].ValueDomain.DataType; if (!expr1.IsScalar || expr1.OperatorSymbol != "comp") { throw new VtlOperatorError(expression, this._name, "Expected component operator expression as the first parameter."); } if (!expr2.IsScalar) { throw new VtlOperatorError(expression, this._name, "Expected scalar expression as the second parameter."); } if (expr1.Structure.Identifiers.Count != 0 && expr1.Structure.Identifiers[0].ValueDomain.DataType != BasicDataType.None) { throw new VtlOperatorError(expression, this._name, "Identifier of any dataset can not be modify."); } if (!type1.EqualsObj(type2)) { throw new VtlOperatorError(expression, this._name, "Types of parameters don't match."); } BasicDataType type = type2; if (type == BasicDataType.None || (type2 == BasicDataType.Integer && type1 == BasicDataType.Number)) { type = type1; } IDataStructure dataStructure = this._dsResolver(); switch (this.Keyword) { case "identifier": if (this.AreNullValues(expr2)) { throw new VtlOperatorError(expression, this._name, "Possible putting null values into an identifier component."); } dataStructure.Identifiers.Add( new StructureComponent(type, expr1.ExpressionText)); break; case "measure": dataStructure.Measures.Add( new StructureComponent(type, expr1.ExpressionText)); break; case "viral attribute": dataStructure.ViralAttributes.Add( new StructureComponent(type, expr1.ExpressionText)); break; case "attribute": dataStructure.NonViralAttributes.Add( new StructureComponent(type, expr1.ExpressionText)); break; default: throw new VtlOperatorError(expression, this._name, $"Unknown keyword of an operator: {this.Keyword}"); } return(dataStructure); }
public void GetOutputStructure_NoTimeIdentifiersExpr_ThrowsException(string symbol, BasicDataType type) { IExpression timeExpr = ModelResolvers.ExprResolver(); timeExpr.OperatorDefinition = ModelResolvers.OperatorResolver(symbol); IExpression timeDsExpr = ModelResolvers.ExprResolver(); timeDsExpr.Structure = ModelResolvers.DsResolver("Id1", ComponentType.Identifier, type); timeDsExpr.Structure.Identifiers.Add(new StructureComponent(BasicDataType.Integer, "Id2")); timeExpr.AddOperand("ds_1", timeDsExpr); Assert.ThrowsAny <VtlOperatorError>(() => { timeExpr.OperatorDefinition.GetOutputStructure(timeExpr); }); }
public IDataStructure GetOutputStructure(IExpression expression) { IDataStructure structure = this._dsResolver(); IExpression parentExpr = expression.ParentExpression; if (parentExpr.OperatorSymbol == "#") { StructureComponent component = parentExpr.Operands["ds_1"].Structure.Components.FirstOrDefault(comp => comp.ComponentName.GetNameWithoutAlias() == expression.ExpressionText); if (component == null) { throw new VtlOperatorError(expression, this.Name, $"Component {expression.ExpressionText} has been not found in dataset {parentExpr.Operands["ds_1"].ExpressionText}."); } structure = this._dsResolver(component.ComponentName.GetNameWithoutAlias(), component.ComponentType, component.ValueDomain.DataType); } else if (parentExpr.OperatorSymbol == "unpivot") { if (expression.ParamSignature == "ds_1") { structure = this._dsResolver(expression.ExpressionText, ComponentType.Identifier, BasicDataType.String); //string as nominal data } else { // unpivot > datasetClause > dataset if (parentExpr.ParentExpression?.Operands["ds_1"]?.Structure?.Measures.First() != null) { BasicDataType type = parentExpr.ParentExpression.Operands["ds_1"].Structure.Measures.First().ValueDomain.DataType; structure = this._dsResolver(expression.ExpressionText, ComponentType.Measure, type); } else { structure = this._dsResolver(expression.ExpressionText, ComponentType.Measure, BasicDataType.None); } } } else if ((parentExpr.OperatorSymbol != "calcExpr" || parentExpr.Operands["ds_1"] != expression) && (parentExpr.OperatorSymbol != "renameExpr" || parentExpr.Operands["ds_2"] != expression)) { this._compTypeInference.InferTypeOfComponent(expression); structure = expression.Structure.GetCopy(); } else { BasicDataType dataType; ComponentType compType; if (parentExpr.OperatorSymbol == "calcExpr") { dataType = BasicDataType.None; switch (parentExpr.OperatorDefinition.Keyword) { case "identifier": compType = ComponentType.Identifier; break; case "measure": compType = ComponentType.Measure; break; case "attribute": compType = ComponentType.NonViralAttribute; break; case "viral attribute": compType = ComponentType.ViralAttribute; break; default: throw new VtlOperatorError(expression, this.Name, $"Unknown operator keyword: {parentExpr.OperatorDefinition.Keyword}"); } structure = this._dsResolver(expression.ExpressionText, compType, dataType); } else if (parentExpr.OperatorSymbol == "renameExpr") { StructureComponent baseComp = parentExpr.Operands["ds_1"].Structure.Components[0]; dataType = baseComp.ValueDomain.DataType; compType = baseComp.ComponentType; structure = this._dsResolver(expression.ExpressionText, compType, dataType); } else { throw new VtlOperatorError(expression, this.Symbol, "Unknown component type."); } } IRuleset ruleset = expression.ContainingSchema?.Rulesets.FirstOrDefault(ruleset => ruleset.RulesCollection.Contains(expression.GetFirstAncestorExpr() ?? expression)); if (ruleset != null) { if (ruleset.Variables.Count > 0) { structure.Components[0].BaseComponentName = ruleset.Variables[structure.Components[0].ComponentName]; } else { structure.Components[0].BaseComponentName = ruleset.ValueDomains[structure.Components[0].ComponentName].Signature; } } return(structure); }
public IDataStructure GetOutputStructure(IExpression expression) { if (expression.IsApplyComponent) { expression.Operands["if"].Structure = expression.Operands["if"].Operands["ds_1"].Structure.GetCopy(); expression.Operands["then"].Structure = expression.Operands["then"].Operands["ds_1"].Structure.GetCopy(); expression.Operands["else"].Structure = expression.Operands["else"].Operands["ds_1"].Structure.GetCopy(); return(this._joinApplyMeasuresOp.GetMeasuresStructure(expression)); } IDataStructure dataStructure = null; IExpression ifExpr = expression.Operands["if"]; IExpression thenExpr = expression.Operands["then"]; IExpression elseExpr = expression.Operands["else"]; ifExpr.Structure = ifExpr.OperandsCollection.First().Structure.GetCopy(); thenExpr.Structure = thenExpr.OperandsCollection.First().Structure.GetCopy(); elseExpr.Structure = elseExpr.OperandsCollection.First().Structure.GetCopy(); if (ifExpr.IsScalar && ifExpr.Structure.Components[0].ValueDomain.DataType != BasicDataType.Boolean) { throw new VtlOperatorError(expression, this.Name, "Expected boolean value in condition expression."); } else if (!ifExpr.IsScalar) { if (ifExpr.Structure.Measures.Count != 1) { throw new VtlOperatorError(expression, this.Name, "Expected single measure expression as condition."); } if (ifExpr.Structure.Measures[0].ValueDomain.DataType != BasicDataType.Boolean) { throw new VtlOperatorError(expression, this.Name, "Expected boolean measure in condition expression."); } } if (!thenExpr.IsScalar) { if (elseExpr.IsScalar) { dataStructure = thenExpr.Structure.GetCopy().WithAttributesOf(ifExpr.Structure); if (thenExpr.Structure.Measures.FirstOrDefault(me => !me.ValueDomain.DataType.EqualsObj(elseExpr.Structure.Components[0].ValueDomain.DataType)) != null) { throw new VtlOperatorError(expression, this.Name, "All measures of thenClause data structure must have elseClause's scalar data type."); } // Remove none and replace ints to numbers data types when possible: foreach (StructureComponent measure in dataStructure.Measures) { if (measure.ValueDomain.DataType.In(BasicDataType.None, BasicDataType.Integer) && elseExpr.Structure.Components[0].ValueDomain.DataType != BasicDataType.None) { measure.ValueDomain = new ValueDomain(elseExpr.Structure.Components[0].ValueDomain.DataType); } } } if (!ifExpr.IsScalar && !ifExpr.Structure.IsSupersetOf(thenExpr.Structure)) { throw new VtlOperatorError(expression, this.Name, "Datasets don't fit"); } } if (!elseExpr.IsScalar) { if (thenExpr.IsScalar) { dataStructure = elseExpr.Structure.GetCopy().WithAttributesOf(ifExpr.Structure); if (elseExpr.Structure.Measures.FirstOrDefault(me => !me.ValueDomain.DataType.EqualsObj(thenExpr.Structure.Components[0].ValueDomain.DataType)) != null) { throw new VtlOperatorError(expression, this.Name, "All measures of elseClause data structure must have thenClause's scalar data type."); } // Remove none and replace ints to numbers data types when possible: foreach (StructureComponent measure in dataStructure.Measures) { if (measure.ValueDomain.DataType.In(BasicDataType.None, BasicDataType.Integer) && thenExpr.Structure.Components[0].ValueDomain.DataType != BasicDataType.None) { measure.ValueDomain = new ValueDomain(thenExpr.Structure.Components[0].ValueDomain.DataType); } } } if (!ifExpr.IsScalar && !ifExpr.Structure.IsSupersetOf(elseExpr.Structure)) { throw new VtlOperatorError(expression, this.Name, "Datasets don't fit"); } } if (!thenExpr.IsScalar && !elseExpr.IsScalar) { bool thenStructure = thenExpr.Structure.IsSupersetOf(elseExpr.Structure, true, false, true); if (thenStructure) { dataStructure = thenExpr.Structure.GetCopy().WithAttributesOf(ifExpr.Structure).WithAttributesOf(elseExpr.Structure); } else if (elseExpr.Structure.IsSupersetOf(thenExpr.Structure, true, false, true)) { dataStructure = elseExpr.Structure.GetCopy().WithAttributesOf(ifExpr.Structure).WithAttributesOf(thenExpr.Structure); } else { throw new VtlOperatorError(expression, this.Name, "Datasets don't fit"); } // Remove none and replace ints to numbers data types when possible: for (int i = 0; i < dataStructure.Measures.Count; i++) { StructureComponent measure = dataStructure.Measures[i]; if (measure.ValueDomain.DataType.In(BasicDataType.None, BasicDataType.Integer)) { if (thenStructure && elseExpr.Structure.Measures[i].ValueDomain.DataType != BasicDataType.None) { measure.ValueDomain = new ValueDomain(elseExpr.Structure.Measures[i].ValueDomain.DataType); } else if (thenExpr.Structure.Measures[i].ValueDomain.DataType != BasicDataType.None) { measure.ValueDomain = new ValueDomain(thenExpr.Structure.Measures[i].ValueDomain.DataType); } } } } else if (thenExpr.IsScalar && elseExpr.IsScalar && !thenExpr.Structure.Components[0].ValueDomain.DataType.EqualsObj(elseExpr.Structure.Components[0].ValueDomain.DataType)) { throw new VtlOperatorError(expression, this.Name, "ThenClause and ElseClause scalar data types are not the same."); } if (dataStructure != null) { return(dataStructure); } else if (!ifExpr.IsScalar) { if (thenExpr.Structure.Components[0].ValueDomain.DataType != BasicDataType.Boolean || elseExpr.Structure.Components[0].ValueDomain.DataType != BasicDataType.Boolean) { throw new VtlOperatorError(expression, this.Name, "Expected boolean values in thenClause and elseClause."); } return(ifExpr.Structure.GetCopy()); } BasicDataType type = thenExpr.Structure.Components[0].ValueDomain.DataType; if (type.In(BasicDataType.Integer, BasicDataType.None) && elseExpr.Structure.Components[0].ValueDomain.DataType != BasicDataType.None) { type = elseExpr.Structure.Components[0].ValueDomain.DataType; } return(this._dsResolver(type.GetVariableName(), ComponentType.Measure, type)); }
public IDataStructure GetOutputStructure(IExpression expression) { if (expression.IsApplyComponent) { return(this._joinApplyMeasuresOp.GetMeasuresStructure(expression)); } IDataStructure structure; IDataStructure ds1 = expression.OperandsCollection.ToArray()[0].Structure.GetCopy(); IDataStructure ds2 = expression.OperandsCollection.ToArray()[1].Structure.GetCopy(); if (!ds1.IsSingleComponent && ds1.Measures.Count > 1) { throw new VtlOperatorError(expression, this.Name, "Expected single measure structure."); } if (!ds2.IsSingleComponent && ds2.Measures.Count > 1) { throw new VtlOperatorError(expression, this.Name, "Expected single measure structure."); } if (!ds1.IsSingleComponent && !ds2.IsSingleComponent) { if (!ds1.IsSupersetOf(ds2, true, false, true) && !ds2.IsSupersetOf(ds1, true, false, true)) { throw new VtlOperatorError(expression, this.Name, "Datasets doesn't fit."); } if (!ds1.Measures[0].ValueDomain.DataType.In(BasicDataType.None, BasicDataType.Integer) || ds2.Measures[0].ValueDomain.DataType == BasicDataType.None) { structure = ds1.WithAttributesOf(ds2); } else { structure = ds2.WithAttributesOf(ds1); } return(structure); } if (!ds1.IsSingleComponent || !ds2.IsSingleComponent) { structure = ds1.GetCopy().WithAttributesOf(ds2); BasicDataType scalarType = ds2.Components[0].ValueDomain.DataType; if (!ds2.IsSingleComponent) { structure = ds2.GetCopy().WithAttributesOf(ds1); scalarType = ds1.Components[0].ValueDomain.DataType; } if (!structure.Measures[0].ValueDomain.DataType.EqualsObj(scalarType)) { throw new VtlOperatorError(expression, this.Name, "Data types of parameters are not equal."); } if (structure.Measures[0].ValueDomain.DataType.In(BasicDataType.None, BasicDataType.Integer) && scalarType != BasicDataType.None) { structure.Measures[0].ValueDomain = new ValueDomain(scalarType); } return(structure); } if (!ds1.Components[0].ValueDomain.DataType.EqualsObj(ds2.Components[0].ValueDomain.DataType)) { throw new VtlOperatorError(expression, this.Name, "Data types of parameters are not equal."); } if (!ds1.Components[0].ValueDomain.DataType.In(BasicDataType.None, BasicDataType.Integer) || ds2.Components[0].ValueDomain.DataType == BasicDataType.None) { structure = ds1.WithAttributesOf(ds2); } else { structure = ds2.WithAttributesOf(ds1); } return(structure); }