Пример #1
0
        void CreateSecondaryKeyInfo(List <Tuple <int, IList <SecondaryKeyAttribute> > > attributes,
                                    Dictionary <uint, TableFieldInfo> primaryKeyFields,
                                    RelationVersionInfo prevVersion)
        {
            _secondaryKeys      = new Dictionary <uint, SecondaryKeyInfo>();
            _secondaryKeysNames = new Dictionary <string, uint>();
            var skIndexNames = attributes.SelectMany(t => t.Item2).Select(a => a.Name).Distinct();

            foreach (var indexName in skIndexNames)
            {
                var indexFields = new List <Tuple <int, SecondaryKeyAttribute> >(); //fieldIndex, attribute
                foreach (var kv in attributes)
                {
                    var attr = kv.Item2.FirstOrDefault(a => a.Name == indexName);
                    if (attr == null)
                    {
                        continue;
                    }
                    indexFields.Add(Tuple.Create(kv.Item1, attr));
                }
                var orderedAttrs = indexFields.OrderBy(a => a.Item2.Order).ToList();
                var info         = new SecondaryKeyInfo
                {
                    Name   = indexName,
                    Fields = new List <FieldId>(),
                    Index  = SelectSecondaryKeyIndex(indexName, prevVersion)
                };
                var usedPKFields = new Dictionary <uint, object>();
                foreach (var attr in orderedAttrs)
                {
                    for (uint i = 1; i <= attr.Item2.IncludePrimaryKeyOrder; i++)
                    {
                        usedPKFields.Add(i, null);
                        var pi = _primaryKeyFields.IndexOf(primaryKeyFields[i]);
                        info.Fields.Add(new FieldId(true, (uint)pi));
                    }
                    if (attr.Item1 < 0)
                    {
                        var pkOrder = (uint)-attr.Item1;
                        usedPKFields.Add(pkOrder, null);
                        var pi = _primaryKeyFields.IndexOf(primaryKeyFields[pkOrder]);
                        info.Fields.Add(new FieldId(true, (uint)pi));
                    }
                    else
                    {
                        info.Fields.Add(new FieldId(false, (uint)attr.Item1));
                    }
                }
                //fill all not present parts of primary key
                foreach (var pk in primaryKeyFields)
                {
                    if (!usedPKFields.ContainsKey(pk.Key))
                    {
                        info.Fields.Add(new FieldId(true, (uint)_primaryKeyFields.IndexOf(primaryKeyFields[pk.Key])));
                    }
                }
                _secondaryKeysNames[indexName] = info.Index;
                _secondaryKeys[info.Index]     = info;
            }
        }
Пример #2
0
        uint ReadRelationVersions(uint relationIndex, string name, Dictionary <uint, RelationVersionInfo> relationVersions)
        {
            uint lastPersistedVersion = 0;
            var  relationInfoResolver = new RelationInfoResolver((ObjectDB)_tr.Owner);

            var writer = new SpanWriter();

            writer.WriteByteArrayRaw(ObjectDB.RelationVersionsPrefix);
            writer.WriteVUInt32(relationIndex);
            var prefix = writer.GetSpan().ToArray();

            if (!_trkv.FindFirstKey(prefix))
            {
                return(lastPersistedVersion);
            }
            do
            {
                var keyReader   = new SpanReader(_trkv.GetKey().Slice(prefix.Length));
                var valueReader = new SpanReader(_trkv.GetValue());
                lastPersistedVersion = keyReader.ReadVUInt32();
                var relationVersionInfo = RelationVersionInfo.LoadUnresolved(ref valueReader, name);
                relationVersionInfo.ResolveFieldHandlers(relationInfoResolver.FieldHandlerFactory);
                relationVersions[lastPersistedVersion] = relationVersionInfo;
            } while (_trkv.FindNextKey(prefix));

            return(lastPersistedVersion);
        }
