IGNITE-6523 .NET: QueryField.NotNull
authorPavel Tupitsyn <ptupitsyn@apache.org>
Fri, 29 Sep 2017 12:22:36 +0000 (15:22 +0300)
committerPavel Tupitsyn <ptupitsyn@apache.org>
Fri, 29 Sep 2017 12:22:36 +0000 (15:22 +0300)
12 files changed:
modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java
modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheConfigurationTest.cs
modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheDmlQueriesTest.cs
modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesCodeConfigurationTest.cs
modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs
modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/cache-query.xml
modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/full-config.xml
modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs
modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QueryEntity.cs
modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QueryField.cs
modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QuerySqlFieldAttribute.cs
modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd

index e223193..66160fb 100644 (file)
@@ -459,6 +459,7 @@ public class PlatformConfigurationUtils {
         // Fields
         int cnt = in.readInt();
         Set<String> keyFields = new HashSet<>(cnt);
+        Set<String> notNullFields = new HashSet<>(cnt);
 
         if (cnt > 0) {
             LinkedHashMap<String, String> fields = new LinkedHashMap<>(cnt);
@@ -471,12 +472,18 @@ public class PlatformConfigurationUtils {
 
                 if (in.readBoolean())
                     keyFields.add(fieldName);
+
+                if (in.readBoolean())
+                    notNullFields.add(fieldName);
             }
 
             res.setFields(fields);
 
             if (!keyFields.isEmpty())
                 res.setKeyFields(keyFields);
+
+            if (!notNullFields.isEmpty())
+                res.setNotNullFields(notNullFields);
         }
 
         // Aliases
@@ -937,6 +944,7 @@ public class PlatformConfigurationUtils {
 
         if (fields != null) {
             Set<String> keyFields = queryEntity.getKeyFields();
+            Set<String> notNullFields = queryEntity.getNotNullFields();
 
             writer.writeInt(fields.size());
 
@@ -944,6 +952,7 @@ public class PlatformConfigurationUtils {
                 writer.writeString(field.getKey());
                 writer.writeString(field.getValue());
                 writer.writeBoolean(keyFields != null && keyFields.contains(field.getKey()));
+                writer.writeBoolean(notNullFields != null && notNullFields.contains(field.getKey()));
             }
         }
         else
index 4e5d443..abf8af0 100644 (file)
@@ -511,6 +511,7 @@ namespace Apache.Ignite.Core.Tests.Cache
             Assert.AreEqual(x.Name, y.Name);
             Assert.AreEqual(x.FieldTypeName, y.FieldTypeName);
             Assert.AreEqual(x.IsKeyField, y.IsKeyField);
+            Assert.AreEqual(x.NotNull, y.NotNull);
         }
 
         /// <summary>
@@ -587,7 +588,7 @@ namespace Apache.Ignite.Core.Tests.Cache
                         {
                             new QueryField("length", typeof(int)), 
                             new QueryField("name", typeof(string)) {IsKeyField = true},
-                            new QueryField("location", typeof(string)),
+                            new QueryField("location", typeof(string)) {NotNull = true},
                         },
                         Aliases = new [] {new QueryAlias("length", "len") },
                         Indexes = new[]
index 9d16799..a6ddc8c 100644 (file)
@@ -103,6 +103,44 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
         }
 
         /// <summary>
+        /// Tests the NotNull constraint.
+        /// </summary>
+        [Test]
+        public void TestNotNull()
+        {
+            var cfg = new CacheConfiguration("not_null", new QueryEntity(typeof(int), typeof(Foo))
+            {
+                Fields = new[]
+                {
+                    new QueryField("id", typeof(int)) {NotNull = true}, 
+                    new QueryField("name", typeof(string)) 
+                }
+            });
+
+            var cache = Ignition.GetIgnite().CreateCache<int, Foo>(cfg);
+
+            var ex = Assert.Throws<IgniteException>(() => cache.QueryFields(new SqlFieldsQuery(
+                "insert into foo(_key, name) values (?, ?)", 1, "bar")).GetAll());
+
+            Assert.AreEqual("Null value is not allowed for field 'ID'", ex.Message);
+        }
+
+        /// <summary>
+        /// Tests the NotNull constraint.
+        /// </summary>
+        [Test]
+        public void TestNotNullAttribute()
+        {
+            var cfg = new CacheConfiguration("not_null_attr", new QueryEntity(typeof(int), typeof(Foo)));
+            var cache = Ignition.GetIgnite().CreateCache<int, Foo>(cfg);
+
+            var ex = Assert.Throws<IgniteException>(() => cache.QueryFields(new SqlFieldsQuery(
+                "insert into foo(_key, id) values (?, ?)", 1, 2)).GetAll());
+
+            Assert.AreEqual("Null value is not allowed for field 'NAME'", ex.Message);
+        }
+
+        /// <summary>
         /// Tests all primitive key types.
         /// </summary>
         [Test]
