Example #1
0
        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"));
            };
        }
Example #2
0
        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");
            };
        }
Example #3
0
        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"));
            };
        }
Example #4
0
        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> >();
                    };
                };
            };
        }