Пример #3
0
        uint ReadRelationVersions(uint relationIndex, string name, Dictionary <uint, RelationVersionInfo> relationVersions)
        {
            uint lastPersistedVersion = 0;

            {
                var relationInfoResolver = new RelationInfoResolver((ObjectDB)_tr.Owner);
                var writer = new ByteBufferWriter();
                writer.WriteByteArrayRaw(ObjectDB.RelationVersionsPrefix);
                writer.WriteVUInt32(relationIndex);
                _trkv.SetKeyPrefix(writer.Data);
                if (!_trkv.FindFirstKey())
                {
                    return(lastPersistedVersion);
                }
                var keyReader   = new KeyValueDBKeyReader(_trkv);
                var valueReader = new KeyValueDBValueReader(_trkv);
                do
                {
                    keyReader.Restart();
                    valueReader.Restart();
                    lastPersistedVersion = keyReader.ReadVUInt32();
                    relationVersions[lastPersistedVersion] = RelationVersionInfo.Load(valueReader,
                                                                                      relationInfoResolver.FieldHandlerFactory, name);
                } while (_trkv.FindNextKey());
            }
            return(lastPersistedVersion);
        }
Пример #4
0
 public RelationVersionInfo(Dictionary <uint, TableFieldInfo> primaryKeyFields,                //order -> info
                            List <Tuple <int, IList <SecondaryKeyAttribute> > > secondaryKeys, //positive: sec key field idx, negative: pk order, attrs
                            TableFieldInfo[] secondaryKeyFields,
                            TableFieldInfo[] fields, RelationVersionInfo prevVersion)
 {
     _primaryKeyFields   = primaryKeyFields.OrderBy(kv => kv.Key).Select(kv => kv.Value).ToArray();
     _secondaryKeyFields = secondaryKeyFields;
     CreateSecondaryKeyInfo(secondaryKeys, primaryKeyFields, prevVersion);
     _fields = fields;
 }
Пример #5
0
 internal static bool Equal(RelationVersionInfo a, RelationVersionInfo b)
 {
     //PKs
     if (a._primaryKeyFields.Count != b._primaryKeyFields.Count)
     {
         return(false);
     }
     for (int i = 0; i < a._primaryKeyFields.Count; i++)
     {
         if (!TableFieldInfo.Equal(a._primaryKeyFields[i], b._primaryKeyFields[i]))
         {
             return(false);
         }
     }
     //SKs
     if (a._secondaryKeys.Count != b._secondaryKeys.Count)
     {
         return(false);
     }
     foreach (var key in a._secondaryKeys)
     {
         SecondaryKeyInfo bInfo;
         if (!b._secondaryKeys.TryGetValue(key.Key, out bInfo))
         {
             return(false);
         }
         if (!SecondaryKeyInfo.Equal(key.Value, bInfo))
         {
             return(false);
         }
     }
     //Fields
     if (a._fields.Length != b._fields.Length)
     {
         return(false);
     }
     for (int i = 0; i < a._fields.Length; i++)
     {
         if (!TableFieldInfo.Equal(a._fields[i], b._fields[i]))
         {
             return(false);
         }
     }
     return(true);
 }
Пример #6
0
        static void CheckThatPrimaryKeyHasNotChanged(string name, RelationVersionInfo info, RelationVersionInfo previousInfo)
        {
            var pkFields     = info.GetPrimaryKeyFields();
            var prevPkFields = previousInfo.GetPrimaryKeyFields();

            if (pkFields.Count != prevPkFields.Count)
            {
                throw new BTDBException($"Change of primary key in relation '{name}' is not allowed. Field count {pkFields.Count} != {prevPkFields.Count}.");
            }
            var en  = pkFields.GetEnumerator();
            var pen = prevPkFields.GetEnumerator();

            while (en.MoveNext() && pen.MoveNext())
            {
                if (!ArePrimaryKeyFieldsCompatible(en.Current.Handler, pen.Current.Handler))
                {
                    throw new BTDBException($"Change of primary key in relation '{name}' is not allowed. Field '{en.Current.Name}' is not compatible.");
                }
            }
        }
