Skip to content

Commit

Permalink
add index support (#573)
Browse files Browse the repository at this point in the history
* feat: add doc store

* feat: add index

* test: add index test case
  • Loading branch information
imotai authored Jul 24, 2023
1 parent 8c41779 commit 2be31b0
Show file tree
Hide file tree
Showing 13 changed files with 282 additions and 78 deletions.
6 changes: 3 additions & 3 deletions sdk/src/account/db3_account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import { toHEX } from '../crypto/crypto_utils'
* const account = createFromPrivateKey("0x........")
* ```
* @param privatekey - a hex format private key string
* @returns the instance of {@link DB3ACCOUNT}
* @returns the instance of {@link DB3Account}
*
**/
export function createFromPrivateKey(privateKey: Hex) {
Expand All @@ -60,7 +60,7 @@ export function createFromPrivateKey(privateKey: Hex) {
* ```ts
* const account = createRandomAccount()
* ```
* @returns the instance of {@link DB3ACCOUNT}
* @returns the instance of {@link DB3Account}
*
**/
export function createRandomAccount() {
Expand All @@ -75,7 +75,7 @@ export function createRandomAccount() {
* ```ts
* const account = createFromExternal()
* ```
* @returns the instance of {@link DB3ACCOUNT}
* @returns the instance of {@link DB3Account}
*
**/
export async function createFromExternal(chain?: Chain) {
Expand Down
14 changes: 11 additions & 3 deletions sdk/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,25 @@
* limitations under the License.
*/

export type { DB3Account } from './account/types'
export {
createFromPrivateKey,
createRandomAccount,
signTypedData,
createFromExternal,
} from './account/db3_account'
export type { DB3Account } from './account/types'
export type { Client, ReadClient } from './client/types'
export type { Database, Collection } from './store/types'
export type {
Database,
Collection,
CreateDBResult,
CreateCollectionResult,
MutationResult,
QueryResult,
} from './store/types'
export { addDoc, updateDoc, deleteDoc, queryDoc } from './store/document_v2'

export { SystemConfig, SystemStatus } from './proto/db3_base'
export { SystemConfig, SystemStatus, Version } from './proto/db3_base'
export {
createClient,
createReadonlyClient,
Expand All @@ -50,6 +57,7 @@ export {
showCollection,
getDatabase,
getCollection,
addIndex,
} from './store/database_v2'

export { Index, IndexType } from './proto/db3_database_v2'
Expand Down
1 change: 0 additions & 1 deletion sdk/src/provider/storage_provider_v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,6 @@ export class StorageProviderV2 {
blockId: block,
orderId: order,
}

try {
const { response } = await this.client.getMutationHeader(request)
return response
Expand Down
89 changes: 81 additions & 8 deletions sdk/src/store/database_v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
Mutation_BodyWrapper,
DocumentDatabaseMutation,
EventDatabaseMutation,
AddIndexMutation,
} from '../proto/db3_mutation_v2'

import { Client, ReadClient } from '../client/types'
Expand All @@ -43,10 +44,22 @@ import { Index } from '../proto/db3_database_v2'
* Create an event database to store contract events
*
* ```ts
* const {db, result} = await createEventDatabase(client, "my_db")
* const {db, result} = await createEventDatabase(client,
* "my contract event db",
* "0x...",
* ["DepositEvent"],
* "{...}",
* "wss://xxxxx",
* "100000"
* )
* ```
* @param client - the db3 client instance
* @param desc - the description for the database
* @param client - the client instance
* @param desc - the description for the event database
* @param contractAddress - the contract address
* @param tables - the contract event list
* @param abi - the json abi of contract
* @param evmNodeUrl - the websocket url of evm node
* @param startBlock - the start block to subscribe, 0 start from the latest block
* @returns the {@link CreateDBResult}
*
**/
Expand Down Expand Up @@ -111,6 +124,65 @@ export async function createEventDatabase(
throw new Error('fail to create database')
}
}
/**
*
* Add index the existing Collection
*
* ```ts
*
* const index:Index = {
* path:'/city', // a top level field name 'city' and the path will be '/city'
* indexType: IndexType.StringKey
* }
* const result = await addIndex(collection, [index])
* ```
* @param client - the db3 client instance
* @param indexes - the index list of {@link Index}
* @returns the {@link MutationResult}
*
**/
export async function addIndex(collection: Collection, indexes: Index[]) {
if (indexes.filter((item) => !item.path.startsWith('/')).length > 0) {
throw new Error('the index path must start with /')
}
const addIndexMutation: AddIndexMutation = {
collectionName: collection.name,
indexFields: indexes,
}

const body: Mutation_BodyWrapper = {
body: { oneofKind: 'addIndexMutation', addIndexMutation },
dbAddress: fromHEX(collection.db.addr),
}

const dm: Mutation = {
action: MutationAction.AddIndex,
bodies: [body],
}
const payload = Mutation.toBinary(dm)
try {
const response = await collection.db.client.provider.sendMutation(
payload,
collection.db.client.nonce.toString()
)
if (response.code == 0) {
return {
result: {
id: response.id,
block: response.block,
order: response.order,
} as MutationResult,
}
} else {
throw new Error('fail to add index with err ' + response.msg)
}
} catch (e) {
throw e
} finally {
collection.db.client.nonce += 1
}
}

/**
*
* Create a document database to group the collections
Expand Down Expand Up @@ -163,12 +235,12 @@ export async function createDocumentDatabase(client: Client, desc: string) {
* Get the collection by an db address and collection name
*
* ```ts
* const database = await getCollection("0x....", "col1", client)
* const collection = await getCollection("0x....", "col1", client)
* ```
* @param addr - a hex format string address
* @param addr - a hex format string database address
* @param name - the name of collection
* @param client- the db3 client instance
* @returns the {@link Database}[]
* @param client- the client instance
* @returns the {@link Collection}
*
**/
export async function getCollection(
Expand All @@ -187,6 +259,7 @@ export async function getCollection(
)
}
}

/**
*
* Get the database by an address
Expand Down Expand Up @@ -271,7 +344,7 @@ export async function showDatabase(owner: string, client: Client | ReadClient) {
*
* @param db - the instance of database
* @param name - the name of collection
* @param indexFields - the fields for index
* @param indexFields - the fields for {@link Index}
* @returns the {@link CreateCollectionResult}
*
**/
Expand Down
2 changes: 1 addition & 1 deletion sdk/src/store/document_v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ async function runQueryInternal<T>(col: Collection, query: Query) {
* @param col - the instance of collection
* @param queryStr - a document query string
* @param parameters - an optional query parameters
* @returns the {@link Queryresult}
* @returns the {@link QueryResult}
*
**/
export async function queryDoc<T = DocumentData>(
Expand Down
69 changes: 69 additions & 0 deletions sdk/tests/client_v2.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import {
createCollection,
getDatabase,
getCollection,
addIndex,
} from '../src/store/database_v2'
import { Index, IndexType } from '../src/proto/db3_database_v2'
import { SystemConfig } from '../src/proto/db3_base'
Expand Down Expand Up @@ -271,6 +272,74 @@ describe('test db3.js client module', () => {
expect(1).toBe(0)
}
})

test('test add index', async () => {
const client = await createTestClient()
try {
const { db } = await createDocumentDatabase(
client,
'db_for_add index'
)
expect(db).toBeDefined()
const index: Index = {
path: '/city',
indexType: IndexType.StringKey,
}
const { collection } = await createCollection(db, 'col', [index])
expect(collection).toBeDefined()
try {
await addIndex(collection, [index])
} catch (e) {
expect(
'invalid key path for error the index paths ["/city"] exist'
).toBe(e.message)
}
const index2: Index = {
path: '/name',
indexType: IndexType.StringKey,
}
try {
const result = await addIndex(collection, [index2])
expect(result).toBeDefined()
} catch (e) {
expect(1).toBe(2)
}
const badIndex: Index = {
path: 'name',
indexType: IndexType.StringKey,
}
try {
const result = await addIndex(collection, [badIndex])
expect(1).toBe(2)
} catch (e) {
expect('the index path must start with /').toBe(e.message)
}

const client2 = await createTestClient()
const collection2 = await getCollection(db.addr, 'col', client2)
expect(collection2).toBeDefined()
try {
const result = await addIndex(collection2, [index2])
expect(1).toBe(2)
} catch (e) {
expect('You have no permission to modify the collection').toBe(
e.message
)
}
expect(collection2.indexFields.length).toBe(2)
expect(collection2.indexFields[0].path).toBe('/city')
expect(collection2.indexFields[0].indexType).toBe(
IndexType.StringKey
)
expect(collection2.indexFields[1].path).toBe('/name')
expect(collection2.indexFields[1].indexType).toBe(
IndexType.StringKey
)
} catch (e) {
console.log(e)
expect(1).toBe(2)
}
})
test('test create/update/delete document', async () => {
const client = await createTestClient()
try {
Expand Down
13 changes: 4 additions & 9 deletions sdk/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3213,15 +3213,10 @@ caniuse-api@^3.0.0:
lodash.memoize "^4.1.2"
lodash.uniq "^4.5.0"

caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001426:
version "1.0.30001443"
resolved "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001443.tgz#8fc85f912d5471c9821acacf9e715c421ca0dd1f"
integrity sha512-jUo8svymO8+Mkj3qbUbVjR8zv8LUGpGkUM/jKvc9SO2BvjCI980dp9fQbf/dyLs6RascPzgR4nhAKFA4OHeSaA==

caniuse-lite@^1.0.30001400:
version "1.0.30001434"
resolved "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001434.tgz#ec1ec1cfb0a93a34a0600d37903853030520a4e5"
integrity sha512-aOBHrLmTQw//WFa2rcF1If9fa3ypkC1wzqqiKHgfdrXTWcU8C4gKVZT77eQAPWN1APys3+uQ0Df07rKauXGEYA==
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001400, caniuse-lite@^1.0.30001426:
version "1.0.30001517"
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001517.tgz"
integrity sha512-Vdhm5S11DaFVLlyiKu4hiUTkpZu+y1KA/rZZqVQfOD5YdDT/eQKlkt7NaE0WGOFgX32diqt9MiP9CAiFeRklaA==

capture-exit@^2.0.0:
version "2.0.0"
Expand Down
17 changes: 11 additions & 6 deletions src/error/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,7 @@ pub enum DB3Error {
QuerySessionVerifyError(String),
#[error("fail to query database {0}")]
QueryDatabaseError(String),
#[error("database with addr {0} was not found")]
DatabaseNotFound(String),
#[error("collection with name {0} was not found in db {1}")]
CollectionNotFound(String, String),
#[error("collection {0} already exist in db {1}")]
CollectionAlreadyExist(String, String),

#[error("the address does not match the public key")]
InvalidSigner,
#[error("fail to generate key for {0}")]
Expand Down Expand Up @@ -139,6 +134,16 @@ pub enum DB3Error {
InvalidArUrlError(String),
#[error("invalid database desc for error {0}")]
InvalidDescError(String),

#[error("database with addr {0} was not found")]
DatabaseNotFound(String),

#[error("collection with name {0} was not found in db {1}")]
CollectionNotFound(String, String),
#[error("collection {0} already exist in db {1}")]
CollectionAlreadyExist(String, String),
#[error("You have no permission to modify the collection")]
CollectionPermssionDenied(),
}

pub type Result<T> = std::result::Result<T, DB3Error>;
1 change: 0 additions & 1 deletion src/node/src/storage_node_light_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,6 @@ impl StorageNode for StorageNodeV2Impl {
})?;
let action = MutationAction::from_i32(dm.action)
.ok_or(Status::invalid_argument("bad mutation action".to_string()))?;
// TODO validate the database mutation
match self.state_store.incr_nonce(&address, nonce) {
Ok(_) => {
// mutation id
Expand Down
1 change: 0 additions & 1 deletion src/proto/proto/db3_database_v2.proto
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ message EventTable {
}

message Collection {
bytes id = 1;
string name = 2;
repeated Index index_fields = 3;
bytes sender = 4;
Expand Down
7 changes: 7 additions & 0 deletions src/proto/proto/db3_mutation_v2.proto
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ message MintDocumentDatabaseMutation {
string sender = 6;
}

message AddIndexMutation {
string collection_name = 1;
repeated db3_database_v2_proto.Index index_fields = 2;
}

message DocumentMutation {
string collection_name = 1;
repeated bytes documents = 2;
Expand Down Expand Up @@ -102,6 +107,7 @@ enum MutationAction {
CreateEventDB = 5;
MintDocumentDB = 6;
MintCollection = 7;
AddIndex = 8;
}

enum MutationRollupStatus {
Expand All @@ -121,6 +127,7 @@ message Mutation {
DocumentDatabaseMutation doc_database_mutation = 5;
MintDocumentDatabaseMutation mint_doc_database_mutation = 6;
MintCollectionMutation mint_collection_mutation = 7;
AddIndexMutation add_index_mutation = 8;
}
}
repeated BodyWrapper bodies = 3;
Expand Down
Loading

0 comments on commit 2be31b0

Please sign in to comment.