@@ -388,7 +426,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
         private class Foo
         {
             [QuerySqlField] public int Id { get; set; }
-            [QuerySqlField] public string Name { get; set; }
+            [QuerySqlField(NotNull = true)] public string Name { get; set; }
         }
 
         /// <summary>
index 7421b95..2e24ff6 100644 (file)
@@ -125,6 +125,9 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
                 "GroupIndex1", "GroupIndex2", "GroupIndex3"
             }, fields.Select(x => x.Name));
 
+            Assert.IsTrue(fields.Single(x => x.Name == "SqlField").NotNull);
+            Assert.IsFalse(fields.Single(x => x.Name == "IndexedField1").NotNull);
+
             var idx = qe.Indexes.ToArray();
 
             Assert.AreEqual(QueryIndexType.Sorted, idx[0].IndexType);
@@ -314,7 +317,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
         /// </summary>
         private class AttributeTest
         {
-            [QuerySqlField]
+            [QuerySqlField(NotNull = true)]
             public double SqlField { get; set; }
 
             [QuerySqlField(IsIndexed = true, Name = "IndexedField1", IsDescending = true, IndexInlineSize = 513)]
index 6361850..9c63c73 100644 (file)
@@ -687,8 +687,15 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
         {
             var entity = Cache().GetConfiguration().QueryEntities.Single();
 
-            Assert.AreEqual(typeof(int), entity.Fields.Single(x => x.Name == "age").FieldType);
-            Assert.AreEqual(typeof(string), entity.Fields.Single(x => x.Name == "name").FieldType);
+            var ageField = entity.Fields.Single(x => x.Name == "age");
+            Assert.AreEqual(typeof(int), ageField.FieldType);
+            Assert.IsFalse(ageField.NotNull);
+            Assert.IsFalse(ageField.IsKeyField);
+
+            var nameField = entity.Fields.Single(x => x.Name == "name");
+            Assert.AreEqual(typeof(string), nameField.FieldType);
+            Assert.IsTrue(nameField.NotNull);
+            Assert.IsFalse(nameField.IsKeyField);
         }
 
         /// <summary>
index 3b61d8d..87e65a2 100644 (file)
                                         <entry key="name" value="java.lang.String" />
                                     </util:map>
                                 </property>
+                                <property name="notNullFields">
+                                    <list>
+                                        <value>name</value>
+                                    </list>
+                                </property>
                                 <property name="indexes">
                                     <list>
                                         <bean class="org.apache.ignite.cache.QueryIndex">
index f6854e1..229d42e 100644 (file)
@@ -55,7 +55,7 @@
             <queryEntities>
                 <queryEntity keyType='System.Int32' valueType='System.String' tableName='myTable'>
                     <fields>
-                        <queryField name='length' fieldType='System.Int32' isKeyField='true' />
+                        <queryField name='length' fieldType='System.Int32' isKeyField='true' notNull='true' />
                     </fields>
                     <aliases>
                         <queryAlias fullName='somefield.field' alias='shortField' />
index b04f466..edecccc 100644 (file)
@@ -115,6 +115,7 @@ namespace Apache.Ignite.Core.Tests
             Assert.AreEqual("length", queryEntity.Fields.Single().Name);
             Assert.AreEqual(typeof(int), queryEntity.Fields.Single().FieldType);
             Assert.IsTrue(queryEntity.Fields.Single().IsKeyField);
+            Assert.IsTrue(queryEntity.Fields.Single().NotNull);
             Assert.AreEqual("somefield.field", queryEntity.Aliases.Single().FullName);
             Assert.AreEqual("shortField", queryEntity.Aliases.Single().Alias);
 
@@ -600,7 +601,11 @@ namespace Apache.Ignite.Core.Tests
                             {
                                 Fields = new[]
                                 {
-                                    new QueryField("field", typeof (int)) { IsKeyField = true }
+                                    new QueryField("field", typeof (int))
+                                    {
+                                        IsKeyField = true,
+                                        NotNull = true
+                                    }
                                 },
                                 Indexes = new[]
                                 {
index b40231c..e8d0c91 100644 (file)
@@ -51,6 +51,7 @@ namespace Apache.Ignite.Core.Cache.Configuration
         /** */
         private Dictionary<string, string> _aliasMap;
 
+        /** */
         private ICollection<QueryAlias> _aliases;
 
         /// <summary>
@@ -241,9 +242,7 @@ namespace Apache.Ignite.Core.Cache.Configuration
             var count = reader.ReadInt();
             Fields = count == 0
                 ? null
-                : Enumerable.Range(0, count).Select(x =>
-                    new QueryField(reader.ReadString(), reader.ReadString()) {IsKeyField = reader.ReadBoolean()})
-                    .ToList();
+                : Enumerable.Range(0, count).Select(x => new QueryField(reader)).ToList();
 
             count = reader.ReadInt();
             Aliases = count == 0 ? null : Enumerable.Range(0, count)
@@ -271,9 +270,7 @@ namespace Apache.Ignite.Core.Cache.Configuration
 
                 foreach (var field in Fields)
                 {
-                    writer.WriteString(field.Name);
-                    writer.WriteString(field.FieldTypeName);
-                    writer.WriteBoolean(field.IsKeyField);
+                    field.Write(writer);
                 }
             }
             else
@@ -456,11 +453,15 @@ namespace Apache.Ignite.Core.Cache.Configuration
                         indexes.Add(new QueryIndexEx(columnName, attr.IsDescending, QueryIndexType.Sorted,
                             attr.IndexGroups)
                         {
-                            InlineSize = attr.IndexInlineSize
+                            InlineSize = attr.IndexInlineSize,
                         });
                     }
 
-                    fields.Add(new QueryField(columnName, memberInfo.Value) {IsKeyField = isKey});
+                    fields.Add(new QueryField(columnName, memberInfo.Value)
+                    {
+                        IsKeyField = isKey,
+                        NotNull = attr.NotNull
+                    });
 
                     ScanAttributes(memberInfo.Value, fields, indexes, columnName, visitedTypes, isKey);
                 }
index 596837a..b8142fd 100644 (file)
@@ -21,6 +21,7 @@ namespace Apache.Ignite.Core.Cache.Configuration
 {
     using System;
     using System.Diagnostics;
+    using Apache.Ignite.Core.Binary;
     using Apache.Ignite.Core.Impl.Binary;
     using Apache.Ignite.Core.Impl.Common;
     using Apache.Ignite.Core.Log;
@@ -73,6 +74,32 @@ namespace Apache.Ignite.Core.Cache.Configuration
         }
 
         /// <summary>
+        /// Initializes a new instance of the <see cref="QueryField"/> class.
+        /// </summary>
+        internal QueryField(IBinaryRawReader reader)
+        {
+            Debug.Assert(reader != null);
+
+            Name = reader.ReadString();
+            FieldTypeName = reader.ReadString();
+            IsKeyField = reader.ReadBoolean();
+            NotNull = reader.ReadBoolean();
+        }
+
+        /// <summary>
+        /// Writes this instance to the specified writer.
+        /// </summary>
+        internal void Write(IBinaryRawWriter writer)
+        {
+            Debug.Assert(writer != null);
+
+            writer.WriteString(Name);
+            writer.WriteString(FieldTypeName);
+            writer.WriteBoolean(IsKeyField);
+            writer.WriteBoolean(NotNull);
+        }
+
+        /// <summary>
         /// Gets or sets the field name.
         /// </summary>
         public string Name { get; set; }
@@ -115,6 +142,11 @@ namespace Apache.Ignite.Core.Cache.Configuration
         public bool IsKeyField { get; set; }
 
         /// <summary>
+        /// Gets or sets a value indicating whether null value is allowed for the field.
+        /// </summary>
+        public bool NotNull { get; set; }
+
+        /// <summary>
         /// Validates this instance and outputs information to the log, if necessary.
         /// </summary>
         internal void Validate(ILogger log, string logInfo)
index b920304..d15cc1a 100644 (file)
@@ -71,5 +71,10 @@ namespace Apache.Ignite.Core.Cache.Configuration
         /// </summary>
         [DefaultValue(QueryIndex.DefaultInlineSize)]
         public int IndexInlineSize { get; set; }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether null values are allowed for this field.
+        /// </summary>
+        public bool NotNull { get; set; }
     }
 }
index 730cb9f..988fa1f 100644 (file)
                                                                                             <xs:documentation>Indicates whether this field belongs to the cache key.</xs:documentation>
                                                                                         </xs:annotation>
                                                                                     </xs:attribute>
+                                                                                    <xs:attribute name="notNull" type="xs:boolean">
+                                                                                        <xs:annotation>
+                                                                                            <xs:documentation>Indicates whether null value is allowed for the field.</xs:documentation>
+                                                                                        </xs:annotation>
+                                                                                    </xs:attribute>
                                                                                 </xs:complexType>
                                                                             </xs:element>
                                                                         </xs:sequence>