public async ValueTask <IndexRow> ToIndexRowAsync() { ValidatePredicates(); var app = await RuntimeContext.Current.GetApplicationModelAsync(_indexModel.Owner.AppId); //Console.WriteLine($"IndexGet.ToIndexRowAsync: {StringHelper.ToHexString(keyPtr, keySize)}"); //TODO:*****暂只支持非分区表索引 if (_indexModel.Global || _indexModel.Owner.SysStoreOptions.HasPartitionKeys) { throw ExceptionHelper.NotImplemented(); } //先获取目标分区 ulong groupId = await EntityStore.GetOrCreateGlobalTablePartition(app, _indexModel.Owner, IntPtr.Zero); if (groupId == 0) { Log.Warn("Can't find index partition"); return(IndexRow.Empty); } //生成Key IntPtr keyPtr; int keySize = KeyUtil.INDEXCF_PREFIX_SIZE; unsafe { int *varSizes = stackalloc int[_indexModel.Fields.Length]; //主要用于记录String utf8数据长度,避免重复计算 for (int i = 0; i < _indexModel.Fields.Length; i++) { keySize += EntityStoreWriter.CalcMemberSize(ref _predicates[i].Value, varSizes + i, true); } byte *pkPtr = stackalloc byte[keySize]; EntityId.WriteRaftGroupId(pkPtr, groupId); pkPtr[KeyUtil.INDEXCF_INDEXID_POS] = _indexModel.IndexId; var writer = new EntityStoreWriter(pkPtr, KeyUtil.INDEXCF_PREFIX_SIZE); for (int i = 0; i < _predicates.Length; i++) { //注意写入索引键排序标记 writer.WriteMember(ref _predicates[i].Value, varSizes, true, _indexModel.Fields[i].OrderByDesc); } keyPtr = new IntPtr(pkPtr); } //TODO: 根据是否在事务内走ReadIndex或事务读命令 var res = await StoreApi.Api.ReadIndexByGetAsync(groupId, keyPtr, (uint)keySize, KeyUtil.INDEXCF_INDEX); return(res == null ? IndexRow.Empty : new IndexRow(res)); }
private static async ValueTask <Entity> LoadFieldPath(Entity owner, ushort memberId, ReadonlyTransaction txn) { //TODO:从事务缓存内先查找是否存在 var refModel = (EntityRefModel)owner.Model.GetMember(memberId, true); var refId = owner.GetEntityId(refModel.FKMemberIds[0]); if (refId == null) { return(null); } ulong refModelId = refModel.RefModelIds[0]; if (refModel.IsAggregationRef) { refModelId = owner.GetUInt64(refModel.TypeMemberId); } return(await EntityStore.LoadAsync(refModelId, refId)); }
/// <summary> /// 执行查询并返回Entity[] /// </summary> /// <returns>返回值可能为null</returns> public async ValueTask <IList <Entity> > ToListAsync() { var app = await RuntimeContext.Current.GetApplicationModelAsync(IdUtil.GetAppIdFromModelId(modelId)); var model = await RuntimeContext.Current.GetModelAsync <EntityModel>(modelId); var indexModel = model.SysStoreOptions.Indexes.SingleOrDefault(t => t.IndexId == indexId); if (indexModel == null) { throw new Exception("Index not exists."); } if (indexModel.Global) { throw new NotImplementedException(); } //先判断是否需要快照读事务 //TODO:跨分区也需要 ReadonlyTransaction txn = rootIncluder == null ? null : new ReadonlyTransaction(); if (model.SysStoreOptions.HasPartitionKeys) { //分区表先根据PartionPredicate查询出相关分区,再依次扫描 ulong[] parts = await GetPartitions(app.StoreId, model); if (parts == null || parts.Length == 0) { return(null); } var list = new List <Entity>((int)(take <= 1000 ? take : 20)); uint skipped = 0; uint taken = 0; for (int i = 0; i < parts.Length; i++) { var partRes = await ExecLocalIndexScanAsync(indexModel, parts[i], skip - skipped, take - taken, true); if (partRes != null) { partRes.ForEachRow((kp, ks, vp, vs) => { list.Add(EntityStoreReader.ReadEntity(model, kp, ks, vp, vs)); }); skipped += partRes.Skipped; taken += (uint)partRes.Length; partRes.Dispose(); if (taken >= take) { break; } } } await LoadIncludesAsync(list, txn); return(list); } else { ulong groupId = await EntityStore.GetOrCreateGlobalTablePartition(app, indexModel.Owner, IntPtr.Zero); if (groupId == 0) { return(null); } var res = await ExecLocalIndexScanAsync(indexModel, groupId, skip, take, true); if (res == null || res.Length == 0) { return(null); } var list = new Entity[res.Length]; int rowIndex = 0; res.ForEachRow((kp, ks, vp, vs) => { list[rowIndex] = EntityStoreReader.ReadEntity(model, kp, ks, vp, vs); rowIndex++; }); res.Dispose(); await LoadIncludesAsync(list, txn); return(list); } }