protected async override Task<bool> HandleDirtyTable()
        {
            if (this.Query.Filter != null || !this.force)
            {
                throw new InvalidOperationException("The table cannot be purged because it has pending operations.");
            }

            var delOperationsQuery = new MobileServiceTableQueryDescription(MobileServiceLocalSystemTables.OperationQueue);
            delOperationsQuery.Filter = new BinaryOperatorNode(BinaryOperatorKind.Equal, new MemberAccessNode(null, "tableName"), new ConstantNode(this.Table.TableName));

            // count ops to be deleted
            delOperationsQuery.IncludeTotalCount = true;
            delOperationsQuery.Top = 0;
            long toRemove = QueryResult.Parse(await this.Store.ReadAsync(delOperationsQuery), null, validate: false).TotalCount;

            // delete operations
            delOperationsQuery.Top = null;
            await this.Store.DeleteAsync(delOperationsQuery);

            // delete errors
            var delErrorsQuery = new MobileServiceTableQueryDescription(MobileServiceLocalSystemTables.SyncErrors);
            delErrorsQuery.Filter = delOperationsQuery.Filter;
            await this.Store.DeleteAsync(delErrorsQuery);

            // update queue operation count
            this.OperationQueue.UpdateOperationCount(-toRemove);

            return true;
        }
        public Task<JToken> ReadAsync(MobileServiceTableQueryDescription query)
        {
            if (query.TableName == MobileServiceLocalSystemTables.OperationQueue || query.TableName == MobileServiceLocalSystemTables.SyncErrors)
            {
                MockTable table = GetTable(query.TableName);

                IEnumerable<JObject> items = table.Values;
                if (query.TableName == MobileServiceLocalSystemTables.OperationQueue)
                {
                    string odata = query.ToODataString();
                    if (odata.Contains("$orderby=sequence desc")) // the query to take total count and max sequence
                    {
                        items = items.OrderBy(o => o.Value<long>("sequence"));
                    }
                    else if (odata.StartsWith("$filter=((tableKind eq ") && odata.Contains("(sequence gt "))
                    {
                        var sequenceCompareNode = ((BinaryOperatorNode)query.Filter).RightOperand as BinaryOperatorNode;

                        items = items.Where(o => o.Value<long>("sequence") > (long)((ConstantNode)sequenceCompareNode.RightOperand).Value);
                        items = items.OrderBy(o => o.Value<long>("sequence"));
                    }
                    else if (odata.Contains("(sequence gt ")) // the query to get next operation
                    {
                        items = items.Where(o => o.Value<long>("sequence") > (long)((ConstantNode)((BinaryOperatorNode)query.Filter).RightOperand).Value);
                        items = items.OrderBy(o => o.Value<long>("sequence"));
                    }
                    else if (odata.Contains(") and (itemId eq '")) // the query to retrive operation by item id
                    {
                        string targetTable = ((ConstantNode)((BinaryOperatorNode)((BinaryOperatorNode)query.Filter).LeftOperand).RightOperand).Value.ToString();
                        string targetId = ((ConstantNode)((BinaryOperatorNode)((BinaryOperatorNode)query.Filter).RightOperand).RightOperand).Value.ToString();
                        items = items.Where(o => o.Value<string>("itemId") == targetId && o.Value<string>("tableName") == targetTable);
                    }
                    else if (odata.Contains("$filter=(tableName eq '"))
                    {
                        items = items.Where(o => o.Value<string>("tableName") == ((ConstantNode)((BinaryOperatorNode)query.Filter).RightOperand).Value.ToString());
                    }
                }

                if (query.IncludeTotalCount)
                {
                    return Task.FromResult<JToken>(new JObject() { { "count", items.Count() }, { "results", new JArray(items) } });
                }

                return Task.FromResult<JToken>(new JArray(items));
            }

            this.ReadQueries.Add(query);
            JToken response;

            if (ReadAsyncFunc != null)
            {
                response = ReadAsyncFunc(query);
            }
            else
            {
                response = JToken.Parse(ReadResponses.Dequeue());
            }

            return Task.FromResult(response);
        }
        private async Task Delete(MobileServiceTableQueryDescription query)
        {
            await this.store.DeleteAsync(query);

            OperationsInfo operationsInfo = this.operationsInfo.Value;
            Interlocked.Decrement(ref operationsInfo.Count);
        }
        public async Task DoesNotUpsertAnObject_IfItDoesNotHaveAnId()
        {
            var query = new MobileServiceTableQueryDescription("test");
            var action = new PullAction(this.table.Object, MobileServiceTableKind.Table, this.context.Object, null, query, null, null, this.opQueue.Object, this.settings.Object, this.store.Object, MobileServiceRemoteTableOptions.All, null, CancellationToken.None);

            var itemWithId = new JObject() { { "id", "abc" }, { "text", "has id" } };
            var itemWithoutId = new JObject() { { "text", "no id" } };
            var result = new JArray(new[]{
                itemWithId,
                itemWithoutId
            });
            this.opQueue.Setup(q => q.LockTableAsync(It.IsAny<string>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult<IDisposable>(null));
            this.opQueue.Setup(q => q.CountPending(It.IsAny<string>())).Returns(Task.FromResult(0L));
            this.table.SetupSequence(t => t.ReadAsync(It.IsAny<string>(), It.IsAny<IDictionary<string, string>>(), It.IsAny<MobileServiceFeatures>()))
                      .Returns(Task.FromResult(QueryResult.Parse(result, null, false)))
                      .Returns(Task.FromResult(QueryResult.Parse(new JArray(), null, false)));
            this.store.Setup(s => s.UpsertAsync("test", It.IsAny<IEnumerable<JObject>>(), true))
                      .Returns(Task.FromResult(0))
                      .Callback<string, IEnumerable<JObject>, bool>((tableName, items, fromServer) =>
                        {
                            Assert.AreEqual(1, items.Count());
                            Assert.AreEqual(itemWithId, items.First());
                        });

            await action.ExecuteAsync();

            store.VerifyAll();
            opQueue.VerifyAll();
            table.VerifyAll();

            store.Verify(s => s.DeleteAsync("test", It.IsAny<IEnumerable<string>>()), Times.Never(), "There shouldn't be any call to delete");
        }
Beispiel #5
0
        /// <summary>
        /// Execute a query and return its results.
        /// </summary>
        /// <typeparam name="T">
        /// The type of element returned by the query.
        /// </typeparam>
        /// <param name="query">
        /// The query to evaluate and get the results for.
        /// </param>
        /// <returns>
        /// Results of the query.
        /// </returns>
        internal async Task <IEnumerable <T> > Execute <T>(IMobileServiceTableQuery <T> query)
        {
            // Compile the query from the underlying IQueryable's expression
            // tree
            MobileServiceTableQueryDescription compiledQuery = this.Compile(query);

            // Send the query
            string      odata  = compiledQuery.ToODataString();
            QueryResult result = await this.Execute <T>(query, odata);

            return(new QueryResultEnumerable <T>(
                       result.TotalCount,
                       result.NextLink,
                       query.Table.MobileServiceClient.Serializer.Deserialize(result.Values, compiledQuery.ProjectionArgumentType).Select(
                           value =>
            {
                // Apply the projection to the instance transforming it
                // as desired
                foreach (Delegate projection in compiledQuery.Projections)
                {
                    value = projection.DynamicInvoke(value);
                }

                return (T)value;
            })));
        }
        /// <summary>
        /// Counts all the items returned from the query
        /// </summary>
        /// <param name="store">An instance of <see cref="IMobileServiceLocalStore"/></param>
        /// <param name="query">An instance of <see cref="MobileServiceTableQueryDescription"/></param>
        /// <returns>Task that will complete with count of items.</returns>
        public static async Task<long> CountAsync(this IMobileServiceLocalStore store, MobileServiceTableQueryDescription query)
        {
            query.Top = 0;
            query.IncludeTotalCount = true;

            QueryResult result = await store.QueryAsync(query);
            return result.TotalCount;
        }
 public PullStrategy(MobileServiceTableQueryDescription query,
                     PullCursor cursor,
                     MobileServiceRemoteTableOptions options)
 {
     this.Query = query;
     this.Cursor = cursor;
     this.SupportsSkip = options.HasFlag(MobileServiceRemoteTableOptions.Skip);
     this.SupportsTop = options.HasFlag(MobileServiceRemoteTableOptions.Top);
 }
Beispiel #8
0
        /// <summary>
        /// Compile the query into a MobileServiceTableQueryDescription.
        /// </summary>
        /// <returns>
        /// The compiled OData query.
        /// </returns>
        internal MobileServiceTableQueryDescription Compile <T>(IMobileServiceTableQuery <T> query)
        {
            // Compile the query from the underlying IQueryable's expression
            // tree
            MobileServiceTableQueryTranslator <T> translator    = new MobileServiceTableQueryTranslator <T>(query);
            MobileServiceTableQueryDescription    compiledQuery = translator.Translate();

            return(compiledQuery);
        }
Beispiel #9
0
        /// <summary>
        /// Initializes a new instance of the MobileServiceTableQueryTranslator
        /// class.
        /// </summary>
        /// <param name="query">
        /// The <see cref="T:MobileServiceTableQuery`1{T}"/> which
        /// is being translated.
        /// </param>
        internal MobileServiceTableQueryTranslator(IMobileServiceTableQuery <T> query)
        {
            Arguments.IsNotNull(query, nameof(query));

            this.query            = query;
            this.queryDescription = new MobileServiceTableQueryDescription(query.Table.TableName)
            {
                IncludeTotalCount = query.RequestTotalCount,
            };
        }
        /// <summary>
        /// Initializes a new instance of the MobileServiceTableQueryTranslator
        /// class.
        /// </summary>
        /// <param name="query">
        /// The <see cref="T:MobileServiceTableQuery`1{T}"/> which
        /// is being translated.
        /// </param>
        internal MobileServiceTableQueryTranslator(IMobileServiceTableQuery <T> query)
        {
            Debug.Assert(query != null);

            this.query = query;

            this.queryDescription = new MobileServiceTableQueryDescription(query.Table.TableName)
            {
                IncludeTotalCount = query.RequestTotalCount,
            };
        }
        private OperationsInfo LoadOperationsInformation()
        {
            var query = new MobileServiceTableQueryDescription(FileOperationTableName);
            query.IncludeTotalCount = true;
            query.Top = 1;

            // Get the last item in the queue
            query.Ordering.Add(new OrderByNode(new MemberAccessNode(null, "sequence"), OrderByDirection.Descending));

            JToken result = this.store.ReadAsync(query).Result;

            return new OperationsInfo(result.Value<int>(CountPropertyName), result.Value<int>("sequence"));
        }
        public async Task SavesTheMaxUpdatedAt_IfQueryIdIsSpecified_WithoutFilter()
        {
            var query = new MobileServiceTableQueryDescription("test");

            var result = new JArray(new[]
            {
                new JObject() { { "id", "abc" }, { "text", "has id"}, { "__updatedAt", "1985-07-17" } },
                new JObject() { { "id", "abc" }, { "text", "has id"}, { "__updatedAt", "2014-07-09" } }
            });
            string firstQuery = "$filter=(__updatedAt ge datetimeoffset'2013-01-01T00%3A00%3A00.0000000%2B00%3A00')&$orderby=__updatedAt&$skip=0&$top=50";
            string secondQuery = "$filter=(__updatedAt ge datetimeoffset'2014-07-09T07%3A00%3A00.0000000%2B00%3A00')&$orderby=__updatedAt&$skip=0&$top=50";
            await TestIncrementalSync(query, result, new DateTime(2014, 07, 09), savesMax: true, firstQuery: firstQuery, secondQuery: secondQuery);
        }
 public PurgeAction(MobileServiceTable table,
                    MobileServiceTableKind tableKind,
                    string queryId,
                    MobileServiceTableQueryDescription query,
                    bool force,
                    MobileServiceSyncContext context,
                    OperationQueue operationQueue,
                    MobileServiceSyncSettingsManager settings,
                    IMobileServiceLocalStore store,
                    CancellationToken cancellationToken)
     : base(table, tableKind, queryId, query, null, context, operationQueue, settings, store, cancellationToken)
 {
     this.force = force;
 }
 public IncrementalPullStrategy(MobileServiceTable table,
                                MobileServiceTableQueryDescription query,
                                string queryId,
                                MobileServiceSyncSettingsManager settings,
                                PullCursor cursor,
                                MobileServiceRemoteTableOptions options)
     : base(query, cursor, options)
 {
     this.table = table;
     this.originalFilter = query.Filter;
     this.queryId = queryId;
     this.settings = settings;
     this.ordered = options.HasFlag(MobileServiceRemoteTableOptions.OrderBy);
 }
Beispiel #15
0
        /// <summary>
        /// Creates a copy of <see cref="MobileServiceTableQueryDescription"/>
        /// </summary>
        /// <returns>The cloned query</returns>
        public MobileServiceTableQueryDescription Clone()
        {
            var clone = new MobileServiceTableQueryDescription(this.TableName);

            clone.Filter                 = this.Filter;
            clone.Selection              = this.Selection.ToList();
            clone.Ordering               = this.Ordering.ToList();
            clone.Projections            = this.Projections.ToList();
            clone.ProjectionArgumentType = this.ProjectionArgumentType;
            clone.Skip = this.Skip;
            clone.Top  = this.Top;
            clone.IncludeTotalCount = this.IncludeTotalCount;

            return(clone);
        }
        private async Task<IMobileServiceFileOperation> GetNextOperationItemAsync(bool deleteItem)
        {
            var query = new MobileServiceTableQueryDescription(FileOperationTableName);
            query.Ordering.Add(new OrderByNode(new MemberAccessNode(null, "sequence"), OrderByDirection.Ascending));
            query.Top = 1;

            JToken result = await this.store.ReadAsync(query);
            FileOperationItem operationItem = result.ToObject<List<FileOperationItem>>().FirstOrDefault();

            if (deleteItem)
            {
                await Delete(query);
            }

            return operationItem != null ? operationItem.ToOperation() : null;
        }
 public TableAction(MobileServiceTable table,
                    MobileServiceTableKind tableKind,
                    string queryId,
                    MobileServiceTableQueryDescription query,
                    IEnumerable<string> relatedTables,
                    MobileServiceSyncContext context,
                    OperationQueue operationQueue,
                    MobileServiceSyncSettingsManager settings,
                    IMobileServiceLocalStore store,
                    CancellationToken cancellationToken)
     : base(operationQueue, store, cancellationToken)
 {
     this.Table = table;
     this.TableKind = tableKind;
     this.QueryId = queryId;
     this.Query = query;
     this.RelatedTables = relatedTables;
     this.Settings = settings;
     this.Context = context;
 }
 public PullAction(MobileServiceTable table,
                   MobileServiceTableKind tableKind,
                   MobileServiceSyncContext context,
                   string queryId,
                   MobileServiceTableQueryDescription query,
                   IDictionary<string, string> parameters,
                   IEnumerable<string> relatedTables,
                   OperationQueue operationQueue,
                   MobileServiceSyncSettingsManager settings,
                   IMobileServiceLocalStore store,
                   MobileServiceRemoteTableOptions options,
                   MobileServiceObjectReader reader,
                   CancellationToken cancellationToken)
     : base(table, tableKind, queryId, query, relatedTables, context, operationQueue, settings, store, cancellationToken)
 {
     this.options = options;
     this.parameters = parameters;
     this.cursor = new PullCursor(query);
     this.Reader = reader ?? new MobileServiceObjectReader();
 }
        public async Task RemoveAsync(string id)
        {
            var query = new MobileServiceTableQueryDescription(FileOperationTableName);
            query.Filter = new BinaryOperatorNode(BinaryOperatorKind.Equal, new MemberAccessNode(null, MobileServiceSystemColumns.Id), new ConstantNode(id));
            query.Top = 1;

            await Delete(query);
        }
        public async Task DeleteAsync_WithQuery_SendsNotification()
        {
            var store = new MobileServiceLocalStoreMock();
            var trackingContext = new StoreTrackingContext(StoreOperationSource.Local, string.Empty);
            var eventManager = new MobileServiceEventManagerMock<IMobileServiceEvent>();
            var settings = new MobileServiceSyncSettingsManager(store);
            var changeTracker = new LocalStoreChangeTracker(store, trackingContext, eventManager, settings);

            JObject item = EnqueueSimpleObjectResponse(store);

            StoreOperationCompletedEvent operationEvent = null;
            eventManager.PublishAsyncFunc = t =>
            {
                operationEvent = t as StoreOperationCompletedEvent;
                return Task.FromResult(0);
            };

            MobileServiceTableQueryDescription query = new MobileServiceTableQueryDescription("test");
            query.Filter = new BinaryOperatorNode(BinaryOperatorKind.Equal, new MemberAccessNode(null, MobileServiceSystemColumns.Id), new ConstantNode("123"));

            await changeTracker.DeleteAsync(query);

            Assert.IsNotNull(operationEvent);
            Assert.AreEqual(operationEvent.Operation.Kind, LocalStoreOperationKind.Delete);
            Assert.AreEqual(operationEvent.Operation.RecordId, "123");
            Assert.AreEqual(operationEvent.Operation.TableName, "test");
        }
 /// <summary>
 /// Counts all the items in a local table
 /// </summary>
 /// <param name="store">Instance of <see cref="IMobileServiceLocalStore"/></param>
 /// <param name="tableName">Name of the table</param>
 /// <returns>Task that will complete with count of items.</returns>
 public async static Task<long> CountAsync(this IMobileServiceLocalStore store, string tableName)
 {
     var query = new MobileServiceTableQueryDescription(MobileServiceLocalSystemTables.OperationQueue);
     return await CountAsync(store, query);
 }
        public void ToODataString_EscapesThe_Uri()
        {

            //updatedat gt datetimeoffset'2014-04-04T07:00:00.0000000+00:00'
            var datetime1 = new ConstantNode(new DateTimeOffset(2014, 4, 4, 7, 0, 0, TimeSpan.FromHours(0)));
            var updatedAt = new MemberAccessNode(null, "updatedat");
            var gt1 = new BinaryOperatorNode(BinaryOperatorKind.GreaterThan, updatedAt, datetime1);

            // updatedat gt datetime'2014-04-04T07:0:0.000Z'
            var datetime2 = new ConstantNode(new DateTime(2014, 4, 4, 7, 0, 0, DateTimeKind.Utc));
            var someDate = new MemberAccessNode(null, "someDate");
            var gt2 = new BinaryOperatorNode(BinaryOperatorKind.GreaterThan, someDate, datetime2);

            // startswith(text,'this&''%%=,?#')
            var text = new MemberAccessNode(null, "text");
            var value = new ConstantNode("this&'%%=,?#");
            var startswith = new FunctionCallNode("startswith", new QueryNode[] { text, value });

            //updatedat gt datetimeoffset'2014-04-04T07:00:00.0000000+00:00' and startswith(text,'this&''%%=,?#')
            var and2 = new BinaryOperatorNode(BinaryOperatorKind.And, gt2, startswith);

            var and1 = new BinaryOperatorNode(BinaryOperatorKind.And, gt1, and2);

            var desc = new MobileServiceTableQueryDescription("someTable") { Filter = and1 };
            Assert.AreEqual(desc.ToODataString(), EscapedODataString);
        }
        public async Task UpsertAsync_ThenReadAsync_AllTypes()
        {
            TestUtilities.DropTestTable(TestDbName, TestTable);

            // first create a table called todo
            using (MobileServiceSQLiteStore store = new MobileServiceSQLiteStore(TestDbName))
            {
                store.DefineTable(TestTable, JObjectTypes.GetObjectWithAllTypes());

                await store.InitializeAsync();

                var upserted = new JObject()
                {
                    { "id", "xyz" },
                    { "Object", new JObject() { {"id", "abc"} }},
                    { "Array", new JArray() { new JObject(){{"id", 3}} } },
                    { "Integer", 123L },
                    { "Float", 12.5m },
                    { "String", "def" },
                    { "Boolean", true },
                    { "Date", new DateTime(2003, 5, 6, 4, 5, 1, DateTimeKind.Utc) },
                    { "Bytes", new byte[] { 1, 2, 3} },
                    { "Guid", new Guid("AB3EB1AB-53CD-4780-928B-A7E1CB7A927C") },
                    { "TimeSpan", new TimeSpan(1234) }
                };
                await store.UpsertAsync(TestTable, new[] { upserted }, false);

                var query = new MobileServiceTableQueryDescription(TestTable);
                var items = await store.ReadAsync(query) as JArray;
                Assert.IsNotNull(items);
                Assert.AreEqual(items.Count, 1);

                var lookedup = items.First as JObject;
                Assert.AreEqual(upserted.ToString(Formatting.None), lookedup.ToString(Formatting.None));
            }
        }
        public async Task<IMobileServiceFileOperation> GetOperationByFileIdAsync(string fileId)
        {
            var query = new MobileServiceTableQueryDescription(FileOperationTableName);
            query.Filter = new BinaryOperatorNode(BinaryOperatorKind.Equal, new MemberAccessNode(null, "fileId"), new ConstantNode(fileId));
            query.Top = 1;

            JToken result = await this.store.ReadAsync(query);

            FileOperationItem operationItem = result.ToObject<List<FileOperationItem>>().FirstOrDefault();

            return operationItem != null ? operationItem.ToOperation() : null;
        }
 public async Task DoesNotSaveTheMaxUpdatedAt_IfThereAreNoResults()
 {
     var query = new MobileServiceTableQueryDescription("test");
     var result = new JArray();
     string expectedOdata = "$filter=(__updatedAt ge datetimeoffset'2013-01-01T00%3A00%3A00.0000000%2B00%3A00')&$orderby=__updatedAt&$skip=0&$top=50";
     await TestIncrementalSync(query, result, DateTime.MinValue, savesMax: false, firstQuery: expectedOdata, secondQuery: null);
 }
 public async Task DoesNotSaveTheMaxUpdatedAt_IfResultsDoNotHaveUpdatedAt()
 {
     var query = new MobileServiceTableQueryDescription("test");
     query.Filter = new BinaryOperatorNode(BinaryOperatorKind.Equal, new ConstantNode(4), new ConstantNode(3));
     var result = new JArray(new[]
     {
         new JObject() { { "id", "abc" }, { "text", "has id"} },
         new JObject() { { "id", "abc" }, { "text", "has id"} }
     });
     string firstQuery = "$filter=((4 eq 3) and (__updatedAt ge datetimeoffset'2013-01-01T00%3A00%3A00.0000000%2B00%3A00'))&$orderby=__updatedAt&$skip=0&$top=50";
     string secondQuery = "$filter=((4 eq 3) and (__updatedAt ge datetimeoffset'2013-01-01T00%3A00%3A00.0000000%2B00%3A00'))&$orderby=__updatedAt&$skip=2&$top=50";
     await TestIncrementalSync(query, result, new DateTime(2014, 07, 09), savesMax: false, firstQuery: firstQuery, secondQuery: secondQuery);
 }
Beispiel #27
0
        internal string ToODataString <T>(IMobileServiceTableQuery <T> query)
        {
            MobileServiceTableQueryDescription description = this.Compile(query);

            return(description.ToODataString());
        }
 public async Task SavesTheMaxUpdatedAt_IfQueryIdIsSpecified()
 {
     var query = new MobileServiceTableQueryDescription("test");
     query.Filter = new BinaryOperatorNode(BinaryOperatorKind.Equal, new ConstantNode(4), new ConstantNode(3));
     query.Ordering.Add(new OrderByNode(new MemberAccessNode(null, "text"), OrderByDirection.Descending));
     var result = new JArray(new[]
     {
         new JObject() { { "id", "abc" }, { "text", "has id"}, { "__updatedAt", "1985-07-17" } },
         new JObject() { { "id", "abc" }, { "text", "has id"}, { "__updatedAt", "2014-07-09" } }
     });
     string firstQuery = "$filter=((4 eq 3) and (__updatedAt ge datetimeoffset'2013-01-01T00%3A00%3A00.0000000%2B00%3A00'))&$orderby=__updatedAt&$skip=0&$top=50";
     string secondQuery = "$filter=((4 eq 3) and (__updatedAt ge datetimeoffset'2014-07-09T07%3A00%3A00.0000000%2B00%3A00'))&$orderby=__updatedAt&$skip=0&$top=50";
     await TestIncrementalSync(query, result, new DateTime(2014, 07, 09), savesMax: true, firstQuery: firstQuery, secondQuery: secondQuery);
 }
        /// <summary>
        /// Creates a copy of <see cref="MobileServiceTableQueryDescription"/>
        /// </summary>
        /// <returns>The cloned query</returns>
        public MobileServiceTableQueryDescription Clone()
        {
            var clone = new MobileServiceTableQueryDescription(this.TableName);

            clone.Filter = this.Filter;
            clone.Selection = this.Selection.ToList();
            clone.Ordering = this.Ordering.ToList();
            clone.Projections = this.Projections.ToList();
            clone.ProjectionArgumentType = this.ProjectionArgumentType;
            clone.Skip = this.Skip;
            clone.Top = this.Top;
            clone.IncludeTotalCount = this.IncludeTotalCount;

            return clone;
        }
Beispiel #30
0
        private static MobileServiceTableQueryDescription Parse(string tableName, string query, string uriPath)
        {
            bool includeTotalCount = false;
            int? top  = null;
            int? skip = null;

            string[]            selection = null;
            QueryNode           filter    = null;
            IList <OrderByNode> orderings = null;

            IDictionary <string, string> parameters = HttpUtility.ParseQueryString(query);

            foreach (KeyValuePair <string, string> parameter in parameters)
            {
                string key   = parameter.Key;
                string value = parameter.Value;
                if (String.IsNullOrEmpty(key))
                {
                    continue;
                }

                switch (key)
                {
                case ODataOptions.Filter:
                    filter = ODataExpressionParser.ParseFilter(value);
                    break;

                case ODataOptions.OrderBy:
                    orderings = ODataExpressionParser.ParseOrderBy(value);
                    break;

                case ODataOptions.Skip:
                    skip = Int32.Parse(value);
                    break;

                case ODataOptions.Top:
                    top = Int32.Parse(value);
                    break;

                case ODataOptions.Select:
                    selection = value.Split(',');
                    break;

                case ODataOptions.InlineCount:
                    includeTotalCount = "allpages".Equals(value);
                    break;

                default:
                    throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Unrecognized query parameter '{0}'.", key), "query");
                }
            }

            var description = new MobileServiceTableQueryDescription(tableName)
            {
                IncludeTotalCount = includeTotalCount,
                Skip = skip,
                Top  = top
            };

            description.UriPath = uriPath;
            if (selection != null)
            {
                ((List <string>)description.Selection).AddRange(selection);
            }
            if (orderings != null)
            {
                ((List <OrderByNode>)description.Ordering).AddRange(orderings);
            }
            description.Filter = filter;

            return(description);
        }
 private static MobileServiceTableQueryDescription CreateQuery()
 {
     var query = new MobileServiceTableQueryDescription(MobileServiceLocalSystemTables.OperationQueue);
     return query;
 }
        /// <summary>
        /// Deletes items from local table that match the given query.
        /// </summary>
        /// <param name="query">A query to find records to delete.</param>
        /// <returns>A task that completes when delete query has executed.</returns>
        public override Task DeleteAsync(MobileServiceTableQueryDescription query)
        {
            if (query == null)
            {
                throw new ArgumentNullException("query");
            }

            this.EnsureInitialized();

            var formatter = new SqlQueryFormatter(query);
            string sql = formatter.FormatDelete();

            return this.operationSemaphore.WaitAsync()
                .ContinueWith(t =>
                {
                    try
                    {
                        this.ExecuteNonQuery(sql, formatter.Parameters);
                    }
                    finally
                    {
                        this.operationSemaphore.Release();
                    }
                });
        }
        /// <summary>
        /// Reads data from local store by executing the query.
        /// </summary>
        /// <param name="query">The query to execute on local store.</param>
        /// <returns>A task that will return with results when the query finishes.</returns>
        public override Task<JToken> ReadAsync(MobileServiceTableQueryDescription query)
        {
            if (query == null)
            {
                throw new ArgumentNullException("query");
            }

            this.EnsureInitialized();

            var formatter = new SqlQueryFormatter(query);
            string sql = formatter.FormatSelect();

            return this.operationSemaphore.WaitAsync()
                .ContinueWith(t =>
                {
                    try
                    {
                        IList<JObject> rows = this.ExecuteQuery(query.TableName, sql, formatter.Parameters);
                        JToken result = new JArray(rows.ToArray());

                        if (query.IncludeTotalCount)
                        {
                            sql = formatter.FormatSelectCount();
                            IList<JObject> countRows = null;

                            countRows = this.ExecuteQuery(query.TableName, sql, formatter.Parameters);


                            long count = countRows[0].Value<long>("count");
                            result = new JObject() 
                            { 
                                { "results", result }, 
                                { "count", count } 
                            };
                        }

                        return result;
                    }
                    finally
                    {
                        this.operationSemaphore.Release();
                    }
                });
        }
 /// <summary>
 /// Executes the query on local store and returns the parsed result
 /// </summary>
 /// <param name="store">An instance of <see cref="IMobileServiceLocalStore"/></param>
 /// <param name="query">An instance of <see cref="MobileServiceTableQueryDescription"/></param>
 /// <returns>Task that will complete with the parsed result of the query.</returns>
 public static async Task<QueryResult> QueryAsync(this IMobileServiceLocalStore store, MobileServiceTableQueryDescription query)
 {
     return QueryResult.Parse(await store.ReadAsync(query), null, validate: true);
 }
        private async Task TestIncrementalSync(MobileServiceTableQueryDescription query, JArray result, DateTime maxUpdatedAt, bool savesMax, string firstQuery, string secondQuery)
        {
            var action = new PullAction(this.table.Object, MobileServiceTableKind.Table, this.context.Object, "latestItems", query, null, null, this.opQueue.Object, this.settings.Object, this.store.Object, MobileServiceRemoteTableOptions.All, null, CancellationToken.None);

            this.opQueue.Setup(q => q.LockTableAsync(It.IsAny<string>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult<IDisposable>(null));
            this.opQueue.Setup(q => q.CountPending(It.IsAny<string>())).Returns(Task.FromResult(0L));
            this.table.Setup(t => t.ReadAsync(firstQuery, It.IsAny<IDictionary<string, string>>(), It.IsAny<MobileServiceFeatures>()))
                      .Returns(Task.FromResult(QueryResult.Parse(result, null, false)));

            if (result.Any())
            {
                this.table.Setup(t => t.ReadAsync(secondQuery, It.IsAny<IDictionary<string, string>>(), It.IsAny<MobileServiceFeatures>()))
                          .Returns(Task.FromResult(QueryResult.Parse(new JArray(), null, false)));
            }

            if (result.Any())
            {
                this.store.Setup(s => s.UpsertAsync("test", It.IsAny<IEnumerable<JObject>>(), true)).Returns(Task.FromResult(0));
            }

            this.settings.Setup(s => s.GetDeltaTokenAsync("test", "latestItems")).Returns(Task.FromResult(new DateTimeOffset(2013, 1, 1, 0, 0, 0, TimeSpan.Zero)));
            if (savesMax)
            {
                this.settings.Setup(s => s.SetDeltaTokenAsync("test", "latestItems", maxUpdatedAt)).Returns(Task.FromResult(0));
            }

            await action.ExecuteAsync();

            this.store.VerifyAll();
            this.opQueue.VerifyAll();
            this.table.VerifyAll();
            this.settings.VerifyAll();

            store.Verify(s => s.DeleteAsync("test", It.IsAny<IEnumerable<string>>()), Times.Never(), "There shouldn't be any call to delete");
        }
        private static MobileServiceTableQueryDescription Parse(string tableName, string query, string uriPath)
        {
            bool includeTotalCount = false;
            int? top = null;
            int? skip = null;
            string[] selection = null;
            QueryNode filter = null;
            IList<OrderByNode> orderings = null;

            IDictionary<string, string> parameters = HttpUtility.ParseQueryString(query);

            foreach (KeyValuePair<string, string> parameter in parameters)
            {
                string key = parameter.Key;
                string value = parameter.Value;
                if (String.IsNullOrEmpty(key))
                {
                    continue;
                }

                switch (key)
                {
                    case ODataOptions.Filter:
                        filter = ODataExpressionParser.ParseFilter(value);
                        break;
                    case ODataOptions.OrderBy:
                        orderings = ODataExpressionParser.ParseOrderBy(value);
                        break;
                    case ODataOptions.Skip:
                        skip = Int32.Parse(value);
                        break;
                    case ODataOptions.Top:
                        top = Int32.Parse(value);
                        break;
                    case ODataOptions.Select:
                        selection = value.Split(',');
                        break;
                    case ODataOptions.InlineCount:
                        includeTotalCount = "allpages".Equals(value);
                        break;
                    default:
                        throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Unrecognized query parameter '{0}'.", key), "query");
                }
            }

            var description = new MobileServiceTableQueryDescription(tableName)
            {
                IncludeTotalCount = includeTotalCount,
                Skip = skip,
                Top = top
            };
            description.UriPath = uriPath;
            if (selection != null)
            {
                ((List<string>)description.Selection).AddRange(selection);
            }
            if (orderings != null)
            {
                ((List<OrderByNode>)description.Ordering).AddRange(orderings);
            }
            description.Filter = filter;

            return description;
        }
 /// <summary>
 /// Executes the query on local store and returns the first or default item from parsed result
 /// </summary>
 /// <param name="store">An instance of <see cref="IMobileServiceLocalStore"/></param>
 /// <param name="query">An instance of <see cref="MobileServiceTableQueryDescription"/></param>
 /// <returns>Task that will complete with the first or default item from parsed result of the query.</returns>
 public static async Task<JObject> FirstOrDefault(this IMobileServiceLocalStore store, MobileServiceTableQueryDescription query)
 {
     QueryResult result = await store.QueryAsync(query);
     return result.Values.FirstOrDefault() as JObject;
 }