diff --git a/src/mutation.ts b/src/mutation.ts index 0aef34202..456528c57 100644 --- a/src/mutation.ts +++ b/src/mutation.ts @@ -25,6 +25,24 @@ export type ISetCell = btTypes.bigtable.v2.Mutation.ISetCell; export type Bytes = string | Buffer; // eslint-disable-next-line @typescript-eslint/no-explicit-any export type Data = any; +/* +The Data type is expected to be in the following format: +{ + columnFamily1: { + column1: Cell, + column2: Cell + }, + columnFamily2: { + otherColumn1: Cell, + otherColumn2: Cell + } +} +Where the Cell data type has the following structure: +Uint8Array | string | { + value: Uint8Array|string, + timestamp: number|Long|string, +} +*/ export interface JsonObj { [k: string]: string | JsonObj; } diff --git a/src/table.ts b/src/table.ts index e7c286c0f..55d9182c3 100644 --- a/src/table.ts +++ b/src/table.ts @@ -287,6 +287,14 @@ export interface MutateOptions { // eslint-disable-next-line @typescript-eslint/no-explicit-any export type Entry = any; +/* +The Entry type is expected to be in the following format: +{ + columnFamily: { + column: Data // Data is the expected type passed into Mutation.encodeSetCell + } +} +*/ export type DeleteTableCallback = ( err: ServiceError | null, diff --git a/system-test/bigtable.ts b/system-test/bigtable.ts index 10e70e6bc..225426847 100644 --- a/system-test/bigtable.ts +++ b/system-test/bigtable.ts @@ -33,6 +33,7 @@ import {Row} from '../src/row.js'; import {Table} from '../src/table.js'; import {RawFilter} from '../src/filter'; import {generateId, PREFIX} from './common'; +import {Mutation} from '../src/mutation'; describe('Bigtable', () => { const bigtable = new Bigtable(); @@ -1712,6 +1713,90 @@ describe('Bigtable', () => { }); }); }); + + describe('mutateRows entries tests', () => { + const table = INSTANCE.table(generateId('table')); + + afterEach(async () => { + await table.delete(); + }); + + it('should only insert one row in the table with mutate', async () => { + // Create table + const tableOptions = { + families: ['columnFamily'], + }; + await table.create(tableOptions); + // Add entries + const entry = { + columnFamily: { + column: 1, + }, + }; + const mutation = { + key: 'rowKey', + data: entry, + method: Mutation.methods.INSERT, + }; + const gaxOptions = {maxRetries: 4}; + await table.mutate(mutation, {gaxOptions}); + // Get rows and compare + const [rows] = await table.getRows(); + assert.strictEqual(rows.length, 1); + }); + + it('should insert one row in the table using mutate in a similar way to how the documentation says to use insert', async () => { + // Create table + const tableOptions = { + families: ['columnFamily'], + }; + await table.create(tableOptions); + // Add entries + const mutation = { + key: 'rowKey', + data: { + columnFamily: { + column: 1, + }, + }, + method: Mutation.methods.INSERT, + }; + const gaxOptions = {maxRetries: 4}; + await table.mutate(mutation, {gaxOptions}); + // Get rows and compare + const [rows] = await table.getRows(); + assert.strictEqual(rows.length, 1); + }); + + it('should only insert one row in the table with insert as described by the GCP documentation', async () => { + // Create table + const tableOptions = { + families: ['follows'], + }; + await table.create(tableOptions); + // Add entries + const greetings = ['Hello World!', 'Hello Bigtable!', 'Hello Node!']; + const rowsToInsert = greetings.map((greeting, index) => ({ + key: `greeting${index}`, + data: { + follows: { + // 'follows' is the column family + someColumn: { + // Setting the timestamp allows the client to perform retries. If + // server-side time is used, retries may cause multiple cells to + // be generated. + timestamp: new Date(), + value: greeting, + }, + }, + }, + })); + await table.insert(rowsToInsert); + // Get rows and compare + const [rows] = await table.getRows(); + assert.strictEqual(rows.length, 3); + }); + }); }); function createInstanceConfig(