Exemple #1
0
        public override IEnumerable <KeyValuePair <K, int> > CompareNonIndexedKeyWithKey <K, T>(
            DbColumn key, DbColumn column, TokenType comparer, T value)
        {
            if (column.Indexed || column.Table.Multikey)
            {
                throw new ArgumentException($"Column {column} must be un-indexed, and belong to a One-Key table");
            }

            //get the key column, index
            var keyColumn      = column.Table.Key;
            int keyColumnIndex = column.Index;
            K   keyValue       = default(K);

            var keyCount = 0;

            //read indexer offsets in their order
            using (var keyReader =
                       new io.BinaryReader(
                           io.File.OpenRead($"{key.Table.Database.BinaryPath}\\{key.Hash}.offset")))
            {
                //amount of keys
                keyCount = keyReader.ReadInt32();

                var count        = Table.Count;
                var initialCount = column.Index;

                var buffer   = new byte[sizeof(UInt64)];
                var bytes    = Table.RowMaskLength;
                var mainMask = Table.RowMask;

                int columnIndex = 0;
                int columnSize  = 0;

                int   bytesToSkip = 0;
                ulong bitMask     = 0;
                ulong recordMask  = 0;

                void SKIP(int cnt)
                {
                    while (cnt-- > 0)
                    {
                        if ((recordMask & bitMask) == 0)
                        {
                            if (columnIndex == keyColumnIndex)
                            {
                                //read Key value into: keyValue
                                keyValue = GetColumnValue <K>();
                            }
                            else
                            {
                                //SKIP
                                //not null value, add according to column type
                                if (columnSize == 0)
                                {
                                    throw new ArgumentException("unsupported type size");
                                }
                                else if (columnSize > 0)
                                {
                                    bytesToSkip += columnSize;
                                }
                                else
                                {
                                    //string, read length, and add chars
                                    reader.BaseStream.Position += bytesToSkip;

                                    //read new bytes to skip
                                    bytesToSkip = reader.ReadByte();
                                }
                            }
                        }
                        bitMask  >>= 1;
                        columnSize = ColumnTypeSizes[++columnIndex];
                    }
                    //position reader
                    if (bytesToSkip > 0)
                    {
                        reader.BaseStream.Position += bytesToSkip;
                    }
                }

                C GetColumnValue <C>()
                {
                    //for string, read length byte
                    var size = (columnSize < 0) ? reader.ReadByte() : columnSize;
                    //create buffer
                    var columnBuffer = new byte[size];

                    //read it
                    reader.Read(columnBuffer, 0, size);
                    //convert it to generic value
                    return(columnBuffer.BitConvertTo <C>());
                }

                for (var ndx = 0; ndx < keyCount; ndx++)
                {
                    var offset = keyReader.ReadInt32();
                    //point to record offset
                    reader.BaseStream.Position = offset;

                    //copy main mask
                    bitMask = mainMask;

                    //read record mask
                    reader.Read(buffer, 0, bytes);
                    recordMask = BitConverter.ToUInt64(buffer, 0);

                    //developer only
                    var binary = Convert.ToString((long)recordMask, 2);

                    //
                    columnSize  = ColumnTypeSizes[columnIndex = 0];
                    bytesToSkip = 0;

                    //skip initial columns if any
                    if (initialCount > 0)
                    {
                        SKIP(initialCount);
                    }

                    //read column value to compare
                    var columnValue = GetColumnValue <T>();

                    if (comparer.Compare <T>(columnValue, value))
                    {
                        if (keyColumnIndex > columnIndex)
                        {
                            //key not read yet
                            SKIP(keyColumnIndex - columnIndex - 1);

                            //read Key value into: keyValue
                            keyValue = GetColumnValue <K>();
                        }

                        yield return(new KeyValuePair <K, int>(keyValue, offset));
                    }
                }
            }
        }
Exemple #2
0
        /// <summary>
        /// Expensive non-indexed column comparison by a constant value
        /// </summary>
        /// <typeparam name="T">type of column</typeparam>
        /// <param name="key">table key</param>
        /// <param name="column">column to compare</param>
        /// <param name="comparer">comparison operator</param>
        /// <param name="value">constant value</param>
        /// <returns></returns>
        public override IEnumerable <int> CompareNonIndexedKey <T>(
            DbColumn key, DbColumn column, TokenType comparer, T value)
        {
            //THIS CANNOT BE TOGETHER WITH CompareNonIndexedKeyWithKey BECAUSE
            // RETURNING KEY MAKE AN EXTRA LOAD

            var keyCount = 0;

            //read indexer offsets in their order
            using (var keyReader =
                       new io.BinaryReader(
                           io.File.OpenRead($"{key.Table.Database.BinaryPath}\\{key.Hash}.offset")))
            {
                keyCount = keyReader.ReadInt32();

                var count        = Table.Count;
                var initialCount = column.Index;

                var buffer   = new byte[sizeof(UInt64)];
                var bytes    = Table.RowMaskLength;
                var mainMask = Table.RowMask;

                int   columnIndex = 0;
                int   columnSize  = 0;
                int   bytesToSkip = 0;
                ulong bitMask     = 0;
                ulong recordMask  = 0;

                //build column type translator
                var columnTypeSizes = Table.ColumnTypes.Select(t => t.GetSize()).ToArray();

                void SKIP(int cnt)
                {
                    while (cnt-- > 0)
                    {
                        if ((recordMask & bitMask) == 0)
                        {
                            //not null value, add according to column type
                            var size = columnTypeSizes[columnIndex];
                            if (size == 0)
                            {
                                throw new ArgumentException("unsupported type size");
                            }
                            else if (size > 0)
                            {
                                bytesToSkip += size;
                            }
                            else
                            {
                                //string, read length, and add chars
                                reader.BaseStream.Position += bytesToSkip;


                                //read new bytes to skip
                                bytesToSkip = reader.ReadByte();
                            }
                        }
                        bitMask  >>= 1;
                        columnSize = ColumnTypeSizes[++columnIndex];
                    }
                    //position reader
                    if (bytesToSkip > 0)
                    {
                        reader.BaseStream.Position += bytesToSkip;
                    }
                }

                T GetColumnValue <T>()
                {
                    //for string, read length byte
                    var size = (columnSize < 0) ? reader.ReadByte() : columnSize;
                    //create buffer
                    var columnBuffer = new byte[size];

                    //read it
                    reader.Read(columnBuffer, 0, size);
                    //convert it to generic value
                    return(columnBuffer.BitConvertTo <T>());
                }

                for (var ndx = 0; ndx < keyCount; ndx++)
                {
                    var offset = keyReader.ReadInt32();
                    //point to record offset
                    reader.BaseStream.Position = offset;

                    //copy main mask
                    bitMask = mainMask;

                    //read record mask
                    reader.Read(buffer, 0, bytes);
                    recordMask = BitConverter.ToUInt64(buffer, 0);

                    //developer only
                    var binary = Convert.ToString((long)recordMask, 2);

                    columnSize  = ColumnTypeSizes[columnIndex = 0];
                    bytesToSkip = 0;

                    //skip initial columns if any
                    if (initialCount > 0)
                    {
                        SKIP(initialCount);
                    }

                    //read column value to compare
                    var columnValue = GetColumnValue <T>();

                    //compare
                    if (comparer.Compare <T>(columnValue, value))
                    {
                        yield return(offset);
                    }
                }
            }
        }