Пример #1
0
        /// <summary>
        /// Constructor
        /// </summary>
        internal QueryEngine(QueryPlan <T> queryPlan)
        {
            this.table             = queryPlan.Table;
            this.queryPlan         = queryPlan;
            this.paralellism       = table.DbContext.Configuration.QueryParallelism;
            this.filterExpressions = queryPlan.Query.FlexFilters;
            this.sorting           = queryPlan.Query.Sorting;
            this.indexFilters      = queryPlan.Query.IndexFilters;
            this.limit             = this.queryPlan.Query.QueryLimit;
            var bookmark = this.queryPlan.Query.Bookmark;

            if (this.table.DbContext.Configuration.DatabasePath != null)
            {
                pathPrefix = Path.Join(
                    this.table.DbContext.Configuration.DatabasePath,
                    table.Annotation.Name, queryPlan.BestIndex.Name
                    );
            }
            else
            {
                pathPrefix = Path.Join(
                    "var", "data",
                    table.Annotation.Name, queryPlan.BestIndex.Name
                    );
            }

            /*
             *  Check if the bookmark contains a fragment for this engine.
             */
            if (bookmark != null)
            {
                this.bookmarkFragment = null;

                foreach (var fragment in bookmark.Fragments)
                {
                    if (fragment.TableName == this.table.Annotation.Name &&
                        fragment.IndexName == this.queryPlan.BestIndex.Name)
                    {
                        this.bookmarkFragment = fragment;
                        break;
                    }
                }

                if (this.bookmarkFragment == null)
                {
                    throw new FatCatException($"Invalid bookmark. Please always use the bookmarks in the same "
                                              + "queries they were created for. (2)");
                }
            }
        }
Пример #2
0
            internal PacketLoaderTask(Packet <T> packet, QueryPlan <T> queryPlan, bool isAsync)
            {
                this.Packet    = packet;
                this.queryPlan = queryPlan;
                this.isAsync   = isAsync;

                if (isAsync)
                {
                    this.task = WorkerAsync();
                }
                else
                {
                    ThreadPool.QueueUserWorkItem(this.WorkerCallback);
                }
            }
Пример #3
0
        /// <summary>
        /// Decompress the raw data and desirialize the records.
        /// </summary>
        /// <param name="queryPlan">Optional for queries. Filters the recrods if passed.</param>
        internal void DeserializeDecompress(QueryPlan <T> queryPlan = null)
        {
            if (rawCompressedData == null)
            {
                return;
            }

            List <string>  header     = null;
            TsvMapping <T> tsvMapping = null;

            using var ms   = new MemoryStream(rawCompressedData);
            using var gzip = new GZipStream(ms, CompressionMode.Decompress);
            using var tsv  = new TsvReader(gzip);
            int            lineCount      = 0;
            Nullable <int> tsvColumnIndex = null;
            bool           isFirstLine    = true;
            bool           notMatching    = false;

            while (!tsv.EndOfStream)
            {
                var line = tsv.ReadLine();

                if (isFirstLine)
                {
                    // Use its own header for compatibility.
                    header      = line;
                    isFirstLine = false;
                    tsvMapping  = new TsvMapping <T>(table, header);
                    continue;
                }

                if (header.Count != line.Count)
                {
                    throw new Exception($"Header length and column count mismatch in file '{FullPath}' at line {lineCount + 1}.");
                }

                /*
                 *  Filtering by 'Where' expressions
                 */
                if (queryPlan != null)
                {
                    notMatching = false;

                    foreach (var filter in queryPlan.FreeIndexFilters)
                    {
                        tsvColumnIndex = tsvMapping.FromRecordToTsv[filter.Key];

                        if (tsvColumnIndex == null || line[(int)tsvColumnIndex] != filter.Value)
                        {
                            notMatching = true;
                            break;
                        }
                    }

                    if (notMatching)
                    {
                        continue;
                    }
                }

                var record = new T();
                table.LoadFromTSVLine(tsvMapping, record, line);

                /*
                 *  Filtering by flex expressions
                 */
                if (queryPlan != null)
                {
                    notMatching = false;

                    foreach (var exp in queryPlan.Query.FlexFilters)
                    {
                        if (!exp(record))
                        {
                            notMatching = true;
                            break;
                        }
                    }

                    if (notMatching)
                    {
                        continue;
                    }
                }

                string unique = table.GetUnique(record);
                this.data[unique] = record;
                this.lines.Add(record);

                lineCount++;
            }

            /*
             *  Sort records inside the packet
             */
            if (queryPlan != null)
            {
                if (queryPlan.FreeSorting.Count > 0)
                {
                    var props = table.Properties.ToArray();

                    this.lines.Sort((x, y) => {
                        foreach (var directive in queryPlan.FreeSorting)
                        {
                            int dir    = directive.Item2 == SortingDirection.Ascending ? 1 : -1;
                            var valueX = props[directive.Item1].GetValue(x);
                            var valueY = props[directive.Item1].GetValue(y);

                            if (valueX == null && valueY == null)
                            {
                                continue;
                            }

                            if (valueX == null)
                            {
                                return(-dir);
                            }

                            if (valueY == null)
                            {
                                return(dir);
                            }

                            return(((IComparable)valueX).CompareTo((IComparable)valueY) * dir);
                        }

                        return(0);
                    });
                }
            }
        }
Пример #4
0
        /// <summary>
        /// Returns a user-friendly text that describes the query plan.
        /// </summary>
        public string GetQueryPlan()
        {
            var plan = new QueryPlan <T>(this);

            return(plan.ToString());
        }
Пример #5
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="query">An object, specifying the query</param>
 public Cursor(Query <T> query)
 {
     this.table       = query.Table;
     this.queryPlan   = new QueryPlan <T>(query);
     this.queryEngine = new QueryEngine <T>(queryPlan);
 }