public IndexGet(ulong entityModelId, byte indexId) { var model = RuntimeContext.Current.GetModelAsync <EntityModel>(entityModelId).Result; if (model == null) { throw new Exception($"Can't get entity model of :{entityModelId}"); } if (model.SysStoreOptions == null || !model.SysStoreOptions.HasIndexes) { throw new Exception($"Can't get index model of:{indexId}"); } EntityIndexModel indexModel = null; for (int i = 0; i < model.SysStoreOptions.Indexes.Count; i++) { if (model.SysStoreOptions.Indexes[i].IndexId == indexId) { indexModel = model.SysStoreOptions.Indexes[i]; break; } } if (indexModel == null) { throw new Exception($"Can't get index model of:{indexId}"); } if (!indexModel.Unique) { throw new Exception("Only unique index can use IndexGet"); } _indexModel = indexModel; _predicates = new KeyPredicate[_indexModel.Fields.Length]; }
public IndexGet(EntityIndexModel indexModel) { if (indexModel == null) { throw new ArgumentNullException(nameof(indexModel)); } if (!indexModel.Unique) { throw new Exception("Only unique index can use IndexGet"); } _indexModel = indexModel; _predicates = new KeyPredicate[_indexModel.Fields.Length]; }
/// <summary> /// SysStore及SqlStore通用 /// </summary> private static IndexModelBase AddIndex(EntityModel entityModel, string value) { if (entityModel.StoreOptions == null) { throw new InvalidOperationException("Can't add index for DTO"); } var indexInfo = JsonConvert.DeserializeObject <IndexInfo>(value); //Validate if (string.IsNullOrEmpty(indexInfo.Name)) { throw new Exception("Index has no name"); } if (!CodeHelper.IsValidIdentifier(indexInfo.Name)) { throw new Exception("Index name not valid"); } if (indexInfo.Fields == null || indexInfo.Fields.Length == 0) { throw new Exception("Index has no fields"); } if (entityModel.StoreOptions.HasIndexes && entityModel.StoreOptions.Indexes.Any(t => t.Name == indexInfo.Name)) { throw new Exception("Index name has existed"); } var fields = new FieldWithOrder[indexInfo.Fields.Length]; for (int i = 0; i < indexInfo.Fields.Length; i++) { fields[i] = new FieldWithOrder(indexInfo.Fields[i].MID, indexInfo.Fields[i].OrderByDesc); } //根据存储类型新建索引并添加至模型内 if (entityModel.SysStoreOptions != null) { var newIndex = new EntityIndexModel(entityModel, indexInfo.Name, indexInfo.Unique, fields, null); entityModel.SysStoreOptions.AddIndex(entityModel, newIndex); return(newIndex); } else { var newIndex = new SqlIndexModel(entityModel, indexInfo.Name, indexInfo.Unique, fields, null); entityModel.SqlStoreOptions.AddIndex(entityModel, newIndex); return(newIndex); } }
/// <summary> /// 写索引Value /// </summary> /// <returns>非惟一索引且没有覆盖字段返回IntPtr.Zero</returns> internal unsafe static IntPtr WriteIndexData(Entity entity, EntityIndexModel indexModel, out int dataSize) { if (!(indexModel.Unique || indexModel.HasStoringFields)) { dataSize = 0; return(IntPtr.Zero); } int *varSizes = null; int totalSize = indexModel.Unique ? 2 + 16 : 0; if (indexModel.HasStoringFields) { int *vars = stackalloc int[indexModel.StoringFields.Length]; for (int i = 0; i < indexModel.StoringFields.Length; i++) { totalSize += CalcMemberSize(ref entity.GetMember(indexModel.StoringFields[i]), vars + i, true); } varSizes = vars; } dataSize = totalSize; var w = new EntityStoreWriter(totalSize); //先写入惟一索引指向的EntityId if (indexModel.Unique) { w.WriteUInt16(IdUtil.STORE_FIELD_ID_OF_ENTITY_ID); w.WriteGuid(entity.Id.Data); } //再写入StoringFields if (indexModel.HasStoringFields) { for (int i = 0; i < indexModel.StoringFields.Length; i++) { w.WriteMember(ref entity.GetMember(indexModel.StoringFields[i]), varSizes + i, true, false); //TODO:考虑不写入Null } } return(w.nativeStringPtr); }
internal unsafe void WriteIndexKey(Entity entity, EntityIndexModel indexModel, int *varSizes) { var id = entity.Id.Data; byte *idptr = (byte *)&id; //写入EntityId's RaftGroupId WriteSpan(new ReadOnlySpan <byte>(idptr, 6)); //写入IndexId dataPtr[index++] = indexModel.IndexId; //写入各成员 for (int i = 0; i < indexModel.Fields.Length; i++) { //注意MemberId写入排序标记 WriteMember(ref entity.GetMember(indexModel.Fields[i].MemberId), varSizes + i, true, indexModel.Fields[i].OrderByDesc); } //非惟一索引写入EntityId的第二部分 if (!indexModel.Unique) { WriteSpan(new ReadOnlySpan <byte>(idptr + 6, 10)); } }
internal unsafe void WriteKeyRange(ulong groupId, EntityIndexModel model, byte *bk, byte *ek, int *varSizes) { EntityId.WriteRaftGroupId(bk, groupId); EntityId.WriteRaftGroupId(ek, groupId); bk[KeyUtil.INDEXCF_INDEXID_POS] = ek[KeyUtil.INDEXCF_INDEXID_POS] = model.IndexId; if (predicates == null || !predicates[0].HasValue) //short path for no predicate { ek[KeyUtil.INDEXCF_INDEXID_POS] = (byte)(model.IndexId + 1); return; } var bw = new EntityStoreWriter(bk, KeyUtil.INDEXCF_PREFIX_SIZE); var ew = new EntityStoreWriter(ek, KeyUtil.INDEXCF_PREFIX_SIZE); for (int i = 0; i < predicates.Length; i++) { if (!predicates[i].HasValue) { break; //没有指定谓词跳出 } var m = predicates[i].Value.Value; switch (predicates[i].Value.Type) { case KeyPredicateType.Equal: { //注意写入索引键的排序标记 bw.WriteMember(ref m, varSizes, true, model.Fields[i].OrderByDesc); ew.WriteMember(ref m, varSizes, true, model.Fields[i].OrderByDesc); } break; default: throw new NotImplementedException(); } } }
private IActionResult CreateIndexResult(EntityIndexModel model) => View(model);
static TestHelper() { SysAppModel = new ApplicationModel("appbox", Consts.SYS, Consts.SYS_APP_ID); AdminPermissionModel = new PermissionModel(Consts.SYS_PERMISSION_ADMIN_ID, "Admin"); DeveloperPermissionModel = new PermissionModel(Consts.SYS_PERMISSION_DEVELOPER_ID, "Developer"); OrderStatusModel = new EnumModel(SYS_ENUM_MODEL_ID | (1 << IdUtil.MODELID_SEQ_OFFSET), "OrderStatus"); OrderStatusModel.Items.Add(new EnumModelItem("New", 0)); OrderStatusModel.Items.Add(new EnumModelItem("Paid", 1)); EmploeeModel = new EntityModel(Consts.SYS_EMPLOEE_MODEL_ID, Consts.EMPLOEE, EntityStoreType.StoreWithMvcc); var name = new DataFieldModel(EmploeeModel, Consts.NAME, EntityFieldType.String); EmploeeModel.AddSysMember(name, Consts.EMPLOEE_NAME_ID); var account = new DataFieldModel(EmploeeModel, Consts.ACCOUNT, EntityFieldType.String); account.AllowNull = true; EmploeeModel.AddSysMember(account, Consts.EMPLOEE_ACCOUNT_ID); var password = new DataFieldModel(EmploeeModel, Consts.PASSWORD, EntityFieldType.Binary); password.AllowNull = true; EmploeeModel.AddSysMember(password, Consts.EMPLOEE_PASSWORD_ID); //Add indexes var ui_account_pass = new EntityIndexModel(EmploeeModel, "UI_Account_Password", true, new FieldWithOrder[] { new FieldWithOrder(Consts.EMPLOEE_ACCOUNT_ID) }, new ushort[] { Consts.EMPLOEE_PASSWORD_ID }); EmploeeModel.SysStoreOptions.AddSysIndex(EmploeeModel, ui_account_pass, Consts.EMPLOEE_UI_ACCOUNT_ID); //测试用分区表 VehicleStateModel = new EntityModel(((ulong)Consts.SYS_APP_ID << 32) | 18, "VehicleState", EntityStoreType.StoreWithMvcc); var vid = new DataFieldModel(VehicleStateModel, "VehicleId", EntityFieldType.Int32); VehicleStateModel.AddMember(vid); var lng = new DataFieldModel(VehicleStateModel, "Lng", EntityFieldType.Float); VehicleStateModel.AddMember(lng); var lat = new DataFieldModel(VehicleStateModel, "Lat", EntityFieldType.Float); VehicleStateModel.AddMember(lat); var pks = new PartitionKey[1]; pks[0] = new PartitionKey() { MemberId = vid.MemberId, OrderByDesc = false }; VehicleStateModel.SysStoreOptions.SetPartitionKeys(VehicleStateModel, pks); //测试树状结构 ulong orgUnitModelId = ((ulong)Consts.SYS_APP_ID << 32) | 19; OrgUnitModel = new EntityModel(orgUnitModelId, "OrgUnit", EntityStoreType.StoreWithMvcc); var ouName = new DataFieldModel(OrgUnitModel, "Name", EntityFieldType.String); OrgUnitModel.AddSysMember(ouName, 1 << IdUtil.MEMBERID_SEQ_OFFSET); var parentId = new DataFieldModel(OrgUnitModel, "ParentId", EntityFieldType.EntityId, true); parentId.AllowNull = true; OrgUnitModel.AddSysMember(parentId, 2 << IdUtil.MEMBERID_SEQ_OFFSET); var parent = new EntityRefModel(OrgUnitModel, "Parent", orgUnitModelId, new ushort[] { parentId.MemberId }); parent.AllowNull = true; OrgUnitModel.AddSysMember(parent, 3 << IdUtil.MEMBERID_SEQ_OFFSET); var childs = new EntitySetModel(OrgUnitModel, "Childs", orgUnitModelId, parent.MemberId); OrgUnitModel.AddSysMember(childs, 4 << IdUtil.MEMBERID_SEQ_OFFSET); //----以下测试映射至SqlStore的实体--- SqlStoreModel = new DataStoreModel(DataStoreKind.Sql, "appbox.Store.PostgreSQL;appbox.Store.PgSqlStore", "DemoDB"); ulong cityModelId = ((ulong)Consts.SYS_APP_ID << 32) | 25; CityModel = new EntityModel(cityModelId, "City", new SqlStoreOptions(SqlStoreModel.Id)); var cityCode = new DataFieldModel(CityModel, "Code", EntityFieldType.Int32); CityModel.AddMember(cityCode); var cityName = new DataFieldModel(CityModel, "Name", EntityFieldType.String); CityModel.AddMember(cityName); var cityPerson = new DataFieldModel(CityModel, "Persons", EntityFieldType.Int32); CityModel.AddMember(cityPerson); var cityPk = new List <FieldWithOrder>(); cityPk.Add(new FieldWithOrder { MemberId = cityCode.MemberId, OrderByDesc = false }); CityModel.SqlStoreOptions.SetPrimaryKeys(CityModel, cityPk); ulong customerModelId = ((ulong)Consts.SYS_APP_ID << 32) | 26; CustomerModel = new EntityModel(customerModelId, "Customer", new SqlStoreOptions(SqlStoreModel.Id)); var customerId = new DataFieldModel(CustomerModel, "Id", EntityFieldType.Int32); CustomerModel.AddMember(customerId); var customerName = new DataFieldModel(CustomerModel, "Name", EntityFieldType.String); CustomerModel.AddMember(customerName); var customerCityId = new DataFieldModel(CustomerModel, "CityId", EntityFieldType.Int32, true); CustomerModel.AddMember(customerCityId); var customerCity = new EntityRefModel(CustomerModel, "City", cityModelId, new ushort[] { customerCityId.MemberId }); CustomerModel.AddMember(customerCity); var customerPk = new List <FieldWithOrder>(); customerPk.Add(new FieldWithOrder { MemberId = customerId.MemberId, OrderByDesc = false }); CustomerModel.SqlStoreOptions.SetPrimaryKeys(CustomerModel, customerPk); ulong orderModelId = ((ulong)Consts.SYS_APP_ID << 32) | 27; OrderModel = new EntityModel(orderModelId, "Order", new SqlStoreOptions(SqlStoreModel.Id)); var orderId = new DataFieldModel(OrderModel, "Id", EntityFieldType.Int32); OrderModel.AddMember(orderId); var orderCustomerId = new DataFieldModel(OrderModel, "CustomerId", EntityFieldType.Int32, true); OrderModel.AddMember(orderCustomerId); var orderCustomer = new EntityRefModel(OrderModel, "Customer", customerModelId, new ushort[] { orderCustomerId.MemberId }); OrderModel.AddMember(orderCustomer); var orderPk = new List <FieldWithOrder>(); orderPk.Add(new FieldWithOrder { MemberId = orderId.MemberId, OrderByDesc = false }); OrderModel.SqlStoreOptions.SetPrimaryKeys(OrderModel, orderPk); }
/// <summary> /// 执行本地索引扫描,分区表与非分区表通用 /// </summary> private async ValueTask <IScanResponse> ExecLocalIndexScanAsync( EntityIndexModel indexModel, ulong groupId, uint pskip, uint ptake, bool toIndexTarget) { //TODO:***将不能编入Key的谓词作为Filter条件 //开始处理NativeApi所需参数 IntPtr bkPtr; IntPtr ekPtr; int bkSize = KeyUtil.INDEXCF_PREFIX_SIZE; int ekSize = KeyUtil.INDEXCF_PREFIX_SIZE; IntPtr filterPtr = IntPtr.Zero; unsafe { int *varSizes = stackalloc int[indexModel.Fields.Length]; if (_keys != null) { bkSize = ekSize = _keys.CalcKeySize(varSizes); } byte *bk = stackalloc byte[bkSize]; bkPtr = new IntPtr(bk); byte *ek = stackalloc byte[ekSize]; ekPtr = new IntPtr(ek); if (_keys == null) { KeyUtil.WriteIndexKeyPrefix(bk, groupId, indexModel.IndexId); ekPtr = IntPtr.Zero; ekSize = 0; } else { _keys.WriteKeyRange(groupId, indexModel, bk, ek, varSizes); if (_keys.IsOnlyEqual()) //只有相等性判断使用前缀匹配 { ekPtr = IntPtr.Zero; ekSize = 0; } } } if (!Expression.IsNull(filter)) { filterPtr = ModelStore.SerializeModel(filter, out _); } var req = new ClrScanRequire { RaftGroupId = groupId, BeginKeyPtr = bkPtr, BeginKeySize = new IntPtr(bkSize), EndKeyPtr = ekPtr, EndKeySize = new IntPtr(ekSize), FilterPtr = filterPtr, Skip = pskip, Take = ptake, DataCF = KeyUtil.INDEXCF_INDEX, ToIndexTarget = toIndexTarget }; IntPtr reqPtr; unsafe { reqPtr = new IntPtr(&req); } return(await StoreApi.Api.ReadIndexByScanAsync(reqPtr)); }