Пример #1
0
        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));
        }
Пример #2
0
        /// <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);
            }
        }