Пример #7
0
        uint SelectSecondaryKeyIndex(string indexName, RelationVersionInfo prevVersion)
        {
            uint index = 1;

            if (prevVersion != null)
            {
                if (prevVersion._secondaryKeysNames.TryGetValue(indexName, out index))
                {
                    return(index);
                }
                index = 0;
                while (prevVersion._secondaryKeys.ContainsKey(index))
                {
                    index++;
                }
            }
            while (_secondaryKeys.ContainsKey(index))
            {
                index++;
            }
            return(index); //use fresh one
        }
Пример #8
0
        void UpdateSecondaryKeys(IInternalObjectDBTransaction tr, RelationVersionInfo info, RelationVersionInfo previousInfo)
        {
            foreach (var prevIdx in previousInfo.SecondaryKeys.Keys)
            {
                if (!info.SecondaryKeys.ContainsKey(prevIdx))
                {
                    DeleteSecondaryKey(tr.KeyValueDBTransaction, prevIdx);
                }
            }
            var secKeysToAdd = new List <KeyValuePair <uint, SecondaryKeyInfo> >();

            foreach (var sk in info.SecondaryKeys)
            {
                if (!previousInfo.SecondaryKeys.ContainsKey(sk.Key))
                {
                    secKeysToAdd.Add(sk);
                }
            }
            if (secKeysToAdd.Count > 0)
            {
                CalculateSecondaryKey(tr, secKeysToAdd);
            }
        }
Пример #9
0
        public RelationInfo(uint id, string name, IRelationInfoResolver relationInfoResolver, Type interfaceType,
                            Type clientType, IInternalObjectDBTransaction tr)
        {
            _id   = id;
            _name = name;
            _relationInfoResolver     = relationInfoResolver;
            _interfaceType            = interfaceType;
            _clientType               = clientType;
            ClientRelationVersionInfo = CreateVersionInfoByReflection();
            LoadVersionInfos(tr.KeyValueDBTransaction);
            ApartFields = FindApartFields(interfaceType, ClientRelationVersionInfo);
            if (LastPersistedVersion > 0 && RelationVersionInfo.Equal(_relationVersions[LastPersistedVersion], ClientRelationVersionInfo))
            {
                _relationVersions[LastPersistedVersion] = ClientRelationVersionInfo;
                ClientTypeVersion = LastPersistedVersion;
            }
            else
            {
                ClientTypeVersion = LastPersistedVersion + 1;
                _relationVersions.Add(ClientTypeVersion, ClientRelationVersionInfo);
                var writerk = new ByteBufferWriter();
                writerk.WriteByteArrayRaw(ObjectDB.RelationVersionsPrefix);
                writerk.WriteVUInt32(_id);
                writerk.WriteVUInt32(ClientTypeVersion);
                var writerv = new ByteBufferWriter();
                ClientRelationVersionInfo.Save(writerv);
                tr.KeyValueDBTransaction.SetKeyPrefix(ByteBuffer.NewEmpty());
                tr.KeyValueDBTransaction.CreateOrUpdateKeyValue(writerk.Data, writerv.Data);

                if (LastPersistedVersion > 0)
                {
                    CheckThatPrimaryKeyHasNotChanged(name, ClientRelationVersionInfo, _relationVersions[LastPersistedVersion]);
                    UpdateSecondaryKeys(tr, ClientRelationVersionInfo, _relationVersions[LastPersistedVersion]);
                }
            }
            _typeConvertorGenerator = tr.Owner.TypeConvertorGenerator;
        }
Пример #10
0
 static bool AllKeyPrefixesAreSame(RelationVersionInfo relationInfo, ushort count)
 {
     foreach (var sk in relationInfo.SecondaryKeys)
     {
         var skFields = sk.Value;
         var idx      = 0;
         foreach (var field in skFields.Fields)
         {
             if (!field.IsFromPrimaryKey)
             {
                 return(false);
             }
             if (field.Index != idx)
             {
                 return(false);
             }
             if (++idx == count)
             {
                 break;
             }
         }
     }
     return(true);
 }