public virtual bool TryGetColumnCapabilities(DPath columnPath, out DelegationCapability capabilities) { Contracts.AssertValid(columnPath); // Check if it's a valid column name. As capabilities are not defined for all columns, we need to do this check. DType _; if (!_tableSchema.TryGetType(columnPath, out _)) { capabilities = DelegationCapability.None; return(false); } capabilities = DefaultColumnCapabilities; DelegationCapability restrictions; if (TryGetColumnRestrictions(columnPath, out restrictions)) { capabilities &= ~restrictions; } return(true); }
public override bool CheckInvocation(TexlBinding binding, TexlNode[] args, DType[] argTypes, IErrorContainer errors, out DType returnType, out Dictionary <TexlNode, DType> nodeToCoercedTypeMap) { Contracts.AssertValue(args); Contracts.AssertValue(argTypes); Contracts.Assert(args.Length == argTypes.Length); Contracts.AssertValue(errors); Contracts.Assert(MinArity <= args.Length && args.Length <= MaxArity); bool fArgsValid = base.CheckInvocation(args, argTypes, errors, out returnType, out nodeToCoercedTypeMap); Contracts.Assert(returnType.IsTable); if (!argTypes[0].IsTable) { fArgsValid = false; errors.EnsureError(DocumentErrorSeverity.Severe, args[0], TexlStrings.ErrNeedTable_Func, Name); } else { returnType = argTypes[0]; } // The result type has N fewer columns, as specified by (args[1],args[2],args[3],...) int count = args.Length; for (var i = 1; i < count; i++) { TexlNode nameArg = args[i]; DType nameArgType = argTypes[i]; // Verify we have a string literal for the column name. Accd to spec, we don't support // arbitrary expressions that evaluate to string values, because these values contribute to // type analysis, so they need to be known upfront (before DropColumns executes). StrLitNode nameNode; if (nameArgType.Kind != DKind.String || (nameNode = nameArg.AsStrLit()) == null) { fArgsValid = false; errors.EnsureError(DocumentErrorSeverity.Severe, nameArg, TexlStrings.ErrExpectedStringLiteralArg_Name, nameArg.ToString()); continue; } // Verify that the name is valid. if (!DName.IsValidDName(nameNode.Value)) { fArgsValid = false; errors.EnsureError(DocumentErrorSeverity.Severe, nameArg, TexlStrings.ErrArgNotAValidIdentifier_Name, nameNode.Value); continue; } DName columnName = new DName(nameNode.Value); // Verify that the name exists. DType columnType; if (!returnType.TryGetType(columnName, out columnType)) { fArgsValid = false; returnType.ReportNonExistingName(FieldNameKind.Logical, errors, columnName, nameArg); continue; } // Drop the specified column from the result type. bool fError = false; returnType = returnType.Drop(ref fError, DPath.Root, columnName); Contracts.Assert(!fError); } return(fArgsValid); }
public override bool CheckInvocation(TexlBinding binding, TexlNode[] args, DType[] argTypes, IErrorContainer errors, out DType returnType, out Dictionary <TexlNode, DType> nodeToCoercedTypeMap) { Contracts.AssertValue(args); Contracts.AssertAllValues(args); Contracts.AssertValue(argTypes); Contracts.Assert(args.Length == argTypes.Length); Contracts.AssertValue(errors); Contracts.Assert(MinArity <= args.Length && args.Length <= MaxArity); bool fValid = base.CheckInvocation(args, argTypes, errors, out returnType, out nodeToCoercedTypeMap); Contracts.Assert(returnType.IsTable); returnType = argTypes[0]; DType sourceType = argTypes[0]; for (int i = 1; i < args.Length; i += 2) { TexlNode colNameArg = args[i]; DType colNameArgType = argTypes[i]; StrLitNode nameNode; if (colNameArgType.Kind != DKind.String) { errors.EnsureError(DocumentErrorSeverity.Severe, colNameArg, TexlStrings.ErrStringExpected); fValid = false; } else if ((nameNode = colNameArg.AsStrLit()) != null) { // Verify that the name is valid. if (DName.IsValidDName(nameNode.Value)) { DName columnName = new DName(nameNode.Value); // Verify that the name exists. DType columnType; if (!sourceType.TryGetType(columnName, out columnType)) { sourceType.ReportNonExistingName(FieldNameKind.Logical, errors, columnName, args[i]); fValid = false; } else if (!columnType.IsPrimitive || columnType.IsOptionSet) { fValid = false; errors.EnsureError(colNameArg, TexlStrings.ErrSortWrongType); } } else { errors.EnsureError(DocumentErrorSeverity.Severe, nameNode, TexlStrings.ErrArgNotAValidIdentifier_Name, nameNode.Value); fValid = false; } } int nextArgIdx = i + 1; if (nextArgIdx < args.Length && argTypes[nextArgIdx] != DType.String) { fValid = false; errors.EnsureError(args[i + 1], TexlStrings.ErrSortIncorrectOrder); } } return(fValid); }
public override bool CheckInvocation(TexlBinding binding, TexlNode[] args, DType[] argTypes, IErrorContainer errors, out DType returnType, out Dictionary <TexlNode, DType> nodeToCoercedTypeMap) { Contracts.AssertValue(args); Contracts.AssertAllValues(args); Contracts.AssertValue(argTypes); Contracts.Assert(args.Length == argTypes.Length); Contracts.AssertValue(errors); Contracts.Assert(MinArity <= args.Length && args.Length <= MaxArity); bool fValid = base.CheckInvocation(args, argTypes, errors, out returnType, out nodeToCoercedTypeMap); Contracts.Assert(returnType.IsTable); returnType = argTypes[0]; DType sourceType = argTypes[0]; TexlNode nameArg = args[1]; DType nameArgType = argTypes[1]; StrLitNode nameNode = null; DType columnType = DType.Invalid; if (nameArgType.Kind != DKind.String) { errors.EnsureError(DocumentErrorSeverity.Severe, nameArg, TexlStrings.ErrStringExpected); fValid = false; } else if ((nameNode = nameArg.AsStrLit()) != null) { // Verify that the name is valid. if (DName.IsValidDName(nameNode.Value)) { DName columnName = new DName(nameNode.Value); // Verify that the name exists. if (!sourceType.TryGetType(columnName, out columnType)) { sourceType.ReportNonExistingName(FieldNameKind.Logical, errors, columnName, nameNode); fValid = false; } else if (!columnType.IsPrimitive) { fValid = false; errors.EnsureError(nameArg, TexlStrings.ErrSortWrongType); } } else { errors.EnsureError(DocumentErrorSeverity.Severe, nameNode, TexlStrings.ErrArgNotAValidIdentifier_Name, nameNode.Value); fValid = false; } } TexlNode valuesArg = args[2]; IEnumerable <TypedName> columns; if ((columns = argTypes[2].GetNames(DPath.Root)).Count() != 1) { errors.EnsureError(DocumentErrorSeverity.Severe, valuesArg, TexlStrings.ErrInvalidSchemaNeedCol); return(false); } TypedName column = columns.Single(); if (nameNode != null && columnType.IsValid && !columnType.Accepts(column.Type)) { errors.EnsureError(DocumentErrorSeverity.Severe, valuesArg, TexlStrings.ErrTypeError_Arg_Expected_Found, nameNode.Value, columnType.GetKindString(), column.Type.GetKindString()); fValid = false; } return(fValid); }
public override void PostVisit(DottedNameNode node) { Contracts.AssertValue(node); DType lhsType = _txb.GetType(node.Left); DType typeRhs = DType.Invalid; DName nameRhs = node.Right.Name; FirstNameInfo firstNameInfo; FirstNameNode firstNameNode; IExternalTableMetadata tableMetadata; DType nodeType = DType.Unknown; if (node.Left.Kind != NodeKind.FirstName && node.Left.Kind != NodeKind.DottedName) { SetDottedNameError(node, TexlStrings.ErrInvalidName); return; } nameRhs = GetLogicalNodeNameAndUpdateDisplayNames(lhsType, node.Right); if (!lhsType.TryGetType(nameRhs, out typeRhs)) { SetDottedNameError(node, TexlStrings.ErrInvalidName); return; } // There are two cases: // 1. RHS could be an option set. // 2. RHS could be a data entity. // 3. RHS could be a column name and LHS would be a datasource. if (typeRhs.IsOptionSet) { nodeType = typeRhs; } else if (typeRhs.IsExpandEntity) { var entityInfo = typeRhs.ExpandInfo; Contracts.AssertValue(entityInfo); string entityPath = string.Empty; if (lhsType.HasExpandInfo) { entityPath = lhsType.ExpandInfo.ExpandPath.ToString(); } DType expandedEntityType = GetExpandedEntityType(typeRhs, entityPath); var parentDataSource = entityInfo.ParentDataSource; var metadata = new DataTableMetadata(parentDataSource.Name, parentDataSource.Name); nodeType = DType.CreateMetadataType(new DataColumnMetadata(typeRhs.ExpandInfo.Name, expandedEntityType, metadata)); } else if ((firstNameNode = node.Left.AsFirstName()) != null && (firstNameInfo = _txb.GetInfo(firstNameNode)) != null) { var tabularDataSourceInfo = firstNameInfo.Data as IExternalTabularDataSource; tableMetadata = tabularDataSourceInfo?.TableMetadata; if (tableMetadata == null || !tableMetadata.TryGetColumn(nameRhs.Value, out var columnMetadata) || !IsColumnMultiChoice(columnMetadata)) { SetDottedNameError(node, TexlStrings.ErrInvalidName); return; } var metadata = new DataTableMetadata(tabularDataSourceInfo.Name, tableMetadata.DisplayName); nodeType = DType.CreateMetadataType(new DataColumnMetadata(columnMetadata, metadata)); } else { SetDottedNameError(node, TexlStrings.ErrInvalidName); return; } Contracts.AssertValid(nodeType); _txb.SetType(node, nodeType); _txb.SetInfo(node, new DottedNameInfo(node)); }
public override bool CheckInvocation(TexlBinding binding, TexlNode[] args, DType[] argTypes, IErrorContainer errors, out DType returnType, out Dictionary <TexlNode, DType> nodeToCoercedTypeMap) { Contracts.AssertValue(args); Contracts.AssertValue(argTypes); Contracts.Assert(args.Length == argTypes.Length); Contracts.AssertValue(errors); Contracts.Assert(MinArity <= args.Length && args.Length <= MaxArity); bool isValidInvocation = base.CheckInvocation(args, argTypes, errors, out returnType, out nodeToCoercedTypeMap); Contracts.Assert(returnType.IsTable); if (!argTypes[0].IsTable) { isValidInvocation = false; errors.EnsureError(DocumentErrorSeverity.Severe, args[0], TexlStrings.ErrNeedTable_Func, Name); } else { returnType = argTypes[0]; } DType colsToKeep = DType.EmptyTable; // The result type has N columns, as specified by (args[1],args[2],args[3],...) int count = args.Length; for (var i = 1; i < count; i++) { TexlNode nameArg = args[i]; DType nameArgType = argTypes[i]; // Verify we have a string literal for the column name. Accd to spec, we don't support // arbitrary expressions that evaluate to string values, because these values contribute to // type analysis, so they need to be known upfront (before ShowColumns executes). StrLitNode nameNode; if (nameArgType.Kind != DKind.String || (nameNode = nameArg.AsStrLit()) == null) { isValidInvocation = false; errors.EnsureError(DocumentErrorSeverity.Severe, nameArg, TexlStrings.ErrExpectedStringLiteralArg_Name, nameArg.ToString()); continue; } // Verify that the name is valid. if (!DName.IsValidDName(nameNode.Value)) { isValidInvocation = false; errors.EnsureError(DocumentErrorSeverity.Severe, nameArg, TexlStrings.ErrArgNotAValidIdentifier_Name, nameNode.Value); continue; } DName columnName = new DName(nameNode.Value); // Verify that the name exists. DType columnType; if (!returnType.TryGetType(columnName, out columnType)) { isValidInvocation = false; returnType.ReportNonExistingName(FieldNameKind.Logical, errors, columnName, args[i]); continue; } // Verify that the name was only specified once. DType existingColumnType; if (colsToKeep.TryGetType(columnName, out existingColumnType)) { isValidInvocation = false; errors.EnsureError(DocumentErrorSeverity.Warning, nameArg, TexlStrings.WarnColumnNameSpecifiedMultipleTimes_Name, columnName); continue; } // Make a note of which columns are being kept. Contracts.Assert(columnType.IsValid); colsToKeep = colsToKeep.Add(columnName, columnType); } // Drop everything but the columns that need to be kept. returnType = colsToKeep; return(isValidInvocation); }