Пример #1
0
        public ObjectInstance GetOrCreate(JsValue key)
        {
            BlittableObjectProperty property = default;

            if (OwnValues?.TryGetValue(key, out property) == true &&
                property != null)
            {
                return(property.Value.AsObject());
            }

            property = GenerateProperty(key.AsString());

            OwnValues ??= new Dictionary <JsValue, BlittableObjectProperty>(Blittable.Count);

            OwnValues[key] = property;
            Deletes?.Remove(key);

            return(property.Value.AsObject());

            BlittableObjectProperty GenerateProperty(string propertyName)
            {
                var propertyIndex = Blittable.GetPropertyIndex(propertyName);

                var prop = new BlittableObjectProperty(this, propertyName);

                if (propertyIndex == -1)
                {
                    prop.Value = new ObjectInstance(Engine);
                }

                return(prop);
            }
        }
Пример #2
0
        public ObjectInstance GetOrCreate(string key)
        {
            if (OwnValues.TryGetValue(key, out var property) == false)
            {
                property = GenerateProperty(key);

                OwnValues[key] = property;
                Deletes?.Remove(key);
            }

            return(property.Value.AsObject());

            BlittableObjectProperty GenerateProperty(string propertyName)
            {
                var propertyIndex = Blittable.GetPropertyIndex(propertyName);

                var prop = new BlittableObjectProperty(this, propertyName);

                if (propertyIndex == -1)
                {
                    prop.Value = new ObjectInstance(Engine)
                    {
                        Extensible = true
                    };
                }

                return(prop);
            }
        }
Пример #3
0
        public ObjectInstance GetOrCreate(string key)
        {
            BlittableObjectProperty value;

            if (OwnValues.TryGetValue(key, out value) == false)
            {
                var propertyIndex = Blittable.GetPropertyIndex(key);
                value = new BlittableObjectProperty(this, key);
                if (propertyIndex == -1)
                {
                    value.Value = new JsValue(new ObjectInstance(Engine));
                }
                OwnValues[key] = value;
                Deletes?.Remove(key);
            }
            return(value.Value.AsObject());
        }
Пример #4
0
        public void Remove(string property)
        {
            if (_source == null)
            {
                throw new InvalidOperationException(
                          "Cannot remove property when not setup with a source blittable json object");
            }

            var propertyIndex = _source.GetPropertyIndex(property);

            if (propertyIndex == -1)
            {
                return;
            }

            if (Removals == null)
            {
                Removals = new HashSet <int>();
            }
            Removals.Add(propertyIndex);
        }
Пример #5
0
        public override BlittableJsonReaderObject GetUpdatedValue(JsonOperationContext context, BlittableJsonReaderObject previousValue, long index)
        {
            if (previousValue == null)
            {
                return(null);
            }

            var propertyIndex = previousValue.GetPropertyIndex(Value);

            if (propertyIndex == -1)
            {
                return(null);
            }

            previousValue.Modifications ??= new DynamicJsonValue();

            previousValue.Modifications.Removals = new HashSet <int> {
                propertyIndex
            };
            return(context.ReadObject(previousValue, Name));
        }
