public IXTable ReadSource(string tableName, XDatabaseContext context)
        {
            List <IXTable> sources = new List <IXTable>();

            // Find the latest source of this type
            ItemVersions sourceVersions   = context.StreamProvider.ItemVersions(LocationType.Source, tableName);
            ItemVersion  latestFullSource = sourceVersions.LatestBeforeCutoff(CrawlType.Full, context.RequestedAsOfDateTime);

            // If there are no sources, there's nothing to rebuild from
            if (sourceVersions.Versions == null || sourceVersions.Versions.Count == 0)
            {
                return(null);
            }

            // Find the latest already converted table
            ItemVersions tableVersions    = context.StreamProvider.ItemVersions(LocationType.Table, tableName);
            ItemVersion  latestBuiltTable = tableVersions.LatestBeforeCutoff(CrawlType.Full, context.RequestedAsOfDateTime);

            // If no source or table was found, throw
            if (latestFullSource == null && latestBuiltTable == null)
            {
                throw new UsageException(tableName, "[Table]", context.StreamProvider.SourceNames());
            }

            // Read the Table or the Full Crawl Source, whichever is newer
            DateTime incrementalNeededAfterCutoff;

            if (latestBuiltTable != null &&
                (latestFullSource == null || !IsOutOfDate(latestBuiltTable.AsOfDate, latestFullSource.AsOfDate)) &&
                TableMetadataSerializer.UncachedExists(context.StreamProvider, latestBuiltTable.Path))
            {
                // If the table is current, reuse it
                sources.Add(BinaryTableReader.Build(context.StreamProvider, latestBuiltTable.Path));
                incrementalNeededAfterCutoff = latestBuiltTable.AsOfDate;
            }
            else
            {
                // Otherwise, build a new table from the latest source full crawl
                sources.AddRange(context.StreamProvider.Enumerate(latestFullSource.Path, EnumerateTypes.File, true).Select((sa) => new TabularFileReader(context.StreamProvider, sa.Path)));
                incrementalNeededAfterCutoff = latestFullSource.AsOfDate;
            }

            // Add incremental crawls between the full source and the reporting date
            DateTime latestComponent = incrementalNeededAfterCutoff;

            foreach (ItemVersion incrementalCrawl in sourceVersions.VersionsInRange(CrawlType.Inc, incrementalNeededAfterCutoff, context.RequestedAsOfDateTime))
            {
                sources.AddRange(context.StreamProvider.Enumerate(incrementalCrawl.Path, EnumerateTypes.File, true).Select((sa) => new TabularFileReader(context.StreamProvider, sa.Path)));
                latestComponent = latestComponent.BiggestOf(incrementalCrawl.AsOfDate);
            }

            // Report the latest incorporated source back
            context.NewestDependency = latestComponent;

            // Return the source (if a single) or concatenated group (if multiple parts)
            return(ConcatenatedTable.Build(sources));
        }
Beispiel #2
0
        public IXTable Build(IXTable source, XDatabaseContext context)
        {
            if (source != null)
            {
                throw new ArgumentException($"'read' must be the first stage in a pipeline.");
            }

            List <IXTable> sources = new List <IXTable>();

            // Identify the interval and table name requested
            TimeSpan interval = context.Parser.NextTimeSpan();

            if (interval < TimeSpan.Zero)
            {
                throw new ArgumentException($"'interval' must be positive. (For last 7 days, use '7d')");
            }
            string tableName = (string)context.Parser.NextLiteralValue();

            // Determine the range of versions to include (from the as of date or now if not provided)
            DateTime rangeEnd   = (context.RequestedAsOfDateTime == DateTime.MaxValue ? DateTime.UtcNow : context.RequestedAsOfDateTime);
            DateTime rangeStart = rangeEnd.Subtract(interval);

            // Find versions available
            ItemVersions versions = context.StreamProvider.ItemVersions(LocationType.Source, tableName);

            if (versions.Versions.Count == 0)
            {
                versions = context.StreamProvider.ItemVersions(LocationType.Table, tableName);
            }
            if (versions.Versions.Count == 0)
            {
                throw new ArgumentException($"'{tableName}' was not found as a Source or Table.");
            }

            // Find the first version to include (if any) - the last full version before the start was 'current' at the start moment
            ItemVersion previous = versions.LatestBeforeCutoff(CrawlType.Full, rangeStart);

            XDatabaseContext historicalContext;

            foreach (ItemVersion version in versions.VersionsInRange(CrawlType.Full, rangeStart, rangeEnd))
            {
                // Add the version before this one, if any (including any incremental pieces)
                if (previous != null)
                {
                    historicalContext = new XDatabaseContext(context);
                    historicalContext.RequestedAsOfDateTime = version.AsOfDate.AddSeconds(-1);
                    sources.Add(context.Runner.Build(tableName, historicalContext));
                }

                previous = version;
            }

            // Add 'last' up to the requested moment
            historicalContext = new XDatabaseContext(context);
            historicalContext.RequestedAsOfDateTime = rangeEnd;
            sources.Add(context.Runner.Build(tableName, historicalContext));

            // Communicate the latest component as of date back to the builder
            historicalContext.Pop(context);

            // Return the source(s) found
            return(ConcatenatedTable.Build(sources));
        }