public void describe_Subtract() { context["a nullable type - null produces the type"] = () => { Subtraction(SqlDataType.Int.ToNullable(), NullDataType.Instance, SqlDataType.Int); Subtraction(KnownSetDecoratorDataType.IntIncludingSet(1, 2, 3).ToNullable(), NullDataType.Instance, KnownSetDecoratorDataType.IntIncludingSet(1, 2, 3)); Subtraction(DomainDecoratorDataType.Int("Bob").ToNullable(), NullDataType.Instance, DomainDecoratorDataType.Int("Bob")); }; context["KnownSet"] = () => { Subtraction(KnownSetDecoratorDataType.IntIncludingSet(1, 2, 3), KnownSetDecoratorDataType.IntIncludingSet(1), KnownSetDecoratorDataType.IntIncludingSet(2, 3)); }; context["Domain"] = () => { Subtraction(DomainDecoratorDataType.Int("Bob"), DomainDecoratorDataType.Int("Jane"), DomainDecoratorDataType.Int("Bob")); }; }
public void describe_IsAssignableTo() { context["VarChar"] = () => { context["without a domain"] = () => { GoodTypeAssignment(SqlDataType.VarChar, SqlDataType.VarChar); GoodTypeAssignment(new SizedSqlDataType(SizedDataTypeOption.VarChar, 50), new SizedSqlDataType(SizedDataTypeOption.VarChar, 50)); GoodTypeAssignment(new SizedSqlDataType(SizedDataTypeOption.VarChar, 50), new SizedSqlDataType(SizedDataTypeOption.VarChar, 100)); GoodTypeAssignment(SqlDataType.VarChar, SqlDataType.NVarChar, "An NVarChar can hold the representation of a VarChar"); BadTypeAssignment(SqlDataType.VarChar, SqlDataType.Int); BadTypeAssignment(new SizedSqlDataType(SizedDataTypeOption.VarChar, 100), new SizedSqlDataType(SizedDataTypeOption.VarChar, 50)); }; }; context["NVarChar"] = () => { context["without a domain"] = () => { GoodTypeAssignment(SqlDataType.NVarChar, SqlDataType.NVarChar); BadTypeAssignment(SqlDataType.NVarChar, SqlDataType.VarChar); BadTypeAssignment(SqlDataType.NVarChar, SqlDataType.Int); }; }; context["Integers"] = () => { context["without a domain"] = () => { GoodTypeAssignment(SqlDataType.Int, new SqlDataType(ScriptDom.SqlDataTypeOption.Int)); BadTypeAssignment(SqlDataType.Int, SqlDataType.VarChar); BadTypeAssignment(SqlDataType.Int, DomainDecoratorDataType.Int("X"), because: "there is no way to vouch for a domain"); BadTypeAssignment(SqlDataType.Int, KnownSetDecoratorDataType.IntIncludingSet(1, 2, 3)); BadTypeAssignment(SqlDataType.Int, new RowDataType()); }; context["with a domain"] = () => { GoodTypeAssignment(DomainDecoratorDataType.Int("X"), SqlDataType.Int); GoodTypeAssignment(DomainDecoratorDataType.Int("X"), DomainDecoratorDataType.Int("X")); BadTypeAssignment(DomainDecoratorDataType.Int("X"), KnownSetDecoratorDataType.IntIncludingSet(1, 2)); BadTypeAssignment(DomainDecoratorDataType.Int("X"), DomainDecoratorDataType.Int("Y")); }; context["with a known set"] = () => { GoodTypeAssignment(KnownSetDecoratorDataType.IntIncludingSet(1, 2), SqlDataType.Int); GoodTypeAssignment(KnownSetDecoratorDataType.IntIncludingSet(1), KnownSetDecoratorDataType.IntIncludingSet(1, 2), because: "you can assign a subset to a superset"); BadTypeAssignment(KnownSetDecoratorDataType.IntIncludingSet(1, 2), DomainDecoratorDataType.Int("X")); BadTypeAssignment(KnownSetDecoratorDataType.IntIncludingSet(1, 2), KnownSetDecoratorDataType.IntIncludingSet(1), because: "cannot assign a super set to a subset"); BadTypeAssignment(KnownSetDecoratorDataType.IntIncludingSet(1, 2), KnownSetDecoratorDataType.IntIncludingSet(3, 4), because: "cannot assign sets with no common elements"); }; }; context["Nullable<T>"] = () => { GoodTypeAssignment(SqlDataType.Int, SqlDataType.Int.ToNullable()); GoodTypeAssignment(DomainDecoratorDataType.Int("x"), DomainDecoratorDataType.Int("x").ToNullable()); GoodTypeAssignment(SqlDataType.Int.ToNullable(), SqlDataType.Int.ToNullable()); GoodTypeAssignment(DomainDecoratorDataType.Int("x").ToNullable(), DomainDecoratorDataType.Int("x").ToNullable()); GoodTypeAssignment(new SizedSqlDataType(SizedDataTypeOption.VarChar, 10).ToNullable(), new SizedSqlDataType(SizedDataTypeOption.VarChar, 12).ToNullable()); GoodTypeAssignment(new SizedSqlDataType(SizedDataTypeOption.VarChar, 10), new SizedSqlDataType(SizedDataTypeOption.VarChar, 12).ToNullable()); BadTypeAssignment(SqlDataType.Int, SqlDataType.VarChar.ToNullable()); BadTypeAssignment(SqlDataType.Int.ToNullable(), SqlDataType.Int, "A null cannot fit inside of a non-null"); BadTypeAssignment(new SizedSqlDataType(SizedDataTypeOption.VarChar, 12), new SizedSqlDataType(SizedDataTypeOption.VarChar, 10).ToNullable()); }; context["ColumDataType"] = () => { GoodTypeAssignment(new ColumnDataType(ColumnDataType.ColumnName.Anonymous.Instance, SqlDataType.Int), SqlDataType.Int); GoodTypeAssignment(new ColumnDataType(ColumnDataType.ColumnName.Anonymous.Instance, SqlDataType.VarChar), SqlDataType.VarChar); GoodTypeAssignment(new ColumnDataType(new ColumnDataType.ColumnName.Aliased("x", CaseSensitivity.CaseInsensitive), SqlDataType.Int), SqlDataType.Int); GoodTypeAssignment(new ColumnDataType(new ColumnDataType.ColumnName.Schema("x", CaseSensitivity.CaseInsensitive), SqlDataType.Int), SqlDataType.Int); BadTypeAssignment(new ColumnDataType(ColumnDataType.ColumnName.Anonymous.Instance, SqlDataType.VarChar), SqlDataType.Int); BadTypeAssignment(new ColumnDataType(new ColumnDataType.ColumnName.Aliased("x", CaseSensitivity.CaseInsensitive), SqlDataType.VarChar), SqlDataType.Int); BadTypeAssignment(new ColumnDataType(new ColumnDataType.ColumnName.Schema("x", CaseSensitivity.CaseInsensitive), SqlDataType.VarChar), SqlDataType.Int); }; context["RowDataType"] = () => { var anon = String.Empty; var rowWithIDAndCountSchemaNames = RowBuilder .WithSchemaNamedColumn("id", SqlDataType.Int) .AndSchemaNamedColumn("count", SqlDataType.Int) .CreateRow(); var rowWithCountAndIDSchemaNames = RowBuilder .WithSchemaNamedColumn("count", SqlDataType.Int) .AndSchemaNamedColumn("id", SqlDataType.Int) .CreateRow(); var rowWithIDAndCountAliased = RowBuilder .WithAliasedColumn("id", SqlDataType.Int) .AndAliasedColumn("count", SqlDataType.Int) .CreateRow(); var rowWithCountAndIDAliased = RowBuilder .WithAliasedColumn("count", SqlDataType.Int) .AndAliasedColumn("id", SqlDataType.Int) .CreateRow(); var rowWithAnonymousIntInt = RowBuilder .WithAnonymousColumn(SqlDataType.Int) .AndAnonymousColumn(SqlDataType.Int) .CreateRow(); var rowWithAnonymousIntVarChar = RowBuilder .WithAnonymousColumn(SqlDataType.Int) .AndAnonymousColumn(SqlDataType.VarChar) .CreateRow(); var rowWithAnonymousVarCharInt = RowBuilder .WithAnonymousColumn(SqlDataType.VarChar) .AndAnonymousColumn(SqlDataType.Int) .CreateRow(); // empty rows GoodTypeAssignment(new RowDataType(), new RowDataType()); GoodTypeAssignment(RowBuilder.EmptyRow, rowWithIDAndCountSchemaNames); GoodTypeAssignment(rowWithIDAndCountSchemaNames, RowBuilder.EmptyRow); GoodTypeAssignment(rowWithAnonymousIntVarChar, rowWithAnonymousIntVarChar); GoodTypeAssignment(rowWithIDAndCountSchemaNames, rowWithAnonymousIntInt); GoodTypeAssignment(rowWithAnonymousIntInt, rowWithIDAndCountSchemaNames); GoodTypeAssignment(rowWithIDAndCountSchemaNames, rowWithCountAndIDSchemaNames, because: "Schema names do not have to match because a user could be selecting from one schema object into another"); BadTypeAssignment(rowWithAnonymousVarCharInt, rowWithAnonymousIntVarChar, because: "The types do not align"); BadTypeAssignment(rowWithAnonymousVarCharInt, rowWithIDAndCountSchemaNames, because: "The types do not align"); BadTypeAssignment(rowWithAnonymousVarCharInt, rowWithIDAndCountSchemaNames, because: "The types do not align"); BadTypeAssignment(rowWithIDAndCountAliased, rowWithCountAndIDAliased, because: "Aliases are explicitly applied by author and therefore must match the destination"); BadTypeAssignment(rowWithIDAndCountAliased, rowWithCountAndIDSchemaNames, because: "Aliases are explicitly applied by author and therefore must match the destination"); BadTypeAssignment(rowWithCountAndIDAliased, rowWithIDAndCountAliased, because: "Aliases are explicitly applied by author and therefore must match the destination"); BadTypeAssignment(rowWithCountAndIDAliased, rowWithIDAndCountSchemaNames, because: "Aliases are explicitly applied by author and therefore must match the destination"); }; context["ColumnName"] = () => { GoodColumnNameAssignment(ColumnDataType.ColumnName.Anonymous.Instance, ColumnDataType.ColumnName.Anonymous.Instance); GoodColumnNameAssignment(ColumnDataType.ColumnName.Anonymous.Instance, new ColumnDataType.ColumnName.Aliased("x", CaseSensitivity.CaseInsensitive)); GoodColumnNameAssignment(ColumnDataType.ColumnName.Anonymous.Instance, new ColumnDataType.ColumnName.Schema("x", CaseSensitivity.CaseInsensitive)); GoodColumnNameAssignment(new ColumnDataType.ColumnName.Schema("x", CaseSensitivity.CaseInsensitive), new ColumnDataType.ColumnName.Schema("x", CaseSensitivity.CaseInsensitive)); GoodColumnNameAssignment(new ColumnDataType.ColumnName.Schema("x", CaseSensitivity.CaseInsensitive), new ColumnDataType.ColumnName.Schema("y", CaseSensitivity.CaseInsensitive), because: "Schema names do not have to match"); GoodColumnNameAssignment(new ColumnDataType.ColumnName.Aliased("x", CaseSensitivity.CaseInsensitive), new ColumnDataType.ColumnName.Aliased("x", CaseSensitivity.CaseInsensitive)); GoodColumnNameAssignment(new ColumnDataType.ColumnName.Aliased("x", CaseSensitivity.CaseInsensitive), new ColumnDataType.ColumnName.Schema("x", CaseSensitivity.CaseInsensitive)); GoodColumnNameAssignment(new ColumnDataType.ColumnName.Aliased("x", CaseSensitivity.CaseInsensitive), ColumnDataType.ColumnName.Anonymous.Instance); BadColumnNameAssignment(new ColumnDataType.ColumnName.Aliased("x", CaseSensitivity.CaseInsensitive), new ColumnDataType.ColumnName.Aliased("y", CaseSensitivity.CaseInsensitive), because: "an alias in the source expressing an _intention_ and so must match the dest"); BadColumnNameAssignment(new ColumnDataType.ColumnName.Aliased("x", CaseSensitivity.CaseInsensitive), new ColumnDataType.ColumnName.Schema("y", CaseSensitivity.CaseInsensitive), because: "an alias in the source expressing an _intention_ and so must match the dest"); }; }
public void describe_CanCompareWith() { context["varchar"] = () => { context["with a known set"] = () => { GoodTypeComparison(DomainDecoratorDataType.Int("X"), KnownSetDecoratorDataType.IntIncludingSet(1, 2)); GoodTypeComparison(KnownSetDecoratorDataType.VarCharIncludingSet("apples", "oranges"), SqlDataType.VarChar); GoodTypeComparison(KnownSetDecoratorDataType.VarCharIncludingSet("apples", "oranges"), KnownSetDecoratorDataType.VarCharIncludingSet("apples")); GoodTypeComparison(KnownSetDecoratorDataType.VarCharIncludingSet("apples"), KnownSetDecoratorDataType.VarCharIncludingSet("apples", "oranges")); BadTypeComparison(KnownSetDecoratorDataType.VarCharIncludingSet("apples"), KnownSetDecoratorDataType.VarCharIncludingSet("oranges")); BadTypeComparison(KnownSetDecoratorDataType.VarCharIncludingSet("apples", "bananas"), KnownSetDecoratorDataType.VarCharIncludingSet("oranges", "grapes")); }; }; context["integers"] = () => { context["without a domain"] = () => { GoodTypeComparison(SqlDataType.Int, new SqlDataType(ScriptDom.SqlDataTypeOption.Int)); GoodTypeComparison(SqlDataType.Int, DomainDecoratorDataType.Int("X")); GoodTypeComparison(SqlDataType.Int, KnownSetDecoratorDataType.IntIncludingSet(1, 2)); BadTypeComparison(SqlDataType.Int, SqlDataType.VarChar); BadTypeComparison(SqlDataType.Int, new RowDataType()); }; context["with a domain"] = () => { GoodTypeComparison(DomainDecoratorDataType.Int("X"), SqlDataType.Int); GoodTypeComparison(DomainDecoratorDataType.Int("X"), DomainDecoratorDataType.Int("X")); GoodTypeComparison(DomainDecoratorDataType.Int("X"), KnownSetDecoratorDataType.IntIncludingSet(1, 2)); BadTypeComparison(DomainDecoratorDataType.Int("X"), DomainDecoratorDataType.Int("Y")); }; context["with a known set"] = () => { GoodTypeComparison(KnownSetDecoratorDataType.IntIncludingSet(1, 2), SqlDataType.Int); GoodTypeComparison(KnownSetDecoratorDataType.IntIncludingSet(1), KnownSetDecoratorDataType.IntIncludingSet(1, 2), "you can compare two sets so long as one is a subset of the other"); GoodTypeComparison(KnownSetDecoratorDataType.IntIncludingSet(1, 2), KnownSetDecoratorDataType.IntIncludingSet(1), "you can compare two sets so long as one is a subset of the other"); GoodTypeComparison(KnownSetDecoratorDataType.IntIncludingSet(1, 2), DomainDecoratorDataType.Int("X")); BadTypeComparison(KnownSetDecoratorDataType.IntIncludingSet(1, 2), KnownSetDecoratorDataType.IntIncludingSet(3, 4), "cannot compare two entirely disjoint sets"); }; }; context["ColumDataType"] = () => { GoodTypeComparison(new ColumnDataType(ColumnDataType.ColumnName.Anonymous.Instance, SqlDataType.Int), SqlDataType.Int); GoodTypeComparison(new ColumnDataType(ColumnDataType.ColumnName.Anonymous.Instance, SqlDataType.VarChar), SqlDataType.VarChar); GoodTypeComparison(new ColumnDataType(new ColumnDataType.ColumnName.Aliased("x", CaseSensitivity.CaseInsensitive), SqlDataType.Int), SqlDataType.Int); GoodTypeComparison(new ColumnDataType(new ColumnDataType.ColumnName.Schema("x", CaseSensitivity.CaseInsensitive), SqlDataType.Int), SqlDataType.Int); GoodTypeComparison(new ColumnDataType(ColumnDataType.ColumnName.Anonymous.Instance, KnownSetDecoratorDataType.VarCharIncludingSet("x", "y", "z")), KnownSetDecoratorDataType.VarCharIncludingSet("x")); BadTypeComparison(new ColumnDataType(ColumnDataType.ColumnName.Anonymous.Instance, SqlDataType.VarChar), SqlDataType.Int); BadTypeComparison(new ColumnDataType(new ColumnDataType.ColumnName.Aliased("x", CaseSensitivity.CaseInsensitive), SqlDataType.VarChar), SqlDataType.Int); BadTypeComparison(new ColumnDataType(new ColumnDataType.ColumnName.Schema("x", CaseSensitivity.CaseInsensitive), SqlDataType.VarChar), SqlDataType.Int); BadTypeComparison(new ColumnDataType(ColumnDataType.ColumnName.Anonymous.Instance, KnownSetDecoratorDataType.VarCharIncludingSet("x", "y", "z")), KnownSetDecoratorDataType.VarCharIncludingSet("q")); }; }
public void describe_GivenATopFrame() { before = () => { _frame = new StackFrame(); }; it["LastFrame is null"] = () => { _frame.LastFrame.Should().Be(null); _frame.LookupTypeOfSymbolMaybe("a").Should().BeOfType <None <SymbolTyping> >(); }; context["when empty"] = () => { it["Lookup returns None<DataType>"] = () => _frame.LookupTypeOfSymbolMaybe("a").Should().BeOfType <None <SymbolTyping> >(); it["LookupColumn returns None<ColumnDataType>"] = () => _frame.LookupColumnDataTypeByNameMaybe("a").Should().BeOfType <None <(string, ColumnDataType)> >(); it["GetTypesInCurrentFrame<DataType> should return empty"] = () => _frame.GetReadTypesInCurrentFrame <DataType>().Should().BeEquivalentTo(); it["GetTypesInCurrentFrame<ColumnDataType> should return empty"] = () => _frame.GetReadTypesInCurrentFrame <ColumnDataType>().Should().BeEquivalentTo(); }; context["when myRow, myInt, myOtherInt, and myVarCharEnum symbols added"] = () => { before = () => _frame = new StackFrame() .WithSymbol("myInt", SqlDataType.Int) .WithSymbol("myOtherInt", SqlDataType.Int) .WithSymbol("myVarCharEnum", KnownSetDecoratorDataType.VarCharIncludingSet("Apples", "Oranges", "Bananas")) .WithSymbol("myRow", RowBuilder.WithAliasedColumn("id", SqlDataType.Int).AndAliasedColumn("count", SqlDataType.Int).CreateRow()); it["Lookup(myInt) returns Some<SqlDataType>"] = () => _frame.LookupTypeOfSymbolMaybe("myInt") .Should().BeOfType <Some <SymbolTyping> >() .Which.Value.ExpressionType .Should().BeOfType <SqlDataType>() .Which.SqlDataTypeOption .Should().Be(ScriptDom.SqlDataTypeOption.Int); it["Lookup(MYINT) returns Some<SqlDataType>"] = () => _frame.LookupTypeOfSymbolMaybe("MYINT") .Should().BeOfType <Some <SymbolTyping> >(because: "symbol table lookups should be case insensitive") .Which.Value.ExpressionType .Should().BeOfType <SqlDataType>() .Which.SqlDataTypeOption .Should().Be(ScriptDom.SqlDataTypeOption.Int); it["Lookup(myVarCharEnum) returns Some<SqlDataTypeWithKnownSet"] = () => _frame.LookupTypeOfSymbolMaybe("myVarCharEnum") .Should().BeOfType <Some <SymbolTyping> >() .Which.Value.ExpressionType .Should().BeOfType <KnownSetDecoratorDataType>() .Which.Values.Cast <string>() .Should().BeEquivalentTo("Apples", "Oranges", "Bananas"); it["GetTypesInCurrentFrame<SqlDataType> should return all of the simple types"] = () => _frame.GetReadTypesInCurrentFrame <SqlDataType>().Count().Should().Be(2); it["GetTypesInCurrentFrame<RowDataType> should return the single row"] = () => _frame.GetReadTypesInCurrentFrame <RowDataType>().Single().ColumnDataTypes.NameStrings() .Should().BeEquivalentTo("id", "count"); context["when a new frame is nested with myInt shadowing myInt from parent and a new symbol myMoney"] = () => { before = () => _frame = new StackFrame(_frame) .WithSymbol("myInt", DomainDecoratorDataType.Int("XYZ")) .WithSymbol("myMoney", SqlDataType.Money); it["Lookup(myInt) returns the new int type"] = () => _frame.LookupTypeOfSymbolMaybe("myInt") .Should().BeOfType <Some <SymbolTyping> >() .Which.Value.ExpressionType .Should().BeOfType <DomainDecoratorDataType>() .Which.Domain .Should().Be("XYZ"); it["Lookup(myMoney) returns myMoney (new symbol at this level)"] = () => _frame.LookupTypeOfSymbolMaybe("myMoney") .Should().BeOfType <Some <SymbolTyping> >() .Which.Value.ExpressionType .Should().BeOfType <SqlDataType>() .Which.SqlDataTypeOption .Should().Be(ScriptDom.SqlDataTypeOption.Money); context["when popping the current frame off the stack to return to the prior"] = () => { before = () => _frame = _frame.LastFrame; it["Lookup(myInt) returns the original int type"] = () => _frame.LookupTypeOfSymbolMaybe("myInt") .Should().BeOfType <Some <SymbolTyping> >() .Which.Value.ExpressionType .Should().BeOfType <SqlDataType>() .Which.SqlDataTypeOption .Should().Be(ScriptDom.SqlDataTypeOption.Int); it["Lookup(myMoney) returns None<DataType>"] = () => _frame.LookupTypeOfSymbolMaybe("myMoney") .Should().BeOfType <None <SymbolTyping> >(); }; }; }; }