Пример #6
0
        private static unsafe bool CompareBlittable(string fieldPath, string id, BlittableJsonReaderObject originalBlittable,
                                                    BlittableJsonReaderObject newBlittable, IDictionary <string, DocumentsChanges[]> changes,
                                                    List <DocumentsChanges> docChanges)
        {
            BlittableJsonReaderObject.AssertNoModifications(originalBlittable, id, assertChildren: false);
            BlittableJsonReaderObject.AssertNoModifications(newBlittable, id, assertChildren: false);

            var newBlittableProps = newBlittable.GetPropertyNames();
            var oldBlittableProps = originalBlittable.GetPropertyNames();
            var newFields         = new HashSet <string>(newBlittableProps);

            newFields.ExceptWith(oldBlittableProps);
            var removedFields = new HashSet <string>(oldBlittableProps);

            removedFields.ExceptWith(newBlittableProps);

            using var orderedProperties = newBlittable.GetPropertiesByInsertionOrder();

            foreach (var field in removedFields)
            {
                if (changes == null)
                {
                    return(true);
                }
                if (field.Equals(LastModified) ||
                    field.Equals(ChangeVector) ||
                    field.Equals(Id))
                {
                    continue;
                }
                NewChange(fieldPath, field, null, null, docChanges, DocumentsChanges.ChangeType.RemovedField);
            }

            var newProp = new BlittableJsonReaderObject.PropertyDetails();
            var oldProp = new BlittableJsonReaderObject.PropertyDetails();

            for (int i = 0; i < orderedProperties.Size; i++)
            {
                newBlittable.GetPropertyByIndex(orderedProperties.Properties[i], ref newProp);

                if (newProp.Name.Equals(LastModified) ||
                    newProp.Name.Equals(Collection) ||
                    newProp.Name.Equals(ChangeVector) ||
                    newProp.Name.Equals(Id))
                {
                    continue;
                }

                if (newFields.Contains(newProp.Name))
                {
                    if (changes == null)
                    {
                        return(true);
                    }
                    NewChange(fieldPath, newProp.Name, newProp.Value, null, docChanges, DocumentsChanges.ChangeType.NewField);
                    continue;
                }

                var oldPropId = originalBlittable.GetPropertyIndex(newProp.Name);
                originalBlittable.GetPropertyByIndex(oldPropId, ref oldProp);

                switch ((newProp.Token & BlittableJsonReaderBase.TypesMask))
                {
                case BlittableJsonToken.Integer:
                case BlittableJsonToken.Boolean:
                case BlittableJsonToken.LazyNumber:
                case BlittableJsonToken.CompressedString:
                case BlittableJsonToken.String:
                    if (newProp.Value.Equals(oldProp.Value) || CompareValues(oldProp, newProp) ||
                        CompareStringsWithEscapePositions(newBlittable._context, oldProp, newProp))
                    {
                        break;
                    }
                    if (changes == null)
                    {
                        return(true);
                    }
                    NewChange(fieldPath, newProp.Name, newProp.Value, oldProp.Value, docChanges,
                              DocumentsChanges.ChangeType.FieldChanged);
                    break;

                case BlittableJsonToken.Null:
                    if (oldProp.Value == null)
                    {
                        break;
                    }
                    if (changes == null)
                    {
                        return(true);
                    }
                    NewChange(fieldPath, newProp.Name, null, oldProp.Value, docChanges,
                              DocumentsChanges.ChangeType.FieldChanged);
                    break;

                case BlittableJsonToken.StartArray:
                    var newArray = newProp.Value as BlittableJsonReaderArray;
                    var oldArray = oldProp.Value as BlittableJsonReaderArray;

                    if (newArray == null)
                    {
                        throw new InvalidDataException($"Invalid blittable, expected array but got {newProp.Value}");
                    }

                    if (oldArray == null)
                    {
                        if (changes == null)
                        {
                            return(true);
                        }

                        NewChange(fieldPath, newProp.Name, newProp.Value, oldProp.Value, docChanges,
                                  DocumentsChanges.ChangeType.FieldChanged);

                        break;
                    }

                    var changed = CompareBlittableArray(FieldPathCombine(fieldPath, newProp.Name), id, oldArray, newArray, changes, docChanges, newProp.Name);
                    if (changes == null && changed)
                    {
                        return(true);
                    }

                    break;

                case BlittableJsonToken.StartObject:
                    if (oldProp.Value == null ||
                        !(oldProp.Value is BlittableJsonReaderObject oldObj))
                    {
                        if (changes == null)
                        {
                            return(true);
                        }

                        NewChange(fieldPath, newProp.Name, newProp.Value, oldProp.Value, docChanges,
                                  DocumentsChanges.ChangeType.FieldChanged);
                        break;
                    }

                    if (!(newProp.Value is BlittableJsonReaderObject newObj))
                    {
                        throw new InvalidDataException($"Invalid blittable, expected object but got {newProp.Value}");
                    }

                    changed = CompareBlittable(FieldPathCombine(fieldPath, newProp.Name), id, oldObj, newObj, changes, docChanges);
                    if (changes == null && changed)
                    {
                        return(true);
                    }

                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            if ((changes == null) || (docChanges.Count <= 0))
            {
                return(false);
            }

            changes[id] = docChanges.ToArray();
            return(true);
        }
Пример #7
0
        private static bool CompareBlittable(string id, BlittableJsonReaderObject originalBlittable,
                                             BlittableJsonReaderObject newBlittable, IDictionary <string, DocumentsChanges[]> changes,
                                             List <DocumentsChanges> docChanges)
        {
            BlittableJsonReaderObject.AssertNoModifications(originalBlittable, id, assertChildren: false);
            BlittableJsonReaderObject.AssertNoModifications(newBlittable, id, assertChildren: false);

            var newBlittableProps = newBlittable.GetPropertyNames();
            var oldBlittableProps = originalBlittable.GetPropertyNames();
            var newFields         = newBlittableProps.Except(oldBlittableProps);
            var removedFields     = oldBlittableProps.Except(newBlittableProps);

            var propertiesIds = newBlittable.GetPropertiesByInsertionOrder();

            foreach (var field in removedFields)
            {
                if (changes == null)
                {
                    return(true);
                }
                NewChange(field, null, null, docChanges, DocumentsChanges.ChangeType.RemovedField);
            }

            var newProp = new BlittableJsonReaderObject.PropertyDetails();
            var oldProp = new BlittableJsonReaderObject.PropertyDetails();

            foreach (var propId in propertiesIds)
            {
                newBlittable.GetPropertyByIndex(propId, ref newProp);

                if (newProp.Name.Equals(LastModified) ||
                    newProp.Name.Equals(Collection) ||
                    newProp.Name.Equals(ChangeVector) ||
                    newProp.Name.Equals(Id))
                {
                    continue;
                }

                if (newFields.Contains(newProp.Name))
                {
                    if (changes == null)
                    {
                        return(true);
                    }
                    NewChange(newProp.Name, newProp.Value, null, docChanges, DocumentsChanges.ChangeType.NewField);
                    continue;
                }

                var oldPropId = originalBlittable.GetPropertyIndex(newProp.Name);
                originalBlittable.GetPropertyByIndex(oldPropId, ref oldProp);

                switch ((newProp.Token & BlittableJsonReaderBase.TypesMask))
                {
                case BlittableJsonToken.Integer:
                case BlittableJsonToken.Boolean:
                case BlittableJsonToken.LazyNumber:
                case BlittableJsonToken.CompressedString:
                case BlittableJsonToken.String:
                    if (newProp.Value.Equals(oldProp.Value) || ComapreValues(oldProp, newProp))
                    {
                        break;
                    }
                    if (changes == null)
                    {
                        return(true);
                    }
                    NewChange(newProp.Name, newProp.Value, oldProp.Value, docChanges,
                              DocumentsChanges.ChangeType.FieldChanged);
                    break;

                case BlittableJsonToken.Null:
                    if (oldProp.Value == null)
                    {
                        break;
                    }
                    if (changes == null)
                    {
                        return(true);
                    }
                    NewChange(newProp.Name, null, oldProp.Value, docChanges,
                              DocumentsChanges.ChangeType.FieldChanged);
                    break;

                case BlittableJsonToken.StartArray:
                    var newArray = newProp.Value as BlittableJsonReaderArray;
                    var oldArray = oldProp.Value as BlittableJsonReaderArray;

                    if ((newArray == null) || (oldArray == null))
                    {
                        throw new InvalidDataException("Invalid blittable");
                    }

                    var changed = CompareBlittableArray(id, oldArray, newArray, changes, docChanges, newProp.Name);
                    if (changed == false)
                    {
                        break;
                    }

                    if (changes == null)
                    {
                        return(true);
                    }

                    break;

                case BlittableJsonToken.StartObject:
                    if (oldProp.Value == null)
                    {
                        if (changes == null)
                        {
                            return(true);
                        }

                        changed = true;
                        NewChange(newProp.Name, newProp.Value, null, docChanges,
                                  DocumentsChanges.ChangeType.FieldChanged);
                    }
                    else
                    {
                        changed = CompareBlittable(id, oldProp.Value as BlittableJsonReaderObject,
                                                   newProp.Value as BlittableJsonReaderObject, changes, docChanges);
                    }

                    if ((changes == null) && (changed))
                    {
                        return(true);
                    }

                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            if ((changes == null) || (docChanges.Count <= 0))
            {
                return(false);
            }

            changes[id] = docChanges.ToArray();
            return(true);
        }