1 4
/*!
2 4
 * Copyright 2016 Google Inc. All Rights Reserved.
3 4
 *
4 4
 * Licensed under the Apache License, Version 2.0 (the "License");
5 4
 * you may not use this file except in compliance with the License.
6 4
 * You may obtain a copy of the License at
7 4
 *
8 4
 *      http://www.apache.org/licenses/LICENSE-2.0
9 4
 *
10 4
 * Unless required by applicable law or agreed to in writing, software
11 4
 * distributed under the License is distributed on an "AS IS" BASIS,
12 4
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 4
 * See the License for the specific language governing permissions and
14 4
 * limitations under the License.
15 4
 */
16 4

17 4
import {promisifyAll} from '@google-cloud/promisify';
18 4
import * as through from 'through2';
19 4
import {Operation as GaxOperation, CallOptions} from 'google-gax';
20 4
import {Database, UpdateSchemaCallback, UpdateSchemaResponse} from './database';
21 4
import {PartialResultStream, Row} from './partial-result-stream';
22 4
import {
23 4
  ReadRequest,
24 4
  TimestampBounds,
25 4
  CommitResponse,
26 4
  ReadResponse,
27 4
  ReadCallback,
28 4
  CommitCallback,
29 4
} from './transaction';
30 4
import {google as databaseAdmin} from '../protos/protos';
31 4
import {Schema, LongRunningCallback} from './common';
32 4

33 4
export type Key = string | string[];
34 4

35 4
export type CreateTableResponse = [
36 4
  Table,
37 4
  GaxOperation,
38 4
  databaseAdmin.longrunning.IOperation
39 4
];
40 4
export type CreateTableCallback = LongRunningCallback<Table>;
41 4

42 4
export type DropTableResponse = UpdateSchemaResponse;
43 4
export type DropTableCallback = UpdateSchemaCallback;
44 4

45 4
export type DeleteRowsCallback = CommitCallback;
46 4
export type DeleteRowsResponse = CommitResponse;
47 4

48 4
export type InsertRowsCallback = CommitCallback;
49 4
export type InsertRowsResponse = CommitResponse;
50 4

51 4
export type ReplaceRowsCallback = CommitCallback;
52 4
export type ReplaceRowsResponse = CommitResponse;
53 4

54 4
export type UpdateRowsCallback = CommitCallback;
55 4
export type UpdateRowsResponse = CommitResponse;
56 4

57 4
export type UpsertRowsCallback = CommitCallback;
58 4
export type UpsertRowsResponse = CommitResponse;
59 4
/**
60 4
 * Create a Table object to interact with a table in a Cloud Spanner
61 4
 * database.
62 4
 *
63 4
 * @class
64 4
 *
65 4
 * @param {Database} database {@link Database} instance.
66 4
 * @param {string} name Name of the table.
67 4
 *
68 4
 * @example
69 4
 * const {Spanner} = require('@google-cloud/spanner');
70 4
 * const spanner = new Spanner();
71 4
 *
72 4
 * const instance = spanner.instance('my-instance');
73 4
 * const database = instance.database('my-database');
74 4
 * const table = database.table('my-table');
75 4
 */
76 4
class Table {
77 4
  database: Database;
78 4
  name: string;
79 4
  constructor(database: Database, name: string) {
80 4
    /**
81 4
     * The {@link Database} instance of this {@link Table} instance.
82 4
     * @name Table#database
83 4
     * @type {Database}
84 4
     */
85 4
    this.database = database;
86 4
    /**
87 4
     * The name of this table.
88 4
     * @name Table#name
89 4
     * @type {string}
90 4
     */
91 4
    this.name = name;
92 4
  }
93 4
  create(
94 4
    schema: Schema,
95 4
    gaxOptions?: CallOptions
96 4
  ): Promise<CreateTableResponse>;
97 4
  create(schema: Schema, callback: CreateTableCallback): void;
98 4
  create(
99 4
    schema: Schema,
100 4
    gaxOptions: CallOptions,
101 4
    callback: CreateTableCallback
102 4
  ): void;
103 4
  /**
104 4
   * Create a table.
105 4
   *
106 4
   * @param {string} schema See {@link Database#createTable}.
107 4
   * @param {CreateTableCallback} [callback] Callback function.
108 4
   * @returns {Promise<CreateTableResponse>}
109 4
   *
110 4
   * @example
111 4
   * const {Spanner} = require('@google-cloud/spanner');
112 4
   * const spanner = new Spanner();
113 4
   *
114 4
   * const instance = spanner.instance('my-instance');
115 4
   * const database = instance.database('my-database');
116 4
   * const table = database.table('Singers');
117 4
   *
118 4
   * const schema =
119 4
   *   'CREATE TABLE Singers (' +
120 4
   *   '  SingerId INT64 NOT NULL,' +
121 4
   *   '  FirstName STRING(1024),' +
122 4
   *   '  LastName STRING(1024),' +
123 4
   *   '  SingerInfo BYTES(MAX),' +
124 4
   *   ') PRIMARY KEY(SingerId)';
125 4
   *
126 4
   * table.create(schema, function(err, table, operation, apiResponse) {
127 4
   *   if (err) {
128 4
   *     // Error handling omitted.
129 4
   *   }
130 4
   *
131 4
   *   operation
132 4
   *     .on('error', function(err) {})
133 4
   *     .on('complete', function() {
134 4
   *       // Table created successfully.
135 4
   *     });
136 4
   * });
137 4
   *
138 4
   * //-
139 4
   * // If the callback is omitted, we'll return a Promise.
140 4
   * //-
141 4
   * table.create(schema)
142 4
   *   .then(function(data) {
143 4
   *     const table = data[0];
144 4
   *     const operation = data[1];
145 4
   *
146 4
   *     return operation.promise();
147 4
   *   })
148 4
   *   .then(function() {
149 4
   *     // Table created successfully.
150 4
   *   });
151 4
   */
152 4
  create(
153 4
    schema: Schema,
154 4
    gaxOptionsOrCallback?: CallOptions | CreateTableCallback,
155 4
    cb?: CreateTableCallback
156 4
  ): Promise<CreateTableResponse> | void {
157 4
    const gaxOptions =
158 4
      typeof gaxOptionsOrCallback === 'object' ? gaxOptionsOrCallback : {};
159 4
    const callback =
160 4
      typeof gaxOptionsOrCallback === 'function' ? gaxOptionsOrCallback : cb!;
161 4

162 4
    this.database.createTable(schema, gaxOptions, callback!);
163 4
  }
164 4
  /**
165 4
   * Create a readable object stream to receive rows from the database using key
166 4
   * lookups and scans.
167 4
   *
168 4
   * @see [StreamingRead API Documentation](https://cloud.google.com/spanner/docs/reference/rpc/google.spanner.v1#google.spanner.v1.Spanner.StreamingRead)
169 4
   * @see [ReadRequest API Documentation](https://cloud.google.com/spanner/docs/reference/rpc/google.spanner.v1#google.spanner.v1.ReadRequest)
170 4
   *
171 4
   * @param {ReadRequest} query Configuration object. See official
172 4
   *     [`ReadRequest`](https://cloud.google.com/spanner/docs/reference/rpc/google.spanner.v1#google.spanner.v1.ReadRequest).
173 4
   *     API documentation.
174 4
   * @param {TimestampBounds} [options] [Transaction options](https://cloud.google.com/spanner/docs/timestamp-bounds).
175 4
   * @returns {ReadableStream}
176 4
   *
177 4
   * @example
178 4
   * const {Spanner} = require('@google-cloud/spanner');
179 4
   * const spanner = new Spanner();
180 4
   *
181 4
   * const instance = spanner.instance('my-instance');
182 4
   * const database = instance.database('my-database');
183 4
   * const table = database.table('Singers');
184 4
   *
185 4
   * table.createReadStream({
186 4
   *     keys: ['1'],
187 4
   *     columns: ['SingerId', 'name']
188 4
   *   })
189 4
   *   .on('error', function(err) {})
190 4
   *   .on('data', function(row) {
191 4
   *     // row = {
192 4
   *     //   SingerId: '1',
193 4
   *     //   Name: 'Eddie Wilson'
194 4
   *     // }
195 4
   *   })
196 4
   *   .on('end', function() {
197 4
   *     // All results retrieved.
198 4
   *   });
199 4
   *
200 4
   * //-
201 4
   * // Provide an array for `query.keys` to read with a composite key.
202 4
   * //-
203 4
   * const query = {
204 4
   *   keys: [
205 4
   *     [
206 4
   *       'Id1',
207 4
   *       'Name1'
208 4
   *     ],
209 4
   *     [
210 4
   *       'Id2',
211 4
   *       'Name2'
212 4
   *     ]
213 4
   *   ],
214 4
   *   // ...
215 4
   * };
216 4
   *
217 4
   * //-
218 4
   * // If you anticipate many results, you can end a stream early to prevent
219 4
   * // unnecessary processing and API requests.
220 4
   * //-
221 4
   * table.createReadStream({
222 4
   *     keys: ['1'],
223 4
   *     columns: ['SingerId', 'name']
224 4
   *   })
225 4
   *   .on('data', function(row) {
226 4
   *     this.end();
227 4
   *   });
228 4
   */
229 4
  createReadStream(
230 4
    request: ReadRequest,
231 4
    options: TimestampBounds = {}
232 4
  ): PartialResultStream {
233 4
    const proxyStream = through.obj();
234 4

235 4
    this.database.getSnapshot(options, (err, snapshot) => {
236 4
      if (err) {
237 4
        proxyStream.destroy(err);
238 4
        return;
239 4
      }
240 4

241 4
      snapshot!
242 4
        .createReadStream(this.name, request)
243 4
        .on('error', err => {
244 4
          proxyStream.destroy(err);
245 4
          snapshot!.end();
246 4
        })
247 4
        .on('end', () => snapshot!.end())
248 4
        .pipe(proxyStream);
249 4
    });
250 4

251 4
    return proxyStream as PartialResultStream;
252 3
  }
253 4
  delete(gaxOptions?: CallOptions): Promise<DropTableResponse>;
254 4
  delete(callback: DropTableCallback): void;
255 4
  delete(gaxOptions: CallOptions, callback: DropTableCallback): void;
256 4
  /**
257 4
   * Delete the table. Not to be confused with {@link Table#deleteRows}.
258 4
   *
259 4
   * Wrapper around {@link Database#updateSchema}.
260 4
   *
261 4
   * @see {@link Database#updateSchema}
262 4
   *
263 4
   * @throws {TypeError} If any arguments are passed in.
264 4
   * @param {object} [gaxOptions] Request configuration options, outlined here:
265 4
   *     https://googleapis.github.io/gax-nodejs/classes/CallSettings.html.
266 4
   * @param {LongRunningOperationCallback} [callback] Callback function.
267 4
   * @returns {Promise<LongRunningOperationResponse>}
268 4
   *
269 4
   * @example
270 4
   * const {Spanner} = require('@google-cloud/spanner');
271 4
   * const spanner = new Spanner();
272 4
   *
273 4
   * const instance = spanner.instance('my-instance');
274 4
   * const database = instance.database('my-database');
275 4
   * const table = database.table('Singers');
276 4
   *
277 4
   * table.delete(function(err, operation, apiResponse) {
278 4
   *   if (err) {
279 4
   *     // Error handling omitted.
280 4
   *   }
281 4
   *
282 4
   *   operation
283 4
   *     .on('error', function(err) {})
284 4
   *     .on('complete', function() {
285 4
   *       // Table deleted successfully.
286 4
   *     });
287 4
   * });
288 4
   *
289 4
   * //-
290 4
   * // If the callback is omitted, we'll return a Promise.
291 4
   * //-
292 4
   * table.delete()
293 4
   *   .then(function(data) {
294 4
   *     const operation = data[0];
295 4
   *     return operation.promise();
296 4
   *   })
297 4
   *   .then(function() {
298 4
   *     // Table deleted successfully.
299 4
   *   });
300 4
   */
301 4
  delete(
302 4
    gaxOptionsOrCallback?: CallOptions | DropTableCallback,
303 4
    cb?: DropTableCallback
304 4
  ): Promise<DropTableResponse> | void {
305 4
    const gaxOptions =
306 4
      typeof gaxOptionsOrCallback === 'object' ? gaxOptionsOrCallback : {};
307 4
    const callback =
308 4
      typeof gaxOptionsOrCallback === 'function' ? gaxOptionsOrCallback : cb!;
309 4

310 4
    return this.database.updateSchema(
311 4
      'DROP TABLE `' + this.name + '`',
312 4
      gaxOptions,
313 4
      callback!
314 4
    );
315 4
  }
316 4
  deleteRows(
317 4
    keys: Key[],
318 4
    gaxOptions?: CallOptions
319 4
  ): Promise<DeleteRowsResponse>;
320 4
  deleteRows(keys: Key[], callback: DeleteRowsCallback): void;
321 4
  deleteRows(
322 4
    keys: Key[],
323 4
    gaxOptions: CallOptions,
324 4
    callback: DeleteRowsCallback
325 4
  ): void;
326 4
  /**
327 4
   * Delete rows from this table.
328 4
   *
329 4
   * @see [Commit API Documentation](https://cloud.google.com/spanner/docs/reference/rpc/google.spanner.v1#google.spanner.v1.Spanner.Commit)
330 4
   *
331 4
   * @param {array} keys The keys for the rows to delete. If using a
332 4
   *     composite key, provide an array within this array. See the example
333 4
   * below.
334 4
   * @param {object} [gaxOptions] Request configuration options, outlined here:
335 4
   *     https://googleapis.github.io/gax-nodejs/classes/CallSettings.html.
336 4
   * @param {BasicCallback} [callback] Callback function.
337 4
   * @returns {Promise<BasicResponse>}
338 4
   *
339 4
   * @example
340 4
   * const {Spanner} = require('@google-cloud/spanner');
341 4
   * const spanner = new Spanner();
342 4
   *
343 4
   * const instance = spanner.instance('my-instance');
344 4
   * const database = instance.database('my-database');
345 4
   * const table = database.table('Singers');
346 4
   *
347 4
   * const keys = ['Id1', 'Id2', 'Id3'];
348 4
   *
349 4
   * table.deleteRows(keys, function(err, apiResponse) {});
350 4
   *
351 4
   * //-
352 4
   * // Provide an array for `keys` to delete rows with a composite key.
353 4
   * //-
354 4
   * const keys = [
355 4
   *   [
356 4
   *     'Id1',
357 4
   *     'Name1'
358 4
   *   ],
359 4
   *   [
360 4
   *     'Id2',
361 4
   *     'Name2'
362 4
   *   ]
363 4
   * ];
364 4
   *
365 4
   * //-
366 4
   * // If the callback is omitted, we'll return a Promise.
367 4
   * //-
368 4
   * table.deleteRows(keys)
369 4
   *   .then(function(data) {
370 4
   *     const apiResponse = data[0];
371 4
   *   });
372 4
   */
373 4
  deleteRows(
374 4
    keys: Key[],
375 4
    gaxOptionsOrCallback?: CallOptions | DeleteRowsCallback,
376 4
    cb?: DeleteRowsCallback
377 4
  ): Promise<DeleteRowsResponse> | void {
378 4
    const gaxOptions =
379 4
      typeof gaxOptionsOrCallback === 'object' ? gaxOptionsOrCallback : {};
380 4
    const callback =
381 4
      typeof gaxOptionsOrCallback === 'function' ? gaxOptionsOrCallback : cb!;
382 4

383 4
    return this._mutate('deleteRows', keys, gaxOptions, callback!);
384 4
  }
385 4
  drop(gaxOptions?: CallOptions): Promise<DropTableResponse>;
386 4
  drop(callback: DropTableCallback): void;
387 4
  drop(gaxOptions: CallOptions, callback: DropTableCallback): void;
388 4
  /**
389 4
   * Drop the table.
390 4
   *
391 4
   * @see {@link Table#delete}
392 4
   * @see {@link Database#updateSchema}
393 4
   *
394 4
   * @param {object} [gaxOptions] Request configuration options, outlined here:
395 4
   *     https://googleapis.github.io/gax-nodejs/classes/CallSettings.html.
396 4
   * @param {LongRunningOperationCallback} [callback] Callback function.
397 4
   * @returns {Promise<LongRunningOperationResponse>}
398 4
   *
399 4
   * @example
400 4
   * const {Spanner} = require('@google-cloud/spanner');
401 4
   * const spanner = new Spanner();
402 4
   *
403 4
   * const instance = spanner.instance('my-instance');
404 4
   * const database = instance.database('my-database');
405 4
   * const table = database.table('Singers');
406 4
   *
407 4
   * table.drop(function(err, operation, apiResponse) {
408 4
   *   if (err) {
409 4
   *     // Error handling omitted.
410 4
   *   }
411 4
   *
412 4
   *   operation
413 4
   *     .on('error', function(err) {})
414 4
   *     .on('complete', function() {
415 4
   *       // Table dropped successfully.
416 4
   *     });
417 4
   * });
418 4
   *
419 4
   * //-
420 4
   * // If the callback is omitted, we'll return a Promise.
421 4
   * //-
422 4
   * table.drop()
423 4
   *   .then(function(data) {
424 4
   *     const operation = data[0];
425 4
   *     return operation.promise();
426 4
   *   })
427 4
   *   .then(function() {
428 4
   *     // Table dropped successfully.
429 4
   *   });
430 4
   */
431 4
  drop(
432 4
    gaxOptionsOrCallback?: CallOptions | DropTableCallback,
433 4
    cb?: DropTableCallback
434 4
  ): Promise<DropTableResponse> | void {
435 4
    const gaxOptions =
436 4
      typeof gaxOptionsOrCallback === 'object' ? gaxOptionsOrCallback : {};
437 4
    const callback =
438 4
      typeof gaxOptionsOrCallback === 'function' ? gaxOptionsOrCallback : cb!;
439 4

440 4
    return this.delete(gaxOptions, callback!);
441 4
  }
442 4
  insert(
443 4
    rows: object | object[],
444 4
    gaxOptions?: CallOptions
445 4
  ): Promise<InsertRowsResponse>;
446 4
  insert(rows: object | object[], callback: InsertRowsCallback): void;
447 4
  insert(
448 4
    rows: object | object[],
449 4
    gaxOptions: CallOptions,
450 4
    callback: InsertRowsCallback
451 4
  ): void;
452 4
  /**
453 4
   * Insert rows of data into this table.
454 4
   *
455 4
   * @see [Commit API Documentation](https://cloud.google.com/spanner/docs/reference/rpc/google.spanner.v1#google.spanner.v1.Spanner.Commit)
456 4
   *
457 4
   * @param {object|object[]} rows A map of names to values of data to insert
458 4
   *     into this table.
459 4
   * @param {object} [gaxOptions] Request configuration options, outlined here:
460 4
   *     https://googleapis.github.io/gax-nodejs/classes/CallSettings.html.
461 4
   * @param {BasicCallback} [callback] Callback function.
462 4
   * @returns {Promise<BasicResponse>}
463 4
   *
464 4
   * @example
465 4
   * const {Spanner} = require('@google-cloud/spanner');
466 4
   * const spanner = new Spanner();
467 4
   *
468 4
   * const instance = spanner.instance('my-instance');
469 4
   * const database = instance.database('my-database');
470 4
   * const table = database.table('Singers');
471 4
   *
472 4
   * const row = {
473 4
   *   SingerId: 'Id3',
474 4
   *   Name: 'Eddie Wilson'
475 4
   * };
476 4
   *
477 4
   * table.insert(row, function(err, apiResponse) {
478 4
   *   if (err) {
479 4
   *     // Error handling omitted.
480 4
   *   }
481 4
   *
482 4
   *   // Rows inserted successfully.
483 4
   * });
484 4
   *
485 4
   * //-
486 4
   * // Multiple rows can be inserted at once.
487 4
   * //-
488 4
   * const row2 = {
489 4
   *   SingerId: 'Id3b',
490 4
   *   Name: 'Joe West'
491 4
   * };
492 4
   *
493 4
   * table.insert([
494 4
   *   row,
495 4
   *   row2
496 4
   * ], function(err, apiResponse) {});
497 4
   *
498 4
   * //-
499 4
   * // If the callback is omitted, we'll return a Promise.
500 4
   * //-
501 4
   * table.insert(row)
502 4
   *   .then(function(data) {
503 4
   *     const apiResponse = data[0];
504 4
   *   });
505 4
   *
506 4
   * @example <caption>include:samples/crud.js</caption>
507 4
   * region_tag:spanner_insert_data
508 4
   * Full example:
509 4
   */
510 4
  insert(
511 4
    rows: object | object[],
512 4
    gaxOptionsOrCallback?: CallOptions | InsertRowsCallback,
513 4
    cb?: InsertRowsCallback
514 4
  ): Promise<InsertRowsResponse> | void {
515 4
    const gaxOptions =
516 4
      typeof gaxOptionsOrCallback === 'object' ? gaxOptionsOrCallback : {};
517 4
    const callback =
518 4
      typeof gaxOptionsOrCallback === 'function' ? gaxOptionsOrCallback : cb!;
519 4

520 4
    this._mutate('insert', rows, gaxOptions, callback!);
521 4
  }
522 4
  read(request: ReadRequest, options?: TimestampBounds): Promise<ReadResponse>;
523 4
  read(request: ReadRequest, callback: ReadCallback): void;
524 4
  read(
525 4
    request: ReadRequest,
526 4
    options: TimestampBounds,
527 4
    callback: ReadCallback
528 4
  ): void;
529 4
  /**
530 4
   * Configuration object, describing what to read from the table.
531 4
   *
532 4
   * @typedef {object} TableReadRequestOptions
533 4
   * @property {string[]} columns The columns of the table to be returned for each
534 4
   *     row matching this query.
535 4
   * @property {string[]|string[][]} keys The primary keys of the rows in this table to be
536 4
   *     yielded. If using a composite key, provide an array within this array.
537 4
   *     See the example below.
538 4
   * @property {string} [index] The name of an index on the table.
539 4
   * @property {boolean} [json=false] Receive the rows as serialized objects. This
540 4
   *     is the equivalent of calling `toJSON()` on each row.
541 4
   * @property {object} [jsonOptions] Configuration options for the serialized
542 4
   *     objects.
543 4
   * @property {boolean} [jsonOptions.wrapNumbers=false] Protect large integer
544 4
   *     values outside of the range of JavaScript Number.
545 4
   * @property {object} [keySet] Defines a collection of keys and/or key ranges to
546 4
   *     read.
547 4
   * @property {number} [limit] The number of rows to yield.
548 4
   */
549 4
  /**
550 4
   * @typedef {array} TableReadResponse
551 4
   * @property {array[]} 1 Rows are returned as an array of object arrays. Each
552 4
   *     object has a `name` and `value` property. To get a serialized object,
553 4
   *     call `toJSON()`. Optionally, provide an options object to `toJSON()`
554 4
   *     specifying `wrapNumbers: true` to protect large integer values outside
555 4
   * of the range of JavaScript Number. If set, FLOAT64 values will be returned
556 4
   *     as {@link Spanner.Float} objects and INT64 values as {@link
557 4
   * Spanner.Int}.
558 4
   */
559 4
  /**
560 4
   * @callback TableReadCallback
561 4
   * @param {?Error} err Request error, if any.
562 4
   * @param {array[]} rows Rows are returned as an array of object arrays. Each
563 4
   *     object has a `name` and `value` property. To get a serialized object,
564 4
   *     call `toJSON()`. Optionally, provide an options object to `toJSON()`
565 4
   *     specifying `wrapNumbers: true` to protect large integer values outside
566 4
   * of the range of JavaScript Number. If set, FLOAT64 values will be returned
567 4
   *     as {@link Spanner.Float} objects and INT64 values as {@link
568 4
   * Spanner.Int}.
569 4
   */
570 4
  /**
571 4
   * Receive rows from the database using key lookups and scans.
572 4
   *
573 4
   * **Performance Considerations:**
574 4
   *
575 4
   * This method wraps the streaming method,
576 4
   * {@link Table#createReadStream} for your convenience. All rows will
577 4
   * be stored in memory before being released to your callback. If you intend
578 4
   * on receiving a lot of results from your query, consider using the streaming
579 4
   * method, so you can free each result from memory after consuming it.
580 4
   *
581 4
   * @param {ReadRequest} query Configuration object, describing
582 4
   *     what to read from the table.
583 4
   * @param {TimestampBounds} options [Transaction options](https://cloud.google.com/spanner/docs/timestamp-bounds).
584 4
   * @param {TableReadCallback} [callback] Callback function.
585 4
   * @returns {Promise<TableReadResponse>}
586 4
   *
587 4
   * @example
588 4
   * const {Spanner} = require('@google-cloud/spanner');
589 4
   * const spanner = new Spanner();
590 4
   *
591 4
   * const instance = spanner.instance('my-instance');
592 4
   * const database = instance.database('my-database');
593 4
   * const table = database.table('Singers');
594 4
   *
595 4
   * const query = {
596 4
   *   keys: ['1'],
597 4
   *   columns: ['SingerId', 'name']
598 4
   * };
599 4
   *
600 4
   * table.read(query, function(err, rows) {
601 4
   *   if (err) {
602 4
   *     // Error handling omitted.
603 4
   *   }
604 4
   *
605 4
   *   const firstRow = rows[0];
606 4
   *
607 4
   *   // firstRow = [
608 4
   *   //   {
609 4
   *   //     name: 'SingerId',
610 4
   *   //     value: '1'
611 4
   *   //   },
612 4
   *   //   {
613 4
   *   //     name: 'Name',
614 4
   *   //     value: 'Eddie Wilson'
615 4
   *   //   }
616 4
   *   // ]
617 4
   * });
618 4
   *
619 4
   * //-
620 4
   * // Provide an array for `query.keys` to read with a composite key.
621 4
   * //-
622 4
   * const query = {
623 4
   *   keys: [
624 4
   *     [
625 4
   *       'Id1',
626 4
   *       'Name1'
627 4
   *     ],
628 4
   *     [
629 4
   *       'Id2',
630 4
   *       'Name2'
631 4
   *     ]
632 4
   *   ],
633 4
   *   // ...
634 4
   * };
635 4
   *
636 4
   * //-
637 4
   * // Rows are returned as an array of object arrays. Each object has a `name`
638 4
   * // and `value` property. To get a serialized object, call `toJSON()`.
639 4
   * //
640 4
   * // Alternatively, set `query.json` to `true`, and this step will be
641 4
   * performed
642 4
   * // automatically.
643 4
   * //-
644 4
   * table.read(query, function(err, rows) {
645 4
   *   if (err) {
646 4
   *     // Error handling omitted.
647 4
   *   }
648 4
   *
649 4
   *   const firstRow = rows[0];
650 4
   *
651 4
   *   // firstRow.toJSON() = {
652 4
   *   //   SingerId: '1',
653 4
   *   //   Name: 'Eddie Wilson'
654 4
   *   // }
655 4
   * });
656 4
   *
657 4
   * //-
658 4
   * // If the callback is omitted, we'll return a Promise.
659 4
   * //-
660 4
   * table.read(query)
661 4
   *   .then(function(data) {
662 4
   *     const rows = data[0];
663 4
   *   });
664 4
   *
665 4
   * @example <caption>include:samples/crud.js</caption>
666 4
   * region_tag:spanner_read_data
667 4
   * Full example:
668 4
   *
669 4
   * @example <caption>include:samples/crud.js</caption>
670 4
   * region_tag:spanner_read_stale_data
671 4
   * Reading stale data:
672 4
   *
673 4
   * @example <caption>include:samples/indexing.js</caption>
674 4
   * region_tag:spanner_read_data_with_index
675 4
   * Reading data using an index:
676 4
   *
677 4
   * @example <caption>include:samples/indexing.js</caption>
678 4
   * region_tag:spanner_read_data_with_storing_index
679 4
   * Reading data using a storing index:
680 4
   */
681 4
  read(
682 4
    request: ReadRequest,
683 4
    optionsOrCallback?: TimestampBounds | ReadCallback,
684 4
    cb?: ReadCallback
685 4
  ): Promise<ReadResponse> | void {
686 4
    const rows: Row[] = [];
687 4

688 4
    const callback =
689 4
      typeof optionsOrCallback === 'function' ? optionsOrCallback : cb;
690 4
    const options =
691 4
      typeof optionsOrCallback === 'object'
692 4
        ? (optionsOrCallback as TimestampBounds)
693 4
        : {};
694 4

695 4
    this.createReadStream(request, options)
696 4
      .on('error', callback!)
697 4
      .on('data', (row: Row) => rows.push(row))
698 4
      .on('end', () => callback!(null, rows));
699 4
  }
700 4
  replace(
701 4
    rows: object | object[],
702 4
    gaxOptions?: CallOptions
703 4
  ): Promise<ReplaceRowsResponse>;
704 4
  replace(rows: object | object[], callback: ReplaceRowsCallback): void;
705 4
  replace(
706 4
    rows: object | object[],
707 4
    gaxOptions: CallOptions,
708 4
    callback: ReplaceRowsCallback
709 4
  ): void;
710 4
  /**
711 4
   * Replace rows of data within this table.
712 4
   *
713 4
   * @see [Commit API Documentation](https://cloud.google.com/spanner/docs/reference/rpc/google.spanner.v1#google.spanner.v1.Spanner.Commit)
714 4
   *
715 4
   * @param {object|object[]} rows A map of names to values of data to insert
716 4
   *     into this table.
717 4
   * @param {object} [gaxOptions] Request configuration options, outlined here:
718 4
   *     https://googleapis.github.io/gax-nodejs/classes/CallSettings.html.
719 4
   * @param {BasicCallback} [callback] Callback function.
720 4
   * @returns {Promise<BasicResponse>}
721 4
   *
722 4
   * @example
723 4
   * const {Spanner} = require('@google-cloud/spanner');
724 4
   * const spanner = new Spanner();
725 4
   *
726 4
   * const instance = spanner.instance('my-instance');
727 4
   * const database = instance.database('my-database');
728 4
   * const table = database.table('Singers');
729 4
   *
730 4
   * const row = {
731 4
   *   SingerId: 'Id3',
732 4
   *   Name: 'Joe West'
733 4
   * };
734 4
   *
735 4
   * table.replace(row, function(err, apiResponse) {
736 4
   *   if (err) {
737 4
   *     // Error handling omitted.
738 4
   *   }
739 4
   *
740 4
   *   // Row replaced successfully.
741 4
   * });
742 4
   *
743 4
   * //-
744 4
   * // If the callback is omitted, we'll return a Promise.
745 4
   * //-
746 4
   * table.replace(row)
747 4
   *   .then(function(data) {
748 4
   *     const apiResponse = data[0];
749 4
   *   });
750 4
   */
751 4
  replace(
752 4
    rows: object | object[],
753 4
    gaxOptionsOrCallback?: CallOptions | ReplaceRowsCallback,
754 4
    cb?: ReplaceRowsCallback
755 4
  ): Promise<ReplaceRowsResponse> | void {
756 4
    const gaxOptions =
757 4
      typeof gaxOptionsOrCallback === 'object' ? gaxOptionsOrCallback : {};
758 4
    const callback =
759 4
      typeof gaxOptionsOrCallback === 'function' ? gaxOptionsOrCallback : cb!;
760 4

761 4
    this._mutate('replace', rows, gaxOptions, callback!);
762 4
  }
763 4
  update(
764 4
    rows: object | object[],
765 4
    gaxOptions?: CallOptions
766 4
  ): Promise<UpdateRowsResponse>;
767 4
  update(rows: object | object[], callback: UpdateRowsCallback): void;
768 4
  update(
769 4
    rows: object | object[],
770 4
    gaxOptions: CallOptions,
771 4
    callback: UpdateRowsCallback
772 4
  ): void;
773 4
  /**
774 4
   * Update rows of data within this table.
775 4
   *
776 4
   * @see [Commit API Documentation](https://cloud.google.com/spanner/docs/reference/rpc/google.spanner.v1#google.spanner.v1.Spanner.Commit)
777 4
   *
778 4
   * @param {object|object[]} rows A map of names to values of data to insert
779 4
   *     into this table.
780 4
   * @param {object} [gaxOptions] Request configuration options, outlined here:
781 4
   *     https://googleapis.github.io/gax-nodejs/classes/CallSettings.html.
782 4
   * @param {BasicCallback} [callback] Callback function.
783 4
   * @returns {Promise<BasicResponse>}
784 4
   *
785 4
   * @example
786 4
   * const {Spanner} = require('@google-cloud/spanner');
787 4
   * const spanner = new Spanner();
788 4
   *
789 4
   * const instance = spanner.instance('my-instance');
790 4
   * const database = instance.database('my-database');
791 4
   * const table = database.table('Singers');
792 4
   *
793 4
   * const row = {
794 4
   *   SingerId: 'Id3',
795 4
   *   Name: 'Joe West'
796 4
   * };
797 4
   *
798 4
   * table.update(row, function(err, apiResponse) {
799 4
   *   if (err) {
800 4
   *     // Error handling omitted.
801 4
   *   }
802 4
   *
803 4
   *   // Row updated successfully.
804 4
   * });
805 4
   *
806 4
   * //-
807 4
   * // If the callback is omitted, we'll return a Promise.
808 4
   * //-
809 4
   * table.update(row)
810 4
   *   .then(function(data) {
811 4
   *     const apiResponse = data[0];
812 4
   *   });
813 4
   *
814 4
   * @example <caption>include:samples/crud.js</caption>
815 4
   * region_tag:spanner_update_data
816 4
   * Full example:
817 4
   */
818 4
  update(
819 4
    rows: object | object[],
820 4
    gaxOptionsOrCallback?: CallOptions | UpdateRowsCallback,
821 4
    cb?: UpdateRowsCallback
822 4
  ): Promise<UpdateRowsResponse> | void {
823 4
    const gaxOptions =
824 4
      typeof gaxOptionsOrCallback === 'object' ? gaxOptionsOrCallback : {};
825 4
    const callback =
826 4
      typeof gaxOptionsOrCallback === 'function' ? gaxOptionsOrCallback : cb!;
827 4

828 4
    this._mutate('update', rows, gaxOptions, callback!);
829 4
  }
830 4
  upsert(
831 4
    rows: object | object[],
832 4
    gaxOptions?: CallOptions
833 4
  ): Promise<UpsertRowsResponse>;
834 4
  upsert(rows: object | object[], callback: UpsertRowsCallback): void;
835 4
  upsert(
836 4
    rows: object | object[],
837 4
    gaxOptions: CallOptions,
838 4
    callback: UpsertRowsCallback
839 4
  ): void;
840 4
  /**
841 4
   * Insert or update rows of data within this table.
842 4
   *
843 4
   * @see [Commit API Documentation](https://cloud.google.com/spanner/docs/reference/rpc/google.spanner.v1#google.spanner.v1.Spanner.Commit)
844 4
   *
845 4
   * @param {object|object[]} rows A map of names to values of data to insert
846 4
   *     into this table.
847 4
   *
848 4
   * @param {object} [gaxOptions] Request configuration options, outlined here:
849 4
   *     https://googleapis.github.io/gax-nodejs/classes/CallSettings.html.
850 4
   * @param {BasicCallback} [callback] Callback function.
851 4
   * @returns {Promise<BasicResponse>}
852 4
   *
853 4
   * @example
854 4
   * const {Spanner} = require('@google-cloud/spanner');
855 4
   * const spanner = new Spanner();
856 4
   *
857 4
   * const instance = spanner.instance('my-instance');
858 4
   * const database = instance.database('my-database');
859 4
   * const table = database.table('Singers');
860 4
   *
861 4
   * const row = {
862 4
   *   SingerId: 'Id3',
863 4
   *   Name: 'Joe West'
864 4
   * };
865 4
   *
866 4
   * table.upsert(row, function(err, apiResponse) {
867 4
   *   if (err) {
868 4
   *     // Error handling omitted.
869 4
   *   }
870 4
   *
871 4
   *   // Row inserted or updated successfully.
872 4
   * });
873 4
   *
874 4
   * //-
875 4
   * // If the callback is omitted, we'll return a Promise.
876 4
   * //-
877 4
   * table.upsert(row)
878 4
   *   .then(function(data) {
879 4
   *     const apiResponse = data[0];
880 4
   *   });
881 4
   */
882 4
  upsert(
883 4
    rows: object | object[],
884 4
    gaxOptionsOrCallback?: CallOptions | UpsertRowsCallback,
885 4
    cb?: UpsertRowsCallback
886 4
  ): Promise<UpsertRowsResponse> | void {
887 4
    const gaxOptions =
888 4
      typeof gaxOptionsOrCallback === 'object' ? gaxOptionsOrCallback : {};
889 4
    const callback =
890 4
      typeof gaxOptionsOrCallback === 'function' ? gaxOptionsOrCallback : cb!;
891 4

892 4
    this._mutate('upsert', rows, gaxOptions, callback!);
893 4
  }
894 4
  /**
895 4
   * Creates a new transaction and applies the desired mutation via
896 4
   * {@link Transaction#commit}.
897 4
   *
898 4
   * @see [Commit API Documentation](https://cloud.google.com/spanner/docs/reference/rpc/google.spanner.v1#google.spanner.v1.Spanner.Commit)
899 4
   *
900 4
   * @private
901 4
   *
902 4
   * @param {string} method CRUD method (insert, update, etc.).
903 4
   * @param {object|object[]} rows A map of names to values of data to insert
904 4
   *     into this table.
905 4
   * @param {function} callback The callback function.
906 4
   */
907 4
  private _mutate(
908 4
    method: 'deleteRows' | 'insert' | 'replace' | 'update' | 'upsert',
909 4
    rows: object | object[],
910 4
    gaxOptions: CallOptions = {},
911 4
    callback: CommitCallback
912 4
  ): void {
913 4
    this.database.runTransaction((err, transaction) => {
914 4
      if (err) {
915 4
        callback(err);
916 4
        return;
917 4
      }
918 4

919 4
      transaction![method](this.name, rows as Key[]);
920 4
      transaction!.commit(gaxOptions, callback);
921 4
    });
922 4
  }
923 4
}
924 4

925 4
/*! Developer Documentation
926 4
 *
927 4
 * All async methods (except for streams) will return a Promise in the event
928 4
 * that a callback is omitted.
929 4
 */
930 4
promisifyAll(Table, {
931 4
  exclude: ['delete', 'drop'],
932 4
});
933 4

934 4
/**
935 4
 * Reference to the {@link Table} class.
936 4
 * @name module:@google-cloud/spanner.Table
937 4
 * @see Table
938 4
 */
939 4
export {Table};

Read our documentation on viewing source code .

Loading