public IEnumerable <T> Get(ResourceQuery query, CancellationToken cancellationToken) { Debug.Assert(query.PageOffset.HasValue); Debug.Assert(query.PageSize.HasValue); var viewName = GetResourceName(); var orderBy = SqliteBuilder.OrderBySql(query); var sql = SqliteBuilder.SelectSql(viewName, _members, query, out var hasWhere); var pageSql = sql + SqliteBuilder.PageSql(query, viewName, orderBy, hasWhere); var db = OpenConnection(); IEnumerable <T> result = db.Query <T>(pageSql); if (!query.CountTotalRows) { return(result); } var countSql = SqliteBuilder.CountSql(sql, orderBy); var total = db.QuerySingle <int>(countSql); query.TotalRows = total; return(result); }
private void RebuildView(IDbConnection db, IDbTransaction t, IEnumerable <SqliteTableInfo> tableInfoList, int revision) { var viewName = GetResourceName(); db.Execute(SqliteBuilder.DropViewSql(viewName), transaction: t); db.Execute(SqliteBuilder.CreateViewSql(viewName, _members, revision, tableInfoList), transaction: t); }
public ResourceDataDistribution?GetResourceDataDistribution(int revision) { var viewName = GetResourceName(); using var db = new SqliteConnection($"Data Source={FilePath}"); db.Open(); using var t = db.BeginTransaction(); var tableInfoList = db.Query <SqliteTableInfo>(SqliteBuilder.GetTableInfo(), new { name = $"{viewName}%" }, t) .Where(x => !x.name.Contains("_Search")) .AsList() ?? throw new NullReferenceException(); foreach (var tableInfo in tableInfoList) { var revisionString = Regex.Split(tableInfo.name, "([0-9])+$", RegexOptions.IgnoreCase | RegexOptions.Compiled)[1]; if (!int.TryParse(revisionString, out var tableRevision) || tableRevision != revision) { continue; } var count = db.QuerySingle <long>($"SELECT COUNT(*) FROM \"{tableInfo.name}\"", transaction: t); var result = new ResourceDataDistribution { Partition = tableInfo.name, RowCount = count }; return(result); } return(default);
private void CreateThroughTableRevisions(IDbConnection db, IDbTransaction t, int revision) { var viewName = GetResourceName(); // Versioning: // // - Find the API version for the current resource revision // - For any embedded resource collections, find the revision for this API version var version = _changeLog.GetApiVersionForResourceAndRevision(viewName, revision); foreach (var member in _members) { if (!member.Type.ImplementsGeneric(typeof(IEnumerable <>)) || !member.Type.IsGenericType) { continue; // not a collection } var arguments = member.Type.GetGenericArguments(); var embeddedCollectionType = arguments[0]; if (!typeof(IResource).IsAssignableFrom(embeddedCollectionType)) { continue; // not a resource collection } if (!_changeLog.TryGetResourceNameForType(embeddedCollectionType, out var embeddedViewName) || embeddedViewName == default) { embeddedViewName = embeddedCollectionType.Name; } var embeddedViewRevision = _changeLog.GetRevisionForResourceAndApiVersion(embeddedViewName, version); var sql = SqliteBuilder.CreateThroughTableSql(viewName, revision, embeddedViewName, embeddedViewRevision); db.Execute(sql, transaction: t); } }
private long GetNextSequence(int revision, IDbConnection db, IDbTransaction t) { var previous = revision == 1 ? 1 : revision - 1; var viewName = GetResourceName(); // check current partition first var sequence = db.QuerySingleOrDefault <long?>(SqliteBuilder.GetMaxSequence(viewName, revision), transaction: t); while (!sequence.HasValue) { sequence = db.QuerySingleOrDefault <long?>( SqliteBuilder.GetMaxSequence(viewName, previous), transaction: t); previous--; // account for multiple revisions before the first insertion if (previous == 0) { sequence = 0; } } var nextSequence = sequence.GetValueOrDefault(0); nextSequence++; return(nextSequence); }
private void Visit(IDbConnection db, IDbTransaction t) { var viewName = GetResourceName(); var tableInfoList = db.Query <SqliteTableInfo>(SqliteBuilder.GetTableInfo(), new { name = $"{viewName}%" }, t) .Where(x => !x.name.Contains("_Search")) .AsList() ?? throw new NullReferenceException(); int revision; if (tableInfoList.Count == 0) { revision = 1; Visit(db, t, revision, tableInfoList); } else { var tableInfo = tableInfoList[0]; var revisionString = Regex.Split(tableInfo.name, "([0-9])+$", RegexOptions.IgnoreCase | RegexOptions.Compiled)[1]; if (!int.TryParse(revisionString, out revision)) { throw new FormatException(_localizer.GetString("invalid revision number")); } if (_revision <= revision) { return; } Visit(db, t, _revision, tableInfoList); } }
private void InsertRecord(T resource, int revision, bool deleted, IDbConnection db, IDbTransaction t) { var sequence = GetNextSequence(revision, db, t); var viewName = GetResourceName(); var hash = SqliteBuilder.InsertSql(resource, viewName, _reads, _members, revision, sequence, deleted, out string sql); db.Execute(sql, hash, t); }
public bool Exists(Guid id, bool includeDeleted, CancellationToken cancellationToken) { var db = OpenConnection(); var viewName = GetResourceName(); var result = db.QuerySingleOrDefault <int?>(SqliteBuilder.ExistsSql(viewName, includeDeleted), new { Id = id }); return(result != default); }
public bool TryGetById(Guid id, out T?resource, out bool error, List <string>?fields, bool includeDeleted, CancellationToken cancellationToken) { try { var db = OpenConnection(); var viewName = GetResourceName(); var result = db.QuerySingleOrDefault <T?>(SqliteBuilder.GetByIdSql(viewName, _members, fields, includeDeleted), new { Id = id }); resource = result; error = false; return(resource != default); } catch (Exception e) { _logger.LogError(ErrorEvents.ErrorRetrievingResource, e, _localizer.GetString("Error retrieving resource from SQLite")); resource = default; error = true; return(false); } }
private void CreateTableRevision(IDbConnection db, IDbTransaction t, int revision) { var viewName = GetResourceName(); { var sql = SqliteBuilder.CreateTableSql(viewName, _members, revision, false); db.Execute(sql, transaction: t); } if (SupportsSearch) { var sql = SqliteBuilder.AfterInsertTriggerSql(viewName, _members, revision); db.Execute(sql, transaction: t); } foreach (var member in _members.GetValueTypeFields()) { if (member.Name.Equals(nameof(IResource.Id))) { IndexMember(db, t, revision, member, true); } if (member.HasAttribute <IndexAttribute>()) { IndexMember(db, t, revision, member, false); } } // FIXME: deal with user field name collisions { var sql = SqliteBuilder.CreateIndexSql(GetResourceName(), "IsDeleted", revision, false); db.Execute(sql, transaction: t); } if (SupportsSearch) { var sql = SqliteBuilder.CreateTableSql(viewName, _members, revision, true); db.Execute(sql, transaction: t); } }
private void IndexMember(IDbConnection db, IDbTransaction t, int revision, AccessorMember member, bool unique) { var sql = SqliteBuilder.CreateIndexSql(GetResourceName(), member.Name, revision, unique); db.Execute(sql, transaction: t); }