From 5de854b7d99cb81e7a87363f933404cefea9986f Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Fri, 8 Mar 2024 18:33:23 +0530 Subject: [PATCH 01/34] feat(spanner): add support for float32 --- src/codec.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/codec.ts b/src/codec.ts index ac018b310..40c96a924 100644 --- a/src/codec.ts +++ b/src/codec.ts @@ -377,6 +377,10 @@ function decode(value: Value, type: spannerClient.spanner.v1.Type): Value { case 'BYTES': decoded = Buffer.from(decoded, 'base64'); break; + case spannerClient.spanner.v1.TypeCode.FLOAT32: + case 'FLOAT32': + decoded = new Float(decoded); + break; case spannerClient.spanner.v1.TypeCode.FLOAT64: case 'FLOAT64': decoded = new Float(decoded); @@ -531,6 +535,7 @@ const TypeCode: { bool: 'BOOL', int64: 'INT64', pgOid: 'INT64', + float32: 'FLOAT32', float64: 'FLOAT64', numeric: 'NUMERIC', pgNumeric: 'NUMERIC', From 348e965a812d3691baa0a5e96ee4149bd7e4eeb4 Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Tue, 12 Mar 2024 12:54:17 +0530 Subject: [PATCH 02/34] refactor: codec.ts --- src/codec.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/codec.ts b/src/codec.ts index 40c96a924..48d3b2030 100644 --- a/src/codec.ts +++ b/src/codec.ts @@ -607,7 +607,13 @@ function getType(value: Value): Type { is.infinite(value) || (is.number(value) && isNaN(value)); if (is.decimal(value) || isSpecialNumber || value instanceof Float) { - return {type: 'float64'}; + if (value.valueOf() % 1!=0) { + if (Float32Array.of(value).length === 1) { + return {type: 'float32'}; + } else if (Float64Array.of(value).length === 1) { + return {type: 'float64'}; + } + } } if (is.number(value) || value instanceof Int) { From a1d57a6ca09f46d04320c91bf083d8ba10fccb34 Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Tue, 12 Mar 2024 12:54:17 +0530 Subject: [PATCH 03/34] refactor: codec.ts --- samples/archived/datatypes.js | 68 +++++++++++++++++++++++++++++++++++ samples/datatypes.js | 68 +++++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+) diff --git a/samples/archived/datatypes.js b/samples/archived/datatypes.js index c3d8acdac..47ae834a1 100644 --- a/samples/archived/datatypes.js +++ b/samples/archived/datatypes.js @@ -44,6 +44,7 @@ async function createVenuesTable(instanceId, databaseId, projectId) { AvailableDates ARRAY, LastContactDate Date, OutdoorVenue BOOL, + RatingScore FLOAT32, PopularityScore FLOAT64, LastUpdateTime TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true) ) PRIMARY KEY (VenueId)`, @@ -101,6 +102,7 @@ async function insertData(instanceId, databaseId, projectId) { AvailableDates: availableDates1, LastContactDate: '2018-09-02', OutdoorVenue: false, + RatingScore: Spanner.float(0.90432), PopularityScore: Spanner.float(0.85543), LastUpdateTime: 'spanner.commit_timestamp()', }, @@ -112,6 +114,7 @@ async function insertData(instanceId, databaseId, projectId) { AvailableDates: availableDates2, LastContactDate: '2019-01-15', OutdoorVenue: true, + RatingScore: Spanner.float(0.93081), PopularityScore: Spanner.float(0.98716), LastUpdateTime: 'spanner.commit_timestamp()', }, @@ -123,6 +126,7 @@ async function insertData(instanceId, databaseId, projectId) { AvailableDates: availableDates3, LastContactDate: '2018-10-01', OutdoorVenue: false, + RatingScore: Spanner.float(0.98738), PopularityScore: Spanner.float(0.72598), LastUpdateTime: 'spanner.commit_timestamp()', }, @@ -141,6 +145,64 @@ async function insertData(instanceId, databaseId, projectId) { // [END spanner_insert_datatypes_data] } +async function queryWithFloat32(instanceId, databaseId, projectId) { + // [START spanner_query_with_float_parameter] + // Imports the Google Cloud client library. + const {Spanner} = require('@google-cloud/spanner'); + + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // const projectId = 'my-project-id'; + // const instanceId = 'my-instance'; + // const databaseId = 'my-database'; + + // Creates a client + const spanner = new Spanner({ + projectId: projectId, + }); + + // Gets a reference to a Cloud Spanner instance and database. + const instance = spanner.instance(instanceId); + const database = instance.database(databaseId); + + const fieldType = { + type: 'float32', + }; + + const exampleFloat = Spanner.float(0.9); + + const query = { + sql: `SELECT VenueId, VenueName, RatingScore FROM Venues + WHERE RatingScore > @ratingScore`, + params: { + ratingScore: exampleFloat, + }, + types: { + ratingScore: fieldType, + }, + }; + + // Queries rows from the Venues table. + try { + const [rows] = await database.run(query); + + rows.forEach(row => { + const json = row.toJSON(); + console.log( + `VenueId: ${json.VenueId}, VenueName: ${json.VenueName},` + + ` RatingScore: ${json.PopularityScore}` + ); + }); + } catch (err) { + console.error('ERROR:', err); + } finally { + // Close the database when finished. + database.close(); + } + // [END spanner_query_with_float_parameter] +} + async function queryWithArray(instanceId, databaseId, projectId) { // [START spanner_query_with_array_parameter] // Imports the Google Cloud client library. @@ -654,6 +716,12 @@ require('yargs') {}, opts => queryWithDate(opts.instanceName, opts.databaseName, opts.projectId) ) + .command( + 'queryWithFloat32 ', + "Query data from the sample 'Venues' table with a FLOAT32 datatype.", + {}, + opts => queryWithFloat32(opts.instanceName, opts.databaseName, opts.projectId) + ) .command( 'queryWithFloat ', "Query data from the sample 'Venues' table with a FLOAT64 datatype.", diff --git a/samples/datatypes.js b/samples/datatypes.js index 4e9d89b37..8dd858fe7 100644 --- a/samples/datatypes.js +++ b/samples/datatypes.js @@ -43,6 +43,7 @@ async function createVenuesTable(instanceId, databaseId, projectId) { AvailableDates ARRAY, LastContactDate Date, OutdoorVenue BOOL, + RatingScore FLOAT32, PopularityScore FLOAT64, LastUpdateTime TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true) ) PRIMARY KEY (VenueId)`, @@ -107,6 +108,7 @@ async function insertData(instanceId, databaseId, projectId) { AvailableDates: availableDates1, LastContactDate: '2018-09-02', OutdoorVenue: false, + RatingScore: Spanner.float(0.90432), PopularityScore: Spanner.float(0.85543), LastUpdateTime: 'spanner.commit_timestamp()', }, @@ -118,6 +120,7 @@ async function insertData(instanceId, databaseId, projectId) { AvailableDates: availableDates2, LastContactDate: '2019-01-15', OutdoorVenue: true, + RatingScore: Spanner.float(0.93081), PopularityScore: Spanner.float(0.98716), LastUpdateTime: 'spanner.commit_timestamp()', }, @@ -129,6 +132,7 @@ async function insertData(instanceId, databaseId, projectId) { AvailableDates: availableDates3, LastContactDate: '2018-10-01', OutdoorVenue: false, + RatingScore: Spanner.float(0.98738), PopularityScore: Spanner.float(0.72598), LastUpdateTime: 'spanner.commit_timestamp()', }, @@ -384,6 +388,64 @@ async function queryWithDate(instanceId, databaseId, projectId) { // [END spanner_query_with_date_parameter] } +async function queryWithFloat32(instanceId, databaseId, projectId) { + // [START spanner_query_with_float_parameter] + // Imports the Google Cloud client library. + const {Spanner} = require('@google-cloud/spanner'); + + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // const projectId = 'my-project-id'; + // const instanceId = 'my-instance'; + // const databaseId = 'my-database'; + + // Creates a client + const spanner = new Spanner({ + projectId: projectId, + }); + + // Gets a reference to a Cloud Spanner instance and database. + const instance = spanner.instance(instanceId); + const database = instance.database(databaseId); + + const fieldType = { + type: 'float32', + }; + + const exampleFloat = Spanner.float(0.9); + + const query = { + sql: `SELECT VenueId, VenueName, RatingScore FROM Venues + WHERE RatingScore > @ratingScore`, + params: { + ratingScore: exampleFloat, + }, + types: { + ratingScore: fieldType, + }, + }; + + // Queries rows from the Venues table. + try { + const [rows] = await database.run(query); + + rows.forEach(row => { + const json = row.toJSON(); + console.log( + `VenueId: ${json.VenueId}, VenueName: ${json.VenueName},` + + ` RatingScore: ${json.PopularityScore}` + ); + }); + } catch (err) { + console.error('ERROR:', err); + } finally { + // Close the database when finished. + database.close(); + } + // [END spanner_query_with_float_parameter] +} + async function queryWithFloat(instanceId, databaseId, projectId) { // [START spanner_query_with_float_parameter] // Imports the Google Cloud client library. @@ -659,6 +721,12 @@ require('yargs') {}, opts => queryWithDate(opts.instanceName, opts.databaseName, opts.projectId) ) + .command( + 'queryWithFloat32 ', + "Query data from the sample 'Venues' table with a FLOAT32 datatype.", + {}, + opts => queryWithFloat32(opts.instanceName, opts.databaseName, opts.projectId) + ) .command( 'queryWithFloat ', "Query data from the sample 'Venues' table with a FLOAT64 datatype.", From 794f384a7023d00783cba32bc45656adbb6ef973 Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Tue, 12 Mar 2024 12:54:17 +0530 Subject: [PATCH 04/34] refactor: add sample to fetch float32 value from table --- samples/datatypes.js | 60 +------------------------------------------- src/codec.ts | 16 ++++++++++++ src/index.ts | 20 ++++++++++++++- 3 files changed, 36 insertions(+), 60 deletions(-) diff --git a/samples/datatypes.js b/samples/datatypes.js index 8dd858fe7..ec29c92db 100644 --- a/samples/datatypes.js +++ b/samples/datatypes.js @@ -387,65 +387,6 @@ async function queryWithDate(instanceId, databaseId, projectId) { } // [END spanner_query_with_date_parameter] } - -async function queryWithFloat32(instanceId, databaseId, projectId) { - // [START spanner_query_with_float_parameter] - // Imports the Google Cloud client library. - const {Spanner} = require('@google-cloud/spanner'); - - /** - * TODO(developer): Uncomment the following lines before running the sample. - */ - // const projectId = 'my-project-id'; - // const instanceId = 'my-instance'; - // const databaseId = 'my-database'; - - // Creates a client - const spanner = new Spanner({ - projectId: projectId, - }); - - // Gets a reference to a Cloud Spanner instance and database. - const instance = spanner.instance(instanceId); - const database = instance.database(databaseId); - - const fieldType = { - type: 'float32', - }; - - const exampleFloat = Spanner.float(0.9); - - const query = { - sql: `SELECT VenueId, VenueName, RatingScore FROM Venues - WHERE RatingScore > @ratingScore`, - params: { - ratingScore: exampleFloat, - }, - types: { - ratingScore: fieldType, - }, - }; - - // Queries rows from the Venues table. - try { - const [rows] = await database.run(query); - - rows.forEach(row => { - const json = row.toJSON(); - console.log( - `VenueId: ${json.VenueId}, VenueName: ${json.VenueName},` + - ` RatingScore: ${json.PopularityScore}` - ); - }); - } catch (err) { - console.error('ERROR:', err); - } finally { - // Close the database when finished. - database.close(); - } - // [END spanner_query_with_float_parameter] -} - async function queryWithFloat(instanceId, databaseId, projectId) { // [START spanner_query_with_float_parameter] // Imports the Google Cloud client library. @@ -814,6 +755,7 @@ require('yargs') .example('node $0 queryWithBool "my-instance" "my-database" "my-project-id"') .example('node $0 queryWithBytes "my-instance" "my-database" "my-project-id"') .example('node $0 queryWithDate "my-instance" "my-database" "my-project-id"') + .example('node $0 queryWithFloat32 "my-instance" "my-database" "my-project-id"') .example('node $0 queryWithFloat "my-instance" "my-database" "my-project-id"') .example('node $0 queryWithInt "my-instance" "my-database" "my-project-id"') .example( diff --git a/src/codec.ts b/src/codec.ts index 48d3b2030..84d27e6f1 100644 --- a/src/codec.ts +++ b/src/codec.ts @@ -118,6 +118,21 @@ abstract class WrappedNumber { abstract valueOf(): number; } +/** + * @typedef Float32 + * @see Spanner.float32 + */ +export class Float32 extends WrappedNumber { + value: number; + constructor(value: number) { + super(); + this.value = value; + } + valueOf(): number { + return Number(this.value); + } +} + /** * @typedef Float * @see Spanner.float @@ -791,6 +806,7 @@ export const codec = { convertProtoTimestampToDate, createTypeObject, SpannerDate, + Float32, Float, Int, Numeric, diff --git a/src/index.ts b/src/index.ts index eaa44f408..6ca8e2f69 100644 --- a/src/index.ts +++ b/src/index.ts @@ -26,6 +26,7 @@ import * as streamEvents from 'stream-events'; import * as through from 'through2'; import { codec, + Float32, Float, Int, Numeric, @@ -1671,6 +1672,22 @@ class Spanner extends GrpcService { return new PreciseDate(value as number); } + /** + * Helper function to get a Cloud Spanner Float32 object. + * + * @param {string|number} value The float as a number or string. + * @returns {Float} + * + * @example + * ``` + * const {Spanner} = require('@google-cloud/spanner'); + * const float = Spanner.float(10); + * ``` + */ + static float32(value): Float32 { + return new codec.Float32(value); + } + /** * Helper function to get a Cloud Spanner Float64 object. * @@ -1786,6 +1803,7 @@ class Spanner extends GrpcService { promisifyAll(Spanner, { exclude: [ 'date', + 'float32', 'float', 'instance', 'instanceConfig', @@ -1946,4 +1964,4 @@ import * as protos from '../protos/protos'; import IInstanceConfig = instanceAdmin.spanner.admin.instance.v1.IInstanceConfig; export {v1, protos}; export default {Spanner}; -export {Float, Int, Struct, Numeric, PGNumeric, SpannerDate}; +export {Float32, Float, Int, Struct, Numeric, PGNumeric, SpannerDate}; From a854b46a7c87aff858189918ba09d6985faf7f5f Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Thu, 14 Mar 2024 19:14:39 +0530 Subject: [PATCH 05/34] feat: add support for float32 --- samples/archived/datatypes.js | 68 ------------------------- samples/datatypes.js | 77 +++++++++++++++++++++++++---- samples/system-test/spanner.test.js | 19 +++++++ src/codec.ts | 2 +- 4 files changed, 88 insertions(+), 78 deletions(-) diff --git a/samples/archived/datatypes.js b/samples/archived/datatypes.js index 47ae834a1..c3d8acdac 100644 --- a/samples/archived/datatypes.js +++ b/samples/archived/datatypes.js @@ -44,7 +44,6 @@ async function createVenuesTable(instanceId, databaseId, projectId) { AvailableDates ARRAY, LastContactDate Date, OutdoorVenue BOOL, - RatingScore FLOAT32, PopularityScore FLOAT64, LastUpdateTime TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true) ) PRIMARY KEY (VenueId)`, @@ -102,7 +101,6 @@ async function insertData(instanceId, databaseId, projectId) { AvailableDates: availableDates1, LastContactDate: '2018-09-02', OutdoorVenue: false, - RatingScore: Spanner.float(0.90432), PopularityScore: Spanner.float(0.85543), LastUpdateTime: 'spanner.commit_timestamp()', }, @@ -114,7 +112,6 @@ async function insertData(instanceId, databaseId, projectId) { AvailableDates: availableDates2, LastContactDate: '2019-01-15', OutdoorVenue: true, - RatingScore: Spanner.float(0.93081), PopularityScore: Spanner.float(0.98716), LastUpdateTime: 'spanner.commit_timestamp()', }, @@ -126,7 +123,6 @@ async function insertData(instanceId, databaseId, projectId) { AvailableDates: availableDates3, LastContactDate: '2018-10-01', OutdoorVenue: false, - RatingScore: Spanner.float(0.98738), PopularityScore: Spanner.float(0.72598), LastUpdateTime: 'spanner.commit_timestamp()', }, @@ -145,64 +141,6 @@ async function insertData(instanceId, databaseId, projectId) { // [END spanner_insert_datatypes_data] } -async function queryWithFloat32(instanceId, databaseId, projectId) { - // [START spanner_query_with_float_parameter] - // Imports the Google Cloud client library. - const {Spanner} = require('@google-cloud/spanner'); - - /** - * TODO(developer): Uncomment the following lines before running the sample. - */ - // const projectId = 'my-project-id'; - // const instanceId = 'my-instance'; - // const databaseId = 'my-database'; - - // Creates a client - const spanner = new Spanner({ - projectId: projectId, - }); - - // Gets a reference to a Cloud Spanner instance and database. - const instance = spanner.instance(instanceId); - const database = instance.database(databaseId); - - const fieldType = { - type: 'float32', - }; - - const exampleFloat = Spanner.float(0.9); - - const query = { - sql: `SELECT VenueId, VenueName, RatingScore FROM Venues - WHERE RatingScore > @ratingScore`, - params: { - ratingScore: exampleFloat, - }, - types: { - ratingScore: fieldType, - }, - }; - - // Queries rows from the Venues table. - try { - const [rows] = await database.run(query); - - rows.forEach(row => { - const json = row.toJSON(); - console.log( - `VenueId: ${json.VenueId}, VenueName: ${json.VenueName},` + - ` RatingScore: ${json.PopularityScore}` - ); - }); - } catch (err) { - console.error('ERROR:', err); - } finally { - // Close the database when finished. - database.close(); - } - // [END spanner_query_with_float_parameter] -} - async function queryWithArray(instanceId, databaseId, projectId) { // [START spanner_query_with_array_parameter] // Imports the Google Cloud client library. @@ -716,12 +654,6 @@ require('yargs') {}, opts => queryWithDate(opts.instanceName, opts.databaseName, opts.projectId) ) - .command( - 'queryWithFloat32 ', - "Query data from the sample 'Venues' table with a FLOAT32 datatype.", - {}, - opts => queryWithFloat32(opts.instanceName, opts.databaseName, opts.projectId) - ) .command( 'queryWithFloat ', "Query data from the sample 'Venues' table with a FLOAT64 datatype.", diff --git a/samples/datatypes.js b/samples/datatypes.js index ec29c92db..423beda3d 100644 --- a/samples/datatypes.js +++ b/samples/datatypes.js @@ -108,7 +108,7 @@ async function insertData(instanceId, databaseId, projectId) { AvailableDates: availableDates1, LastContactDate: '2018-09-02', OutdoorVenue: false, - RatingScore: Spanner.float(0.90432), + RatingScore: Spanner.float32(0.90432), PopularityScore: Spanner.float(0.85543), LastUpdateTime: 'spanner.commit_timestamp()', }, @@ -120,7 +120,7 @@ async function insertData(instanceId, databaseId, projectId) { AvailableDates: availableDates2, LastContactDate: '2019-01-15', OutdoorVenue: true, - RatingScore: Spanner.float(0.93081), + RatingScore: Spanner.float32(0.93081), PopularityScore: Spanner.float(0.98716), LastUpdateTime: 'spanner.commit_timestamp()', }, @@ -132,7 +132,7 @@ async function insertData(instanceId, databaseId, projectId) { AvailableDates: availableDates3, LastContactDate: '2018-10-01', OutdoorVenue: false, - RatingScore: Spanner.float(0.98738), + RatingScore: Spanner.float32(0.98738), PopularityScore: Spanner.float(0.72598), LastUpdateTime: 'spanner.commit_timestamp()', }, @@ -387,6 +387,7 @@ async function queryWithDate(instanceId, databaseId, projectId) { } // [END spanner_query_with_date_parameter] } + async function queryWithFloat(instanceId, databaseId, projectId) { // [START spanner_query_with_float_parameter] // Imports the Google Cloud client library. @@ -445,6 +446,64 @@ async function queryWithFloat(instanceId, databaseId, projectId) { // [END spanner_query_with_float_parameter] } +async function queryWithFloat32(instanceId, databaseId, projectId) { + // [START spanner_query_with_float32_parameter] + // Imports the Google Cloud client library. + const {Spanner} = require('@google-cloud/spanner'); + + /** + * TODO(developer): Uncomment the following lines before running the sample. + */ + // const projectId = 'my-project-id'; + // const instanceId = 'my-instance'; + // const databaseId = 'my-database'; + + // Creates a client + const spanner = new Spanner({ + projectId: projectId, + }); + + // Gets a reference to a Cloud Spanner instance and database. + const instance = spanner.instance(instanceId); + const database = instance.database(databaseId); + + const fieldType = { + type: 'float32', + }; + + const exampleFloat = Spanner.float32(0.9); + + const query = { + sql: `SELECT VenueId, VenueName, RatingScore FROM Venues + WHERE RatingScore > @ratingScore`, + params: { + ratingScore: exampleFloat, + }, + types: { + ratingScore: fieldType, + }, + }; + + // Queries rows from the Venues table. + try { + const [rows] = await database.run(query); + + rows.forEach(row => { + const json = row.toJSON(); + console.log( + `VenueId: ${json.VenueId}, VenueName: ${json.VenueName},` + + ` RatingScore: ${json.RatingScore}` + ); + }); + } catch (err) { + console.error('ERROR:', err); + } finally { + // Close the database when finished. + database.close(); + } + // [END spanner_query_with_float32_parameter] +} + async function queryWithInt(instanceId, databaseId, projectId) { // [START spanner_query_with_int_parameter] // Imports the Google Cloud client library. @@ -662,18 +721,18 @@ require('yargs') {}, opts => queryWithDate(opts.instanceName, opts.databaseName, opts.projectId) ) - .command( - 'queryWithFloat32 ', - "Query data from the sample 'Venues' table with a FLOAT32 datatype.", - {}, - opts => queryWithFloat32(opts.instanceName, opts.databaseName, opts.projectId) - ) .command( 'queryWithFloat ', "Query data from the sample 'Venues' table with a FLOAT64 datatype.", {}, opts => queryWithFloat(opts.instanceName, opts.databaseName, opts.projectId) ) + .command( + 'queryWithFloat32 ', + "Query data from the sample 'Venues' table with a FLOAT32 datatype.", + {}, + opts => queryWithFloat32(opts.instanceName, opts.databaseName, opts.projectId) + ) .command( 'queryWithInt ', "Query data from the sample 'Venues' table with a INT64 datatype.", diff --git a/samples/system-test/spanner.test.js b/samples/system-test/spanner.test.js index 630aad8db..03181d31f 100644 --- a/samples/system-test/spanner.test.js +++ b/samples/system-test/spanner.test.js @@ -757,6 +757,25 @@ describe('Autogenerated Admin Clients', () => { ); }); + // query_with_float32_parameter + it('should use a FLOAT32 query parameter to query record from the Venues example table', async () => { + const output = execSync( + `${datatypesCmd} queryWithFloat32 ${INSTANCE_ID} ${DATABASE_ID} ${PROJECT_ID}` + ); + assert.match( + output, + /VenueId: 4, VenueName: Venue 4, RatingScore: 0.9/ + ); + assert.match( + output, + /VenueId: 19, VenueName: Venue 19, RatingScore: 0.9/ + ); + assert.match( + output, + /VenueId: 42, VenueName: Venue 42, RatingScore: 0.9/ + ); + }); + // query_with_int_parameter it('should use a INT64 query parameter to query record from the Venues example table', async () => { const output = execSync( diff --git a/src/codec.ts b/src/codec.ts index 84d27e6f1..6f52ad199 100644 --- a/src/codec.ts +++ b/src/codec.ts @@ -394,7 +394,7 @@ function decode(value: Value, type: spannerClient.spanner.v1.Type): Value { break; case spannerClient.spanner.v1.TypeCode.FLOAT32: case 'FLOAT32': - decoded = new Float(decoded); + decoded = new Float32(decoded); break; case spannerClient.spanner.v1.TypeCode.FLOAT64: case 'FLOAT64': From 0289e31464c81a91114217658e75e01fca317905 Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Thu, 14 Mar 2024 19:16:52 +0530 Subject: [PATCH 06/34] fix: lint errors --- samples/datatypes.js | 7 +++++-- samples/system-test/spanner.test.js | 15 +++------------ src/codec.ts | 8 +------- 3 files changed, 9 insertions(+), 21 deletions(-) diff --git a/samples/datatypes.js b/samples/datatypes.js index 423beda3d..9bb913bf5 100644 --- a/samples/datatypes.js +++ b/samples/datatypes.js @@ -731,7 +731,8 @@ require('yargs') 'queryWithFloat32 ', "Query data from the sample 'Venues' table with a FLOAT32 datatype.", {}, - opts => queryWithFloat32(opts.instanceName, opts.databaseName, opts.projectId) + opts => + queryWithFloat32(opts.instanceName, opts.databaseName, opts.projectId) ) .command( 'queryWithInt ', @@ -814,7 +815,9 @@ require('yargs') .example('node $0 queryWithBool "my-instance" "my-database" "my-project-id"') .example('node $0 queryWithBytes "my-instance" "my-database" "my-project-id"') .example('node $0 queryWithDate "my-instance" "my-database" "my-project-id"') - .example('node $0 queryWithFloat32 "my-instance" "my-database" "my-project-id"') + .example( + 'node $0 queryWithFloat32 "my-instance" "my-database" "my-project-id"' + ) .example('node $0 queryWithFloat "my-instance" "my-database" "my-project-id"') .example('node $0 queryWithInt "my-instance" "my-database" "my-project-id"') .example( diff --git a/samples/system-test/spanner.test.js b/samples/system-test/spanner.test.js index 03181d31f..56e919808 100644 --- a/samples/system-test/spanner.test.js +++ b/samples/system-test/spanner.test.js @@ -762,18 +762,9 @@ describe('Autogenerated Admin Clients', () => { const output = execSync( `${datatypesCmd} queryWithFloat32 ${INSTANCE_ID} ${DATABASE_ID} ${PROJECT_ID}` ); - assert.match( - output, - /VenueId: 4, VenueName: Venue 4, RatingScore: 0.9/ - ); - assert.match( - output, - /VenueId: 19, VenueName: Venue 19, RatingScore: 0.9/ - ); - assert.match( - output, - /VenueId: 42, VenueName: Venue 42, RatingScore: 0.9/ - ); + assert.match(output, /VenueId: 4, VenueName: Venue 4, RatingScore: 0.9/); + assert.match(output, /VenueId: 19, VenueName: Venue 19, RatingScore: 0.9/); + assert.match(output, /VenueId: 42, VenueName: Venue 42, RatingScore: 0.9/); }); // query_with_int_parameter diff --git a/src/codec.ts b/src/codec.ts index 6f52ad199..2b01cdd7a 100644 --- a/src/codec.ts +++ b/src/codec.ts @@ -622,13 +622,7 @@ function getType(value: Value): Type { is.infinite(value) || (is.number(value) && isNaN(value)); if (is.decimal(value) || isSpecialNumber || value instanceof Float) { - if (value.valueOf() % 1!=0) { - if (Float32Array.of(value).length === 1) { - return {type: 'float32'}; - } else if (Float64Array.of(value).length === 1) { - return {type: 'float64'}; - } - } + return {type: 'float64'}; } if (is.number(value) || value instanceof Int) { From 0adae714427dbf7b2861f7af88117936d20987ae Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Thu, 14 Mar 2024 21:55:55 +0530 Subject: [PATCH 07/34] fix: presubmit errors --- test/codec.ts | 17 +++++++++++++++++ test/index.ts | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/test/codec.ts b/test/codec.ts index b604e4354..cb3b1e859 100644 --- a/test/codec.ts +++ b/test/codec.ts @@ -163,6 +163,23 @@ describe('codec', () => { }); }); + describe('Float32', () => { + it('should store the value', () => { + const value = 8; + const float = new codec.Float32(value); + + assert.strictEqual(float.value, value); + }); + + it('should return as a float', () => { + const value = '8.2'; + const float = new codec.Float32(value); + + assert.strictEqual(float.valueOf(), Number(value)); + assert.strictEqual(float + 2, Number(value) + 2); + }); + }); + describe('Int', () => { it('should stringify the value', () => { const value = 8; diff --git a/test/index.ts b/test/index.ts index cd60bbbcd..4709fabb7 100644 --- a/test/index.ts +++ b/test/index.ts @@ -494,6 +494,23 @@ describe('Spanner', () => { }); }); + describe('float32', () => { + it('should create a Float32 instance', () => { + const value = {}; + const customValue = {}; + + fakeCodec.Float = class { + constructor(value_) { + assert.strictEqual(value_, value); + return customValue; + } + }; + + const float = Spanner.float32(value); + assert.strictEqual(float, customValue); + }); + }); + describe('int', () => { it('should create an Int instance', () => { const value = {}; From b3d0fffe50266b9141403cb162758c5ee7520eb2 Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Thu, 14 Mar 2024 22:33:22 +0530 Subject: [PATCH 08/34] fix: presubmit errors --- test/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/test/index.ts b/test/index.ts index 4709fabb7..2b6503963 100644 --- a/test/index.ts +++ b/test/index.ts @@ -82,6 +82,7 @@ const fakePfy = extend({}, pfy, { promisified = true; assert.deepStrictEqual(options.exclude, [ 'date', + 'float32', 'float', 'instance', 'instanceConfig', From d8b584db3f428a80d8eb550a1b4dd92275d0a05d Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Thu, 14 Mar 2024 22:33:22 +0530 Subject: [PATCH 09/34] fix: presubmit errors --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 6ca8e2f69..ecd566899 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1676,7 +1676,7 @@ class Spanner extends GrpcService { * Helper function to get a Cloud Spanner Float32 object. * * @param {string|number} value The float as a number or string. - * @returns {Float} + * @returns {Float32} * * @example * ``` From cfe2dfc9a18287915df46caf1b1ae27dc7dac311 Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Thu, 14 Mar 2024 22:33:22 +0530 Subject: [PATCH 10/34] fix: presubmit errors --- src/codec.ts | 1 + src/index.ts | 2 +- test/index.ts | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/codec.ts b/src/codec.ts index 2b01cdd7a..3a2230775 100644 --- a/src/codec.ts +++ b/src/codec.ts @@ -21,6 +21,7 @@ import * as is from 'is'; import {common as p} from 'protobufjs'; import {google as spannerClient} from '../protos/protos'; import {GoogleError} from 'google-gax'; +import { Spanner } from '.'; // eslint-disable-next-line @typescript-eslint/no-explicit-any export type Value = any; diff --git a/src/index.ts b/src/index.ts index ecd566899..62e3fc23d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1681,7 +1681,7 @@ class Spanner extends GrpcService { * @example * ``` * const {Spanner} = require('@google-cloud/spanner'); - * const float = Spanner.float(10); + * const float = Spanner.float32(10); * ``` */ static float32(value): Float32 { diff --git a/test/index.ts b/test/index.ts index 2b6503963..f1cf0f666 100644 --- a/test/index.ts +++ b/test/index.ts @@ -500,15 +500,15 @@ describe('Spanner', () => { const value = {}; const customValue = {}; - fakeCodec.Float = class { + fakeCodec.Float32 = class { constructor(value_) { assert.strictEqual(value_, value); return customValue; } }; - const float = Spanner.float32(value); - assert.strictEqual(float, customValue); + const float32 = Spanner.float32(value); + assert.strictEqual(float32, customValue); }); }); From b96f8a990a3941843fa1aada46044ee56fa24cc7 Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Fri, 15 Mar 2024 13:36:23 +0530 Subject: [PATCH 11/34] fix: lint errors --- src/codec.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/codec.ts b/src/codec.ts index 3a2230775..2b01cdd7a 100644 --- a/src/codec.ts +++ b/src/codec.ts @@ -21,7 +21,6 @@ import * as is from 'is'; import {common as p} from 'protobufjs'; import {google as spannerClient} from '../protos/protos'; import {GoogleError} from 'google-gax'; -import { Spanner } from '.'; // eslint-disable-next-line @typescript-eslint/no-explicit-any export type Value = any; From 736f7d9a82af6dd895796491be1f81d33c28b7df Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Mon, 18 Mar 2024 13:11:35 +0530 Subject: [PATCH 12/34] chore: add system-test for float32 --- system-test/spanner.ts | 232 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) diff --git a/system-test/spanner.ts b/system-test/spanner.ts index 6690b5a18..63baba7bc 100644 --- a/system-test/spanner.ts +++ b/system-test/spanner.ts @@ -403,6 +403,7 @@ describe('Spanner', () => { BytesArray ARRAY, BoolArray ARRAY, DateArray ARRAY< DATE >, + Float32Array ARRAY, FloatArray ARRAY, IntArray ARRAY, NumericArray ARRAY< NUMERIC >, @@ -431,6 +432,7 @@ describe('Spanner', () => { BytesArray ARRAY, BoolArray ARRAY, DateArray ARRAY< DATE >, + Float32Array ARRAY, FloatArray ARRAY, JsonArray ARRAY, IntArray ARRAY, @@ -459,6 +461,7 @@ describe('Spanner', () => { "BytesArray" BYTEA[], "BoolArray" BOOL[], "FloatArray" DOUBLE PRECISION[], + "Float32Array" DOUBLE PRECISION[], "IntArray" BIGINT[], "NumericArray" NUMERIC[], "StringArray" VARCHAR[], @@ -4863,6 +4866,235 @@ describe('Spanner', () => { }); }); + describe('float32', () => { + const float32Query = (done, database, query, value) => { + database.run(query, (err, rows) => { + assert.ifError(err); + let queriedValue = rows[0][0].value; + if (rows[0][0].value) { + queriedValue = rows[0][0].value.value; + } + assert.strictEqual(queriedValue, value); + done(); + }); + }; + + it('GOOGLE_STANDARD_SQL should bind the value', done => { + const query = { + sql: 'SELECT @v', + params: { + v: 2.2, + }, + }; + float32Query(done, DATABASE, query, 2.2); + }); + + it('POSTGRESQL should bind the value', function (done) { + if (IS_EMULATOR_ENABLED) { + this.skip(); + } + const query = { + sql: 'SELECT $1', + params: { + p1: 2.2, + }, + }; + float32Query(done, PG_DATABASE, query, 2.2); + }); + + it('GOOGLE_STANDARD_SQL should allow for null values', done => { + const query = { + sql: 'SELECT @v', + params: { + v: null, + }, + types: { + v: 'float64', + }, + }; + float32Query(done, DATABASE, query, null); + }); + + it('POSTGRESQL should allow for null values', function (done) { + if (IS_EMULATOR_ENABLED) { + this.skip(); + } + const query = { + sql: 'SELECT $1', + params: { + p1: null, + }, + types: { + p1: 'float64', + }, + }; + float32Query(done, PG_DATABASE, query, null); + }); + + it('GOOGLE_STANDARD_SQL should bind arrays', done => { + const values = [null, 1.1, 2.3, 3.5, null]; + + const query = { + sql: 'SELECT @v', + params: { + v: values, + }, + }; + + DATABASE.run(query, (err, rows) => { + assert.ifError(err); + + const expected = values.map(val => { + return is.number(val) ? {value: val} : val; + }); + + assert.strictEqual( + JSON.stringify(rows[0][0].value), + JSON.stringify(expected) + ); + done(); + }); + }); + + it('GOOGLE_STANDARD_SQL should bind empty arrays', done => { + const values = []; + + const query: ExecuteSqlRequest = { + sql: 'SELECT @v', + params: { + v: values, + }, + types: { + v: { + type: 'array', + child: 'float64', + }, + }, + }; + + DATABASE.run(query, (err, rows) => { + assert.ifError(err); + assert.deepStrictEqual(rows![0][0].value, values); + done(); + }); + }); + + it('GOOGLE_STANDARD_SQL should bind null arrays', done => { + const query: ExecuteSqlRequest = { + sql: 'SELECT @v', + params: { + v: null, + }, + types: { + v: { + type: 'array', + child: 'float64', + }, + }, + }; + + DATABASE.run(query, (err, rows) => { + assert.ifError(err); + assert.deepStrictEqual(rows![0][0].value, null); + done(); + }); + }); + + it('GOOGLE_STANDARD_SQL should bind Infinity', done => { + const query = { + sql: 'SELECT @v', + params: { + v: Infinity, + }, + }; + float32Query(done, DATABASE, query, 'Infinity'); + }); + + it('POSTGRESQL should bind Infinity', function (done) { + if (IS_EMULATOR_ENABLED) { + this.skip(); + } + const query = { + sql: 'SELECT $1', + params: { + p1: Infinity, + }, + }; + float32Query(done, PG_DATABASE, query, 'Infinity'); + }); + + it('GOOGLE_STANDARD_SQL should bind -Infinity', done => { + const query = { + sql: 'SELECT @v', + params: { + v: -Infinity, + }, + }; + float32Query(done, DATABASE, query, '-Infinity'); + }); + + it('POSTGRESQL should bind -Infinity', function (done) { + if (IS_EMULATOR_ENABLED) { + this.skip(); + } + const query = { + sql: 'SELECT $1', + params: { + p1: -Infinity, + }, + }; + float32Query(done, PG_DATABASE, query, '-Infinity'); + }); + + it('GOOGLE_STANDARD_SQL should bind NaN', done => { + const query = { + sql: 'SELECT @v', + params: { + v: NaN, + }, + }; + float32Query(done, DATABASE, query, 'NaN'); + }); + + it('POSTGRESQL should bind NaN', function (done) { + if (IS_EMULATOR_ENABLED) { + this.skip(); + } + const query = { + sql: 'SELECT $1', + params: { + p1: NaN, + }, + }; + float32Query(done, PG_DATABASE, query, 'NaN'); + }); + + it('GOOGLE_STANDARD_SQL should bind an array of Infinity and NaN', done => { + const values = [Infinity, -Infinity, NaN]; + + const query = { + sql: 'SELECT @v', + params: { + v: values, + }, + }; + + DATABASE.run(query, (err, rows) => { + assert.ifError(err); + + const expected = values.map(val => { + return is.number(val) ? {value: val + ''} : val; + }); + + assert.strictEqual( + JSON.stringify(rows[0][0].value), + JSON.stringify(expected) + ); + done(); + }); + }); + }); + describe('float64', () => { const float64Query = (done, database, query, value) => { database.run(query, (err, rows) => { From 8679cf578b3942b8dc6e186647e697a4235bed4e Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Mon, 18 Mar 2024 13:23:16 +0530 Subject: [PATCH 13/34] refactor: skip the integration test for float32 --- samples/system-test/spanner.test.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/samples/system-test/spanner.test.js b/samples/system-test/spanner.test.js index 56e919808..630aad8db 100644 --- a/samples/system-test/spanner.test.js +++ b/samples/system-test/spanner.test.js @@ -757,16 +757,6 @@ describe('Autogenerated Admin Clients', () => { ); }); - // query_with_float32_parameter - it('should use a FLOAT32 query parameter to query record from the Venues example table', async () => { - const output = execSync( - `${datatypesCmd} queryWithFloat32 ${INSTANCE_ID} ${DATABASE_ID} ${PROJECT_ID}` - ); - assert.match(output, /VenueId: 4, VenueName: Venue 4, RatingScore: 0.9/); - assert.match(output, /VenueId: 19, VenueName: Venue 19, RatingScore: 0.9/); - assert.match(output, /VenueId: 42, VenueName: Venue 42, RatingScore: 0.9/); - }); - // query_with_int_parameter it('should use a INT64 query parameter to query record from the Venues example table', async () => { const output = execSync( From fdf3ec878dd9f9f7578c4abd334896cff05e7ed0 Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Mon, 18 Mar 2024 13:28:48 +0530 Subject: [PATCH 14/34] fix: presubmit error --- system-test/spanner.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/system-test/spanner.ts b/system-test/spanner.ts index 63baba7bc..51a55d1d4 100644 --- a/system-test/spanner.ts +++ b/system-test/spanner.ts @@ -403,7 +403,6 @@ describe('Spanner', () => { BytesArray ARRAY, BoolArray ARRAY, DateArray ARRAY< DATE >, - Float32Array ARRAY, FloatArray ARRAY, IntArray ARRAY, NumericArray ARRAY< NUMERIC >, @@ -432,7 +431,6 @@ describe('Spanner', () => { BytesArray ARRAY, BoolArray ARRAY, DateArray ARRAY< DATE >, - Float32Array ARRAY, FloatArray ARRAY, JsonArray ARRAY, IntArray ARRAY, @@ -461,7 +459,6 @@ describe('Spanner', () => { "BytesArray" BYTEA[], "BoolArray" BOOL[], "FloatArray" DOUBLE PRECISION[], - "Float32Array" DOUBLE PRECISION[], "IntArray" BIGINT[], "NumericArray" NUMERIC[], "StringArray" VARCHAR[], From 59ce1486c1c039cafb62383fc1e1ada218512739 Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Mon, 18 Mar 2024 14:51:11 +0530 Subject: [PATCH 15/34] refactor: remove sample for float32 query --- samples/datatypes.js | 72 -------------------------------------------- 1 file changed, 72 deletions(-) diff --git a/samples/datatypes.js b/samples/datatypes.js index 9bb913bf5..4e9d89b37 100644 --- a/samples/datatypes.js +++ b/samples/datatypes.js @@ -43,7 +43,6 @@ async function createVenuesTable(instanceId, databaseId, projectId) { AvailableDates ARRAY, LastContactDate Date, OutdoorVenue BOOL, - RatingScore FLOAT32, PopularityScore FLOAT64, LastUpdateTime TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true) ) PRIMARY KEY (VenueId)`, @@ -108,7 +107,6 @@ async function insertData(instanceId, databaseId, projectId) { AvailableDates: availableDates1, LastContactDate: '2018-09-02', OutdoorVenue: false, - RatingScore: Spanner.float32(0.90432), PopularityScore: Spanner.float(0.85543), LastUpdateTime: 'spanner.commit_timestamp()', }, @@ -120,7 +118,6 @@ async function insertData(instanceId, databaseId, projectId) { AvailableDates: availableDates2, LastContactDate: '2019-01-15', OutdoorVenue: true, - RatingScore: Spanner.float32(0.93081), PopularityScore: Spanner.float(0.98716), LastUpdateTime: 'spanner.commit_timestamp()', }, @@ -132,7 +129,6 @@ async function insertData(instanceId, databaseId, projectId) { AvailableDates: availableDates3, LastContactDate: '2018-10-01', OutdoorVenue: false, - RatingScore: Spanner.float32(0.98738), PopularityScore: Spanner.float(0.72598), LastUpdateTime: 'spanner.commit_timestamp()', }, @@ -446,64 +442,6 @@ async function queryWithFloat(instanceId, databaseId, projectId) { // [END spanner_query_with_float_parameter] } -async function queryWithFloat32(instanceId, databaseId, projectId) { - // [START spanner_query_with_float32_parameter] - // Imports the Google Cloud client library. - const {Spanner} = require('@google-cloud/spanner'); - - /** - * TODO(developer): Uncomment the following lines before running the sample. - */ - // const projectId = 'my-project-id'; - // const instanceId = 'my-instance'; - // const databaseId = 'my-database'; - - // Creates a client - const spanner = new Spanner({ - projectId: projectId, - }); - - // Gets a reference to a Cloud Spanner instance and database. - const instance = spanner.instance(instanceId); - const database = instance.database(databaseId); - - const fieldType = { - type: 'float32', - }; - - const exampleFloat = Spanner.float32(0.9); - - const query = { - sql: `SELECT VenueId, VenueName, RatingScore FROM Venues - WHERE RatingScore > @ratingScore`, - params: { - ratingScore: exampleFloat, - }, - types: { - ratingScore: fieldType, - }, - }; - - // Queries rows from the Venues table. - try { - const [rows] = await database.run(query); - - rows.forEach(row => { - const json = row.toJSON(); - console.log( - `VenueId: ${json.VenueId}, VenueName: ${json.VenueName},` + - ` RatingScore: ${json.RatingScore}` - ); - }); - } catch (err) { - console.error('ERROR:', err); - } finally { - // Close the database when finished. - database.close(); - } - // [END spanner_query_with_float32_parameter] -} - async function queryWithInt(instanceId, databaseId, projectId) { // [START spanner_query_with_int_parameter] // Imports the Google Cloud client library. @@ -727,13 +665,6 @@ require('yargs') {}, opts => queryWithFloat(opts.instanceName, opts.databaseName, opts.projectId) ) - .command( - 'queryWithFloat32 ', - "Query data from the sample 'Venues' table with a FLOAT32 datatype.", - {}, - opts => - queryWithFloat32(opts.instanceName, opts.databaseName, opts.projectId) - ) .command( 'queryWithInt ', "Query data from the sample 'Venues' table with a INT64 datatype.", @@ -815,9 +746,6 @@ require('yargs') .example('node $0 queryWithBool "my-instance" "my-database" "my-project-id"') .example('node $0 queryWithBytes "my-instance" "my-database" "my-project-id"') .example('node $0 queryWithDate "my-instance" "my-database" "my-project-id"') - .example( - 'node $0 queryWithFloat32 "my-instance" "my-database" "my-project-id"' - ) .example('node $0 queryWithFloat "my-instance" "my-database" "my-project-id"') .example('node $0 queryWithInt "my-instance" "my-database" "my-project-id"') .example( From e774e981d5d053b08c1ba3712cd3e44917db5287 Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Mon, 18 Mar 2024 17:16:13 +0530 Subject: [PATCH 16/34] chore: add system tests for float32 --- test/codec.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/codec.ts b/test/codec.ts index cb3b1e859..1fc3056dc 100644 --- a/test/codec.ts +++ b/test/codec.ts @@ -544,6 +544,17 @@ describe('codec', () => { assert.deepStrictEqual(decoded, expected); }); + it('should decode FLOAT32', () => { + const value = 'Infinity'; + + const decoded = codec.decode(value, { + code: google.spanner.v1.TypeCode.FLOAT32, + }); + + assert(decoded instanceof codec.Float32); + assert.strictEqual(decoded.value, value); + }); + it('should decode FLOAT64', () => { const value = 'Infinity'; @@ -887,6 +898,14 @@ describe('codec', () => { assert.strictEqual(encoded, '10'); }); + it('should encode FLOAT32', () => { + const value = new codec.Float32(10); + + const encoded = codec.encode(value); + + assert.strictEqual(encoded, 10); + }); + it('should encode FLOAT64', () => { const value = new codec.Float(10); @@ -1126,6 +1145,9 @@ describe('codec', () => { int64: { code: google.spanner.v1.TypeCode[google.spanner.v1.TypeCode.INT64], }, + float32: { + code: google.spanner.v1.TypeCode[google.spanner.v1.TypeCode.FLOAT32], + }, float64: { code: google.spanner.v1.TypeCode[google.spanner.v1.TypeCode.FLOAT64], }, From bae30edf21dbd51264565b53c7cb4e5d555831a0 Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Tue, 19 Mar 2024 12:49:56 +0530 Subject: [PATCH 17/34] refactor tests --- src/codec.ts | 1 + system-test/spanner.ts | 8 ++++---- test/codec.ts | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/codec.ts b/src/codec.ts index 2b01cdd7a..565e6de39 100644 --- a/src/codec.ts +++ b/src/codec.ts @@ -587,6 +587,7 @@ interface FieldType extends Type { /** * @typedef {object} ParamType * @property {string} type The param type. Must be one of the following: + * - float32 * - float64 * - int64 * - numeric diff --git a/system-test/spanner.ts b/system-test/spanner.ts index 51a55d1d4..7929bc1eb 100644 --- a/system-test/spanner.ts +++ b/system-test/spanner.ts @@ -4906,7 +4906,7 @@ describe('Spanner', () => { v: null, }, types: { - v: 'float64', + v: 'float32', }, }; float32Query(done, DATABASE, query, null); @@ -4922,7 +4922,7 @@ describe('Spanner', () => { p1: null, }, types: { - p1: 'float64', + p1: 'float32', }, }; float32Query(done, PG_DATABASE, query, null); @@ -4964,7 +4964,7 @@ describe('Spanner', () => { types: { v: { type: 'array', - child: 'float64', + child: 'float32', }, }, }; @@ -4985,7 +4985,7 @@ describe('Spanner', () => { types: { v: { type: 'array', - child: 'float64', + child: 'float32', }, }, }; diff --git a/test/codec.ts b/test/codec.ts index 1fc3056dc..5c9ed4822 100644 --- a/test/codec.ts +++ b/test/codec.ts @@ -171,7 +171,7 @@ describe('codec', () => { assert.strictEqual(float.value, value); }); - it('should return as a float', () => { + it('should return as a float32', () => { const value = '8.2'; const float = new codec.Float32(value); From fa068b3487ded6c9e3de130bf2b23503577ae646 Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Tue, 19 Mar 2024 13:45:20 +0530 Subject: [PATCH 18/34] fix: presubmit error --- system-test/spanner.ts | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/system-test/spanner.ts b/system-test/spanner.ts index 7929bc1eb..7612171b6 100644 --- a/system-test/spanner.ts +++ b/system-test/spanner.ts @@ -31,6 +31,7 @@ import { InstanceConfig, Session, protos, + Float32, } from '../src'; import {Key} from '../src/table'; import { @@ -4303,6 +4304,7 @@ describe('Spanner', () => { describe('insert & query', () => { const ID = generateName('id'); const NAME = generateName('name'); + const FLOAT32 = 8.1; const FLOAT = 8.2; const INT = 2; const INFO = Buffer.from(generateName('info')); @@ -4315,6 +4317,7 @@ describe('Spanner', () => { const GOOGLE_SQL_INSERT_ROW = { SingerId: ID, Name: NAME, + Float32: FLOAT32, Float: FLOAT, Int: INT, Info: INFO, @@ -4328,6 +4331,7 @@ describe('Spanner', () => { const POSTGRESQL_INSERT_ROW = { SingerId: ID, Name: NAME, + Float32: FLOAT32, Float: FLOAT, Int: INT, Info: INFO, @@ -4470,14 +4474,15 @@ describe('Spanner', () => { assert.strictEqual(metadata.rowType!.fields!.length, 10); assert.strictEqual(metadata.rowType!.fields![0].name, 'SingerId'); assert.strictEqual(metadata.rowType!.fields![1].name, 'Name'); - assert.strictEqual(metadata.rowType!.fields![2].name, 'Float'); - assert.strictEqual(metadata.rowType!.fields![3].name, 'Int'); - assert.strictEqual(metadata.rowType!.fields![4].name, 'Info'); - assert.strictEqual(metadata.rowType!.fields![5].name, 'Created'); - assert.strictEqual(metadata.rowType!.fields![6].name, 'DOB'); - assert.strictEqual(metadata.rowType!.fields![7].name, 'Accents'); - assert.strictEqual(metadata.rowType!.fields![8].name, 'PhoneNumbers'); - assert.strictEqual(metadata.rowType!.fields![9].name, 'HasGear'); + assert.strictEqual(metadata.rowType!.fields![2].name, 'Float32'); + assert.strictEqual(metadata.rowType!.fields![3].name, 'Float'); + assert.strictEqual(metadata.rowType!.fields![4].name, 'Int'); + assert.strictEqual(metadata.rowType!.fields![5].name, 'Info'); + assert.strictEqual(metadata.rowType!.fields![6].name, 'Created'); + assert.strictEqual(metadata.rowType!.fields![7].name, 'DOB'); + assert.strictEqual(metadata.rowType!.fields![8].name, 'Accents'); + assert.strictEqual(metadata.rowType!.fields![9].name, 'PhoneNumbers'); + assert.strictEqual(metadata.rowType!.fields![10].name, 'HasGear'); }); it('POSTGRESQL should return metadata', async function () { @@ -4494,11 +4499,12 @@ describe('Spanner', () => { assert.strictEqual(metadata.rowType!.fields!.length, 7); assert.strictEqual(metadata.rowType!.fields![0].name, 'SingerId'); assert.strictEqual(metadata.rowType!.fields![1].name, 'Name'); - assert.strictEqual(metadata.rowType!.fields![2].name, 'Float'); - assert.strictEqual(metadata.rowType!.fields![3].name, 'Int'); - assert.strictEqual(metadata.rowType!.fields![4].name, 'Info'); - assert.strictEqual(metadata.rowType!.fields![5].name, 'Created'); - assert.strictEqual(metadata.rowType!.fields![6].name, 'HasGear'); + assert.strictEqual(metadata.rowType!.fields![2].name, 'Float32'); + assert.strictEqual(metadata.rowType!.fields![3].name, 'Float'); + assert.strictEqual(metadata.rowType!.fields![4].name, 'Int'); + assert.strictEqual(metadata.rowType!.fields![5].name, 'Info'); + assert.strictEqual(metadata.rowType!.fields![6].name, 'Created'); + assert.strictEqual(metadata.rowType!.fields![7].name, 'HasGear'); }); const invalidQueries = (done, database) => { From 94ece6a16e2b00691a3fea97d41987bb30c45641 Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Tue, 19 Mar 2024 13:45:20 +0530 Subject: [PATCH 19/34] fix: presubmit error --- system-test/spanner.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/system-test/spanner.ts b/system-test/spanner.ts index 7612171b6..2e8388d36 100644 --- a/system-test/spanner.ts +++ b/system-test/spanner.ts @@ -3738,6 +3738,7 @@ describe('Spanner', () => { ( SingerId STRING(1024) NOT NULL, Name STRING(1024), + Float32 FLOAT32, Float FLOAT64, Int INT64, Info BYTES( MAX), @@ -3757,6 +3758,7 @@ describe('Spanner', () => { ( "SingerId" VARCHAR(1024) NOT NULL PRIMARY KEY, "Name" VARCHAR(1024), + "Float32" DOUBLE PRECISION, "Float" DOUBLE PRECISION, "Int" BIGINT, "Info" BYTEA, From 59e4bb64492a7cf171d9d6bbbea229eb2407d333 Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Tue, 19 Mar 2024 13:45:20 +0530 Subject: [PATCH 20/34] fix: presubmit error --- system-test/spanner.ts | 152 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) diff --git a/system-test/spanner.ts b/system-test/spanner.ts index 2e8388d36..c10c545cb 100644 --- a/system-test/spanner.ts +++ b/system-test/spanner.ts @@ -423,6 +423,7 @@ describe('Spanner', () => { BytesValue BYTES( MAX), BoolValue BOOL, DateValue DATE, + Float32Value FLOAT32, FloatValue FLOAT64, JsonValue JSON, IntValue INT64, @@ -432,6 +433,7 @@ describe('Spanner', () => { BytesArray ARRAY, BoolArray ARRAY, DateArray ARRAY< DATE >, + Float32Array ARRAY, FloatArray ARRAY, JsonArray ARRAY, IntArray ARRAY, @@ -450,6 +452,7 @@ describe('Spanner', () => { "Key" VARCHAR NOT NULL PRIMARY KEY, "BytesValue" BYTEA, "BoolValue" BOOL, + "Float32Value" DOUBLE PRECISION, "FloatValue" DOUBLE PRECISION, "IntValue" BIGINT, "NumericValue" NUMERIC, @@ -459,6 +462,7 @@ describe('Spanner', () => { "JsonbValue" JSONB, "BytesArray" BYTEA[], "BoolArray" BOOL[], + "Float32Array" DOUBLE PRECISION[], "FloatArray" DOUBLE PRECISION[], "IntArray" BIGINT[], "NumericArray" NUMERIC[], @@ -901,6 +905,154 @@ describe('Spanner', () => { }); }); + describe('float32s', () => { + const float32Insert = (done, dialect, value) => { + insert({Float32Value: value}, dialect, (err, row) => { + assert.ifError(err); + if (typeof value === 'object' && value !== null) { + value = value.value; + } + assert.deepStrictEqual(row.toJSON().Float32Value, value); + done(); + }); + }; + + it('GOOGLE_STANDARD_SQL should write float32 values', done => { + float32Insert(done, Spanner.GOOGLE_STANDARD_SQL, 8.2); + }); + + it('POSTGRESQL should write float32 values', function (done) { + if (IS_EMULATOR_ENABLED) { + this.skip(); + } + float32Insert(done, Spanner.POSTGRESQL, 8.2); + }); + + it('GOOGLE_STANDARD_SQL should write null float32 values', done => { + float32Insert(done, Spanner.GOOGLE_STANDARD_SQL, null); + }); + + it('POSTGRESQL should write null float32 values', function (done) { + if (IS_EMULATOR_ENABLED) { + this.skip(); + } + float32Insert(done, Spanner.POSTGRESQL, null); + }); + + it('GOOGLE_STANDARD_SQL should accept a Float object with an Int-like value', done => { + float32Insert(done, Spanner.GOOGLE_STANDARD_SQL, Spanner.float32(8)); + }); + + it('POSTGRESQL should accept a Float object with an Int-like value', function (done) { + if (IS_EMULATOR_ENABLED) { + this.skip(); + } + float32Insert(done, Spanner.POSTGRESQL, Spanner.float32(8)); + }); + + it('GOOGLE_STANDARD_SQL should handle Infinity', done => { + float32Insert(done, Spanner.GOOGLE_STANDARD_SQL, Infinity); + }); + + it('POSTGRESQL should handle Infinity', function (done) { + if (IS_EMULATOR_ENABLED) { + this.skip(); + } + float32Insert(done, Spanner.POSTGRESQL, Infinity); + }); + + it('GOOGLE_STANDARD_SQL should handle -Infinity', done => { + float32Insert(done, Spanner.GOOGLE_STANDARD_SQL, -Infinity); + }); + + it('POSTGRESQL should handle -Infinity', function (done) { + if (IS_EMULATOR_ENABLED) { + this.skip(); + } + float32Insert(done, Spanner.POSTGRESQL, -Infinity); + }); + + it('GOOGLE_STANDARD_SQL should handle NaN', done => { + float32Insert(done, Spanner.GOOGLE_STANDARD_SQL, NaN); + }); + + it('POSTGRESQL should handle NaN', function (done) { + if (IS_EMULATOR_ENABLED) { + this.skip(); + } + float32Insert(done, Spanner.POSTGRESQL, NaN); + }); + + it('GOOGLE_STANDARD_SQL should write empty float64 array values', done => { + insert({Float32Array: []}, Spanner.GOOGLE_STANDARD_SQL, (err, row) => { + assert.ifError(err); + assert.deepStrictEqual(row.toJSON().Float32Array, []); + done(); + }); + }); + + it('POSTGRESQL should write empty float64 array values', function (done) { + if (IS_EMULATOR_ENABLED) { + this.skip(); + } + insert({Float32Array: []}, Spanner.POSTGRESQL, (err, row) => { + assert.ifError(err); + assert.deepStrictEqual(row.toJSON().Float32Array, []); + done(); + }); + }); + + it('GOOGLE_STANDARD_SQL should write null float64 array values', done => { + insert( + {Float32Array: [null]}, + Spanner.GOOGLE_STANDARD_SQL, + (err, row) => { + assert.ifError(err); + assert.deepStrictEqual(row.toJSON().Float32Array, [null]); + done(); + } + ); + }); + + it('POSTGRESQL should write null float64 array values', function (done) { + if (IS_EMULATOR_ENABLED) { + this.skip(); + } + insert({Float32Array: [null]}, Spanner.POSTGRESQL, (err, row) => { + assert.ifError(err); + assert.deepStrictEqual(row.toJSON().Float32Array, [null]); + done(); + }); + }); + + it('GOOGLE_STANDARD_SQL should write float64 array values', done => { + const values = [1.2, 2.3, 3.4]; + + insert( + {Float32Array: values}, + Spanner.GOOGLE_STANDARD_SQL, + (err, row) => { + assert.ifError(err); + assert.deepStrictEqual(row.toJSON().Float32Array, values); + done(); + } + ); + }); + + it('POSTGRESQL should write float64 array values', function (done) { + if (IS_EMULATOR_ENABLED) { + this.skip(); + } + const values = [1.2, 2.3, 3.4]; + + insert({Float32Array: values}, Spanner.POSTGRESQL, (err, row) => { + assert.ifError(err); + assert.deepStrictEqual(row.toJSON().Float32Array, values); + done(); + }); + }); + }); + describe('float64s', () => { const float64Insert = (done, dialect, value) => { insert({FloatValue: value}, dialect, (err, row) => { From 9fa5ab4a35f17dca1fadf61f6442d90bbd1f5d2a Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Tue, 19 Mar 2024 13:45:20 +0530 Subject: [PATCH 21/34] fix: presubmit error --- system-test/spanner.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/system-test/spanner.ts b/system-test/spanner.ts index c10c545cb..81d5f09c1 100644 --- a/system-test/spanner.ts +++ b/system-test/spanner.ts @@ -396,6 +396,7 @@ describe('Spanner', () => { BytesValue BYTES( MAX), BoolValue BOOL, DateValue DATE, + Float32Value FLOAT32, FloatValue FLOAT64, IntValue INT64, NumericValue NUMERIC, @@ -404,6 +405,7 @@ describe('Spanner', () => { BytesArray ARRAY, BoolArray ARRAY, DateArray ARRAY< DATE >, + Float32Array ARRAY, FloatArray ARRAY, IntArray ARRAY, NumericArray ARRAY< NUMERIC >, From 22d33f708a894a7cd365f31b506aaa87bdda1555 Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Tue, 19 Mar 2024 13:45:20 +0530 Subject: [PATCH 22/34] fix: presubmit error --- system-test/spanner.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/system-test/spanner.ts b/system-test/spanner.ts index 81d5f09c1..9974dceb3 100644 --- a/system-test/spanner.ts +++ b/system-test/spanner.ts @@ -31,7 +31,6 @@ import { InstanceConfig, Session, protos, - Float32, } from '../src'; import {Key} from '../src/table'; import { From 667dea9eb051d7edaa79f7d23b643035d0588e8f Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Mon, 25 Mar 2024 15:50:05 +0530 Subject: [PATCH 23/34] refactor: system test for float32 --- .gitignore | 1 + .mocharc.js | 2 +- src/codec.ts | 4 +++ src/table.ts | 2 -- src/transaction.ts | 3 +-- system-test/spanner.ts | 59 +++++++++++++++++++++++++++--------------- 6 files changed, 45 insertions(+), 26 deletions(-) diff --git a/.gitignore b/.gitignore index d4f03a0df..14050d4e4 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ system-test/*key.json .DS_Store package-lock.json __pycache__ +.vscode \ No newline at end of file diff --git a/.mocharc.js b/.mocharc.js index 0b600509b..1536da412 100644 --- a/.mocharc.js +++ b/.mocharc.js @@ -14,7 +14,7 @@ const config = { "enable-source-maps": true, "throw-deprecation": true, - "timeout": 10000, + "timeout": 1600000, "recursive": true } if (process.env.MOCHA_THROW_DEPRECATION === 'false') { diff --git a/src/codec.ts b/src/codec.ts index 565e6de39..041672e76 100644 --- a/src/codec.ts +++ b/src/codec.ts @@ -622,6 +622,10 @@ function getType(value: Value): Type { const isSpecialNumber = is.infinite(value) || (is.number(value) && isNaN(value)); + if(value instanceof Float32) { + return {type: 'float32'}; + } + if (is.decimal(value) || isSpecialNumber || value instanceof Float) { return {type: 'float64'}; } diff --git a/src/table.ts b/src/table.ts index c737bf96b..e52e9e08c 100644 --- a/src/table.ts +++ b/src/table.ts @@ -598,7 +598,6 @@ class Table { typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb!; - this._mutate('insert', rows, options, callback!); } /** @@ -1050,7 +1049,6 @@ class Table { callback(err); return; } - transaction![method](this.name, rows as Key[]); transaction!.commit(options, callback); }); diff --git a/src/transaction.ts b/src/transaction.ts index 11eb03657..36b8e373d 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -1292,7 +1292,7 @@ export class Snapshot extends EventEmitter { typeMap[param] = codec.getType(value); } fields[param] = codec.encode(value); - }); + }); params.fields = fields; } @@ -2370,7 +2370,6 @@ export class Transaction extends Dml { ].join('\n\n') ); } - const values = columns.map(column => row[column]); return codec.convertToListValue(values); }); diff --git a/system-test/spanner.ts b/system-test/spanner.ts index 9974dceb3..16cb412b3 100644 --- a/system-test/spanner.ts +++ b/system-test/spanner.ts @@ -53,9 +53,10 @@ const IAM_MEMBER = process.env.IAM_MEMBER; const PREFIX = 'gcloud-tests-'; const RUN_ID = shortUUID(); const LABEL = `node-spanner-systests-${RUN_ID}`; +const endpoint = "staging-wrenchworks.sandbox.googleapis.com"; const spanner = new Spanner({ projectId: process.env.GCLOUD_PROJECT, - apiEndpoint: process.env.API_ENDPOINT, + apiEndpoint: endpoint, }); const GAX_OPTIONS: CallOptions = { retry: { @@ -210,12 +211,12 @@ describe('Spanner', () => { * Not to exceed quota * @see {@link https://cloud.google.com/spanner/quotas#administrative_limits} */ - const limit = pLimit(5); - await Promise.all( - RESOURCES_TO_CLEAN.map(resource => - limit(() => resource.delete(GAX_OPTIONS)) - ) - ); + // const limit = pLimit(5); + // await Promise.all( + // RESOURCES_TO_CLEAN.map(resource => + // limit(() => resource.delete(GAX_OPTIONS)) + // ) + // ); } } catch (err) { console.error('Cleanup failed:', err); @@ -379,7 +380,6 @@ describe('Spanner', () => { callback(err); return; } - callback(null, rows.shift(), insertResp, readResp); }); }); @@ -906,19 +906,30 @@ describe('Spanner', () => { }); }); - describe('float32s', () => { + describe.only('float32s', () => { const float32Insert = (done, dialect, value) => { insert({Float32Value: value}, dialect, (err, row) => { + console.log(DATABASE); assert.ifError(err); if (typeof value === 'object' && value !== null) { value = value.value; } - assert.deepStrictEqual(row.toJSON().Float32Value, value); + console.log("line 916: ", row.toJSON().Float32Value); + console.log("line 917: ", value); + if(row.toJSON().Float32Value === value) { + assert.deepStrictEqual(row.toJSON().Float32Value, value); + } else { + assert.ok((row.toJSON().Float32Value - value) <= 0.00001); + } done(); }); }; - it('GOOGLE_STANDARD_SQL should write float32 values', done => { + it.only('GOOGLE_STANDARD_SQL should write float32 values', done => { + float32Insert(done, Spanner.GOOGLE_STANDARD_SQL, 8.1234567895123); + }); + + it.only('GOOGLE_STANDARD_SQL should write float32 values', done => { float32Insert(done, Spanner.GOOGLE_STANDARD_SQL, 8.2); }); @@ -973,7 +984,7 @@ describe('Spanner', () => { float32Insert(done, Spanner.POSTGRESQL, -Infinity); }); - it('GOOGLE_STANDARD_SQL should handle NaN', done => { + it.only('GOOGLE_STANDARD_SQL should handle NaN', done => { float32Insert(done, Spanner.GOOGLE_STANDARD_SQL, NaN); }); @@ -984,7 +995,7 @@ describe('Spanner', () => { float32Insert(done, Spanner.POSTGRESQL, NaN); }); - it('GOOGLE_STANDARD_SQL should write empty float64 array values', done => { + it('GOOGLE_STANDARD_SQL should write empty float32 array values', done => { insert({Float32Array: []}, Spanner.GOOGLE_STANDARD_SQL, (err, row) => { assert.ifError(err); assert.deepStrictEqual(row.toJSON().Float32Array, []); @@ -992,7 +1003,7 @@ describe('Spanner', () => { }); }); - it('POSTGRESQL should write empty float64 array values', function (done) { + it('POSTGRESQL should write empty float32 array values', function (done) { if (IS_EMULATOR_ENABLED) { this.skip(); } @@ -1003,7 +1014,7 @@ describe('Spanner', () => { }); }); - it('GOOGLE_STANDARD_SQL should write null float64 array values', done => { + it('GOOGLE_STANDARD_SQL should write null float32 array values', done => { insert( {Float32Array: [null]}, Spanner.GOOGLE_STANDARD_SQL, @@ -1015,7 +1026,7 @@ describe('Spanner', () => { ); }); - it('POSTGRESQL should write null float64 array values', function (done) { + it('POSTGRESQL should write null float32 array values', function (done) { if (IS_EMULATOR_ENABLED) { this.skip(); } @@ -1026,7 +1037,7 @@ describe('Spanner', () => { }); }); - it('GOOGLE_STANDARD_SQL should write float64 array values', done => { + it('GOOGLE_STANDARD_SQL should write float32 array values', done => { const values = [1.2, 2.3, 3.4]; insert( @@ -1040,7 +1051,7 @@ describe('Spanner', () => { ); }); - it('POSTGRESQL should write float64 array values', function (done) { + it('POSTGRESQL should write float32 array values', function (done) { if (IS_EMULATOR_ENABLED) { this.skip(); } @@ -1061,12 +1072,18 @@ describe('Spanner', () => { if (typeof value === 'object' && value !== null) { value = value.value; } + console.log("line 1074: ", row.toJSON().FloatValue); + console.log("line 1075: ", value); assert.deepStrictEqual(row.toJSON().FloatValue, value); done(); }); }; - it('GOOGLE_STANDARD_SQL should write float64 values', done => { + it.only('GOOGLE_STANDARD_SQL should write float64 values', done => { + float64Insert(done, Spanner.GOOGLE_STANDARD_SQL, 8.1234567895123); + }); + + it.only('GOOGLE_STANDARD_SQL should write float64 values', done => { float64Insert(done, Spanner.GOOGLE_STANDARD_SQL, 8.2); }); @@ -1121,7 +1138,7 @@ describe('Spanner', () => { float64Insert(done, Spanner.POSTGRESQL, -Infinity); }); - it('GOOGLE_STANDARD_SQL should handle NaN', done => { + it.only('GOOGLE_STANDARD_SQL should handle NaN', done => { float64Insert(done, Spanner.GOOGLE_STANDARD_SQL, NaN); }); @@ -4459,7 +4476,7 @@ describe('Spanner', () => { describe('insert & query', () => { const ID = generateName('id'); const NAME = generateName('name'); - const FLOAT32 = 8.1; + const FLOAT32 = 8.2; const FLOAT = 8.2; const INT = 2; const INFO = Buffer.from(generateName('info')); From fe957b489e02818868d20e7404f94b65ed588a09 Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Mon, 25 Mar 2024 16:54:12 +0530 Subject: [PATCH 24/34] refactor: system test --- system-test/spanner.ts | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/system-test/spanner.ts b/system-test/spanner.ts index 16cb412b3..8385a0b95 100644 --- a/system-test/spanner.ts +++ b/system-test/spanner.ts @@ -909,14 +909,13 @@ describe('Spanner', () => { describe.only('float32s', () => { const float32Insert = (done, dialect, value) => { insert({Float32Value: value}, dialect, (err, row) => { - console.log(DATABASE); assert.ifError(err); if (typeof value === 'object' && value !== null) { value = value.value; } - console.log("line 916: ", row.toJSON().Float32Value); - console.log("line 917: ", value); - if(row.toJSON().Float32Value === value) { + if(Number.isNaN(row.toJSON().Float32Value)) { + assert.deepStrictEqual(row.toJSON().Float32Value, value); + } else if(row.toJSON().Float32Value === value) { assert.deepStrictEqual(row.toJSON().Float32Value, value); } else { assert.ok((row.toJSON().Float32Value - value) <= 0.00001); @@ -925,11 +924,7 @@ describe('Spanner', () => { }); }; - it.only('GOOGLE_STANDARD_SQL should write float32 values', done => { - float32Insert(done, Spanner.GOOGLE_STANDARD_SQL, 8.1234567895123); - }); - - it.only('GOOGLE_STANDARD_SQL should write float32 values', done => { + it('GOOGLE_STANDARD_SQL should write float32 values', done => { float32Insert(done, Spanner.GOOGLE_STANDARD_SQL, 8.2); }); @@ -984,7 +979,7 @@ describe('Spanner', () => { float32Insert(done, Spanner.POSTGRESQL, -Infinity); }); - it.only('GOOGLE_STANDARD_SQL should handle NaN', done => { + it('GOOGLE_STANDARD_SQL should handle NaN', done => { float32Insert(done, Spanner.GOOGLE_STANDARD_SQL, NaN); }); @@ -1045,7 +1040,9 @@ describe('Spanner', () => { Spanner.GOOGLE_STANDARD_SQL, (err, row) => { assert.ifError(err); - assert.deepStrictEqual(row.toJSON().Float32Array, values); + for(let i=0; i { if (typeof value === 'object' && value !== null) { value = value.value; } - console.log("line 1074: ", row.toJSON().FloatValue); - console.log("line 1075: ", value); assert.deepStrictEqual(row.toJSON().FloatValue, value); done(); }); }; - it.only('GOOGLE_STANDARD_SQL should write float64 values', done => { + it('GOOGLE_STANDARD_SQL should write float64 values', done => { float64Insert(done, Spanner.GOOGLE_STANDARD_SQL, 8.1234567895123); }); - it.only('GOOGLE_STANDARD_SQL should write float64 values', done => { - float64Insert(done, Spanner.GOOGLE_STANDARD_SQL, 8.2); - }); - it('POSTGRESQL should write float64 values', function (done) { if (IS_EMULATOR_ENABLED) { this.skip(); @@ -1138,7 +1129,7 @@ describe('Spanner', () => { float64Insert(done, Spanner.POSTGRESQL, -Infinity); }); - it.only('GOOGLE_STANDARD_SQL should handle NaN', done => { + it('GOOGLE_STANDARD_SQL should handle NaN', done => { float64Insert(done, Spanner.GOOGLE_STANDARD_SQL, NaN); }); @@ -5041,7 +5032,7 @@ describe('Spanner', () => { }); }); - describe('float32', () => { + describe.only('float32', () => { const float32Query = (done, database, query, value) => { database.run(query, (err, rows) => { assert.ifError(err); From 4a98236fc3462aee4c9b0460abc1633712ea3e2e Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Mon, 25 Mar 2024 16:54:12 +0530 Subject: [PATCH 25/34] refactor: system test --- src/table.ts | 2 ++ src/transaction.ts | 3 ++- system-test/spanner.ts | 12 ++++++------ test/codec.ts | 16 +++++++++++----- 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/table.ts b/src/table.ts index e52e9e08c..ccba7af26 100644 --- a/src/table.ts +++ b/src/table.ts @@ -598,6 +598,7 @@ class Table { typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb!; + this._mutate('insert', rows, options, callback!); } /** @@ -1049,6 +1050,7 @@ class Table { callback(err); return; } + transaction![method](this.name, rows as Key[]); transaction!.commit(options, callback); }); diff --git a/src/transaction.ts b/src/transaction.ts index 36b8e373d..eb0a2accf 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -1292,7 +1292,7 @@ export class Snapshot extends EventEmitter { typeMap[param] = codec.getType(value); } fields[param] = codec.encode(value); - }); + }); params.fields = fields; } @@ -2370,6 +2370,7 @@ export class Transaction extends Dml { ].join('\n\n') ); } + const values = columns.map(column => row[column]); return codec.convertToListValue(values); }); diff --git a/system-test/spanner.ts b/system-test/spanner.ts index 8385a0b95..5b06c161c 100644 --- a/system-test/spanner.ts +++ b/system-test/spanner.ts @@ -211,12 +211,12 @@ describe('Spanner', () => { * Not to exceed quota * @see {@link https://cloud.google.com/spanner/quotas#administrative_limits} */ - // const limit = pLimit(5); - // await Promise.all( - // RESOURCES_TO_CLEAN.map(resource => - // limit(() => resource.delete(GAX_OPTIONS)) - // ) - // ); + const limit = pLimit(5); + await Promise.all( + RESOURCES_TO_CLEAN.map(resource => + limit(() => resource.delete(GAX_OPTIONS)) + ) + ); } } catch (err) { console.error('Cleanup failed:', err); diff --git a/test/codec.ts b/test/codec.ts index 5c9ed4822..d7e05c4b0 100644 --- a/test/codec.ts +++ b/test/codec.ts @@ -166,17 +166,17 @@ describe('codec', () => { describe('Float32', () => { it('should store the value', () => { const value = 8; - const float = new codec.Float32(value); + const float32 = new codec.Float32(value); - assert.strictEqual(float.value, value); + assert.strictEqual(float32.value, value); }); it('should return as a float32', () => { const value = '8.2'; - const float = new codec.Float32(value); + const float32 = new codec.Float32(value); - assert.strictEqual(float.valueOf(), Number(value)); - assert.strictEqual(float + 2, Number(value) + 2); + assert.strictEqual(float32.valueOf(), Number(value)); + assert.strictEqual(float32 + 2, Number(value) + 2); }); }); @@ -993,6 +993,12 @@ describe('codec', () => { }); }); + it('should determine if the value is a float32', () => { + assert.deepStrictEqual(codec.getType(new codec.Float32(1.1)), { + type: 'float64', + }); + }); + it('should determine if the value is an int', () => { assert.deepStrictEqual(codec.getType(1234), {type: 'int64'}); assert.deepStrictEqual(codec.getType(new codec.Int(1)), {type: 'int64'}); From b5468804457efb727c29d4ded7820f36cce0f51c Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Mon, 25 Mar 2024 18:45:03 +0530 Subject: [PATCH 26/34] fix: presubmit errors --- src/codec.ts | 2 +- src/table.ts | 4 ++-- src/transaction.ts | 2 +- system-test/spanner.ts | 17 ++++++++--------- test/codec.ts | 10 +++++----- 5 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/codec.ts b/src/codec.ts index 041672e76..53c643200 100644 --- a/src/codec.ts +++ b/src/codec.ts @@ -622,7 +622,7 @@ function getType(value: Value): Type { const isSpecialNumber = is.infinite(value) || (is.number(value) && isNaN(value)); - if(value instanceof Float32) { + if (value instanceof Float32) { return {type: 'float32'}; } diff --git a/src/table.ts b/src/table.ts index ccba7af26..c737bf96b 100644 --- a/src/table.ts +++ b/src/table.ts @@ -598,7 +598,7 @@ class Table { typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb!; - + this._mutate('insert', rows, options, callback!); } /** @@ -1050,7 +1050,7 @@ class Table { callback(err); return; } - + transaction![method](this.name, rows as Key[]); transaction!.commit(options, callback); }); diff --git a/src/transaction.ts b/src/transaction.ts index eb0a2accf..11eb03657 100644 --- a/src/transaction.ts +++ b/src/transaction.ts @@ -2370,7 +2370,7 @@ export class Transaction extends Dml { ].join('\n\n') ); } - + const values = columns.map(column => row[column]); return codec.convertToListValue(values); }); diff --git a/system-test/spanner.ts b/system-test/spanner.ts index 5b06c161c..981ee91c4 100644 --- a/system-test/spanner.ts +++ b/system-test/spanner.ts @@ -53,10 +53,9 @@ const IAM_MEMBER = process.env.IAM_MEMBER; const PREFIX = 'gcloud-tests-'; const RUN_ID = shortUUID(); const LABEL = `node-spanner-systests-${RUN_ID}`; -const endpoint = "staging-wrenchworks.sandbox.googleapis.com"; const spanner = new Spanner({ projectId: process.env.GCLOUD_PROJECT, - apiEndpoint: endpoint, + apiEndpoint: process.env.API_ENDPOINT, }); const GAX_OPTIONS: CallOptions = { retry: { @@ -906,19 +905,19 @@ describe('Spanner', () => { }); }); - describe.only('float32s', () => { + describe.skip('float32s', () => { const float32Insert = (done, dialect, value) => { insert({Float32Value: value}, dialect, (err, row) => { assert.ifError(err); if (typeof value === 'object' && value !== null) { value = value.value; } - if(Number.isNaN(row.toJSON().Float32Value)) { + if (Number.isNaN(row.toJSON().Float32Value)) { assert.deepStrictEqual(row.toJSON().Float32Value, value); - } else if(row.toJSON().Float32Value === value) { + } else if (row.toJSON().Float32Value === value) { assert.deepStrictEqual(row.toJSON().Float32Value, value); } else { - assert.ok((row.toJSON().Float32Value - value) <= 0.00001); + assert.ok(row.toJSON().Float32Value - value <= 0.00001); } done(); }); @@ -1040,8 +1039,8 @@ describe('Spanner', () => { Spanner.GOOGLE_STANDARD_SQL, (err, row) => { assert.ifError(err); - for(let i=0; i { }); }); - describe.only('float32', () => { + describe.skip('float32', () => { const float32Query = (done, database, query, value) => { database.run(query, (err, rows) => { assert.ifError(err); diff --git a/test/codec.ts b/test/codec.ts index d7e05c4b0..73b9f2132 100644 --- a/test/codec.ts +++ b/test/codec.ts @@ -163,7 +163,7 @@ describe('codec', () => { }); }); - describe('Float32', () => { + describe.skip('Float32', () => { it('should store the value', () => { const value = 8; const float32 = new codec.Float32(value); @@ -544,7 +544,7 @@ describe('codec', () => { assert.deepStrictEqual(decoded, expected); }); - it('should decode FLOAT32', () => { + it.skip('should decode FLOAT32', () => { const value = 'Infinity'; const decoded = codec.decode(value, { @@ -898,7 +898,7 @@ describe('codec', () => { assert.strictEqual(encoded, '10'); }); - it('should encode FLOAT32', () => { + it.skip('should encode FLOAT32', () => { const value = new codec.Float32(10); const encoded = codec.encode(value); @@ -993,9 +993,9 @@ describe('codec', () => { }); }); - it('should determine if the value is a float32', () => { + it.skip('should determine if the value is a float32', () => { assert.deepStrictEqual(codec.getType(new codec.Float32(1.1)), { - type: 'float64', + type: 'float32', }); }); From a9052d79d8ca862ccacb16a3df0dc8040357fe60 Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Mon, 25 Mar 2024 18:47:26 +0530 Subject: [PATCH 27/34] refactor: system-test --- .mocharc.js | 2 +- system-test/spanner.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.mocharc.js b/.mocharc.js index 1536da412..0b600509b 100644 --- a/.mocharc.js +++ b/.mocharc.js @@ -14,7 +14,7 @@ const config = { "enable-source-maps": true, "throw-deprecation": true, - "timeout": 1600000, + "timeout": 10000, "recursive": true } if (process.env.MOCHA_THROW_DEPRECATION === 'false') { diff --git a/system-test/spanner.ts b/system-test/spanner.ts index 981ee91c4..63e980d36 100644 --- a/system-test/spanner.ts +++ b/system-test/spanner.ts @@ -1074,7 +1074,7 @@ describe('Spanner', () => { }; it('GOOGLE_STANDARD_SQL should write float64 values', done => { - float64Insert(done, Spanner.GOOGLE_STANDARD_SQL, 8.1234567895123); + float64Insert(done, Spanner.GOOGLE_STANDARD_SQL, 8.2); }); it('POSTGRESQL should write float64 values', function (done) { From dccaa3261676e1710451a988090fbc9589ceda05 Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Mon, 25 Mar 2024 18:49:12 +0530 Subject: [PATCH 28/34] skip float32 test --- test/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/index.ts b/test/index.ts index f1cf0f666..dd2b4b7b9 100644 --- a/test/index.ts +++ b/test/index.ts @@ -495,7 +495,7 @@ describe('Spanner', () => { }); }); - describe('float32', () => { + describe.skip('float32', () => { it('should create a Float32 instance', () => { const value = {}; const customValue = {}; From 69ffa96199344270d828435c7149b607445477a2 Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Mon, 25 Mar 2024 18:49:12 +0530 Subject: [PATCH 29/34] skip float32 test --- system-test/spanner.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/system-test/spanner.ts b/system-test/spanner.ts index 63e980d36..5da7ab0f9 100644 --- a/system-test/spanner.ts +++ b/system-test/spanner.ts @@ -394,7 +394,6 @@ describe('Spanner', () => { BytesValue BYTES( MAX), BoolValue BOOL, DateValue DATE, - Float32Value FLOAT32, FloatValue FLOAT64, IntValue INT64, NumericValue NUMERIC, @@ -423,7 +422,6 @@ describe('Spanner', () => { BytesValue BYTES( MAX), BoolValue BOOL, DateValue DATE, - Float32Value FLOAT32, FloatValue FLOAT64, JsonValue JSON, IntValue INT64, @@ -452,7 +450,6 @@ describe('Spanner', () => { "Key" VARCHAR NOT NULL PRIMARY KEY, "BytesValue" BYTEA, "BoolValue" BOOL, - "Float32Value" DOUBLE PRECISION, "FloatValue" DOUBLE PRECISION, "IntValue" BIGINT, "NumericValue" NUMERIC, From a0e7cf13e5bf12b962fee96ae73778b0ab76d2ef Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Mon, 25 Mar 2024 19:24:28 +0530 Subject: [PATCH 30/34] fix: presubmit error --- system-test/spanner.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/system-test/spanner.ts b/system-test/spanner.ts index 5da7ab0f9..39a9b960a 100644 --- a/system-test/spanner.ts +++ b/system-test/spanner.ts @@ -402,7 +402,6 @@ describe('Spanner', () => { BytesArray ARRAY, BoolArray ARRAY, DateArray ARRAY< DATE >, - Float32Array ARRAY, FloatArray ARRAY, IntArray ARRAY, NumericArray ARRAY< NUMERIC >, @@ -431,7 +430,6 @@ describe('Spanner', () => { BytesArray ARRAY, BoolArray ARRAY, DateArray ARRAY< DATE >, - Float32Array ARRAY, FloatArray ARRAY, JsonArray ARRAY, IntArray ARRAY, @@ -3895,7 +3893,6 @@ describe('Spanner', () => { ( SingerId STRING(1024) NOT NULL, Name STRING(1024), - Float32 FLOAT32, Float FLOAT64, Int INT64, Info BYTES( MAX), @@ -3915,7 +3912,6 @@ describe('Spanner', () => { ( "SingerId" VARCHAR(1024) NOT NULL PRIMARY KEY, "Name" VARCHAR(1024), - "Float32" DOUBLE PRECISION, "Float" DOUBLE PRECISION, "Int" BIGINT, "Info" BYTEA, @@ -4460,7 +4456,7 @@ describe('Spanner', () => { insertThenUpdateRow(done, postgreSqlTable); }); - describe('insert & query', () => { + describe.skip('insert & query', () => { const ID = generateName('id'); const NAME = generateName('name'); const FLOAT32 = 8.2; From a890603dab60354b5ddf4533be47823622b783e0 Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Tue, 26 Mar 2024 18:10:11 +0530 Subject: [PATCH 31/34] chore: add test cases for float32 tests --- system-test/spanner.ts | 152 +++++++++++++++++++++++++++++++++-------- 1 file changed, 124 insertions(+), 28 deletions(-) diff --git a/system-test/spanner.ts b/system-test/spanner.ts index 39a9b960a..9b8dcce63 100644 --- a/system-test/spanner.ts +++ b/system-test/spanner.ts @@ -31,6 +31,8 @@ import { InstanceConfig, Session, protos, + Float32, + Float, } from '../src'; import {Key} from '../src/table'; import { @@ -45,6 +47,7 @@ import {google} from '../protos/protos'; import CreateDatabaseMetadata = google.spanner.admin.database.v1.CreateDatabaseMetadata; import CreateBackupMetadata = google.spanner.admin.database.v1.CreateBackupMetadata; import CreateInstanceConfigMetadata = google.spanner.admin.instance.v1.CreateInstanceConfigMetadata; +import { types } from 'protobufjs'; const SKIP_BACKUPS = process.env.SKIP_BACKUPS; const SKIP_FGAC_TESTS = (process.env.SKIP_FGAC_TESTS || 'false').toLowerCase(); @@ -394,6 +397,7 @@ describe('Spanner', () => { BytesValue BYTES( MAX), BoolValue BOOL, DateValue DATE, + // Float32Value FLOAT32, // TODO: Uncomment while using float32 feature. FloatValue FLOAT64, IntValue INT64, NumericValue NUMERIC, @@ -402,6 +406,7 @@ describe('Spanner', () => { BytesArray ARRAY, BoolArray ARRAY, DateArray ARRAY< DATE >, + // Float32Array ARRAY, // TODO: Uncomment while using float32 feature. FloatArray ARRAY, IntArray ARRAY, NumericArray ARRAY< NUMERIC >, @@ -421,6 +426,7 @@ describe('Spanner', () => { BytesValue BYTES( MAX), BoolValue BOOL, DateValue DATE, + // Float32Value FLOAT32, // TODO: Uncomment while using float32 feature. FloatValue FLOAT64, JsonValue JSON, IntValue INT64, @@ -430,6 +436,7 @@ describe('Spanner', () => { BytesArray ARRAY, BoolArray ARRAY, DateArray ARRAY< DATE >, + // Float32Array ARRAY, // TODO: Uncomment while using float32 feature. FloatArray ARRAY, JsonArray ARRAY, IntArray ARRAY, @@ -448,6 +455,7 @@ describe('Spanner', () => { "Key" VARCHAR NOT NULL PRIMARY KEY, "BytesValue" BYTEA, "BoolValue" BOOL, + // "Float32Value" DOUBLE PRECISION, // TODO: Uncomment while using float32 feature. "FloatValue" DOUBLE PRECISION, "IntValue" BIGINT, "NumericValue" NUMERIC, @@ -457,7 +465,7 @@ describe('Spanner', () => { "JsonbValue" JSONB, "BytesArray" BYTEA[], "BoolArray" BOOL[], - "Float32Array" DOUBLE PRECISION[], + // "Float32Array" DOUBLE PRECISION[], // TODO: Uncomment while using float32 feature. "FloatArray" DOUBLE PRECISION[], "IntArray" BIGINT[], "NumericArray" NUMERIC[], @@ -900,6 +908,7 @@ describe('Spanner', () => { }); }); + // TODO: Enable when the float32 feature has been released. describe.skip('float32s', () => { const float32Insert = (done, dialect, value) => { insert({Float32Value: value}, dialect, (err, row) => { @@ -3893,6 +3902,7 @@ describe('Spanner', () => { ( SingerId STRING(1024) NOT NULL, Name STRING(1024), + // Float32 FLOAT32, // TODO: Uncomment while using float32 feature. Float FLOAT64, Int INT64, Info BYTES( MAX), @@ -3912,6 +3922,7 @@ describe('Spanner', () => { ( "SingerId" VARCHAR(1024) NOT NULL PRIMARY KEY, "Name" VARCHAR(1024), + // "Float32" DOUBLE PRECISION, // TODO: Uncomment while using float32 feature. "Float" DOUBLE PRECISION, "Int" BIGINT, "Info" BYTEA, @@ -4456,10 +4467,10 @@ describe('Spanner', () => { insertThenUpdateRow(done, postgreSqlTable); }); - describe.skip('insert & query', () => { + describe('insert & query', () => { const ID = generateName('id'); const NAME = generateName('name'); - const FLOAT32 = 8.2; + // const FLOAT32 = 8.2; // TODO: Uncomment while using float32 feature. const FLOAT = 8.2; const INT = 2; const INFO = Buffer.from(generateName('info')); @@ -4472,7 +4483,7 @@ describe('Spanner', () => { const GOOGLE_SQL_INSERT_ROW = { SingerId: ID, Name: NAME, - Float32: FLOAT32, + // Float32: FLOAT32, // TODO: Uncomment while using float32 feature. Float: FLOAT, Int: INT, Info: INFO, @@ -4486,7 +4497,7 @@ describe('Spanner', () => { const POSTGRESQL_INSERT_ROW = { SingerId: ID, Name: NAME, - Float32: FLOAT32, + // Float32: FLOAT32, // TODO: Uncomment while using float32 feature. Float: FLOAT, Int: INT, Info: INFO, @@ -4629,15 +4640,16 @@ describe('Spanner', () => { assert.strictEqual(metadata.rowType!.fields!.length, 10); assert.strictEqual(metadata.rowType!.fields![0].name, 'SingerId'); assert.strictEqual(metadata.rowType!.fields![1].name, 'Name'); - assert.strictEqual(metadata.rowType!.fields![2].name, 'Float32'); - assert.strictEqual(metadata.rowType!.fields![3].name, 'Float'); - assert.strictEqual(metadata.rowType!.fields![4].name, 'Int'); - assert.strictEqual(metadata.rowType!.fields![5].name, 'Info'); - assert.strictEqual(metadata.rowType!.fields![6].name, 'Created'); - assert.strictEqual(metadata.rowType!.fields![7].name, 'DOB'); - assert.strictEqual(metadata.rowType!.fields![8].name, 'Accents'); - assert.strictEqual(metadata.rowType!.fields![9].name, 'PhoneNumbers'); - assert.strictEqual(metadata.rowType!.fields![10].name, 'HasGear'); + // TODO: Uncomment while using float32 feature and increase the index by 1 for all the asserts below this. + // assert.strictEqual(metadata.rowType!.fields![2].name, 'Float32'); + assert.strictEqual(metadata.rowType!.fields![2].name, 'Float'); + assert.strictEqual(metadata.rowType!.fields![3].name, 'Int'); + assert.strictEqual(metadata.rowType!.fields![4].name, 'Info'); + assert.strictEqual(metadata.rowType!.fields![5].name, 'Created'); + assert.strictEqual(metadata.rowType!.fields![6].name, 'DOB'); + assert.strictEqual(metadata.rowType!.fields![7].name, 'Accents'); + assert.strictEqual(metadata.rowType!.fields![8].name, 'PhoneNumbers'); + assert.strictEqual(metadata.rowType!.fields![9].name, 'HasGear'); }); it('POSTGRESQL should return metadata', async function () { @@ -4654,12 +4666,13 @@ describe('Spanner', () => { assert.strictEqual(metadata.rowType!.fields!.length, 7); assert.strictEqual(metadata.rowType!.fields![0].name, 'SingerId'); assert.strictEqual(metadata.rowType!.fields![1].name, 'Name'); - assert.strictEqual(metadata.rowType!.fields![2].name, 'Float32'); - assert.strictEqual(metadata.rowType!.fields![3].name, 'Float'); - assert.strictEqual(metadata.rowType!.fields![4].name, 'Int'); - assert.strictEqual(metadata.rowType!.fields![5].name, 'Info'); - assert.strictEqual(metadata.rowType!.fields![6].name, 'Created'); - assert.strictEqual(metadata.rowType!.fields![7].name, 'HasGear'); + // uncomment while using float32 feature and increase the index by 1 for all the asserts below this. + // assert.strictEqual(metadata.rowType!.fields![2].name, 'Float32'); + assert.strictEqual(metadata.rowType!.fields![2].name, 'Float'); + assert.strictEqual(metadata.rowType!.fields![3].name, 'Int'); + assert.strictEqual(metadata.rowType!.fields![4].name, 'Info'); + assert.strictEqual(metadata.rowType!.fields![5].name, 'Created'); + assert.strictEqual(metadata.rowType!.fields![6].name, 'HasGear'); }); const invalidQueries = (done, database) => { @@ -5024,6 +5037,7 @@ describe('Spanner', () => { }); }); + // TODO: Enable when the float32 feature has been released. describe.skip('float32', () => { const float32Query = (done, database, query, value) => { database.run(query, (err, rows) => { @@ -5032,22 +5046,55 @@ describe('Spanner', () => { if (rows[0][0].value) { queriedValue = rows[0][0].value.value; } - assert.strictEqual(queriedValue, value); + if (Number.isNaN(queriedValue)) { + assert.deepStrictEqual(queriedValue, value); + } else if (queriedValue === value) { + assert.deepStrictEqual(queriedValue, value); + } else { + assert.ok(queriedValue - value <= 0.00001); + } done(); }); }; - it('GOOGLE_STANDARD_SQL should bind the value', done => { + it('GOOGLE_STANDARD_SQL should bind the value when param type float32 is used', done => { const query = { sql: 'SELECT @v', params: { v: 2.2, }, + types: { + v: 'float32', + } }; float32Query(done, DATABASE, query, 2.2); }); - it('POSTGRESQL should bind the value', function (done) { + it('GOOGLE_STANDARD_SQL should bind the value when spanner.float32 is used', done => { + const query = { + sql: 'SELECT @v', + params: { + v: Spanner.float32(2.2), + }, + }; + float32Query(done, DATABASE, query, 2.2); + }); + + it('GOOGLE_STANDARD_SQL should bind the value as float64 when param type is not specified', done => { + const query = { + sql: 'SELECT @v', + params: { + v: 2.2, + }, + }; + DATABASE.run(query, (err, rows) => { + assert.ifError(err); + assert.strictEqual(rows[0][0].value instanceof Float, true); + done(); + }); + }); + + it('POSTGRESQL should bind the value when param type float32 is used', function (done) { if (IS_EMULATOR_ENABLED) { this.skip(); } @@ -5056,6 +5103,22 @@ describe('Spanner', () => { params: { p1: 2.2, }, + types: { + p1: 'float32', + }, + }; + float32Query(done, PG_DATABASE, query, 2.2); + }); + + it('POSTGRESQL should bind the value when Spanner.float32 is used', function (done) { + if (IS_EMULATOR_ENABLED) { + this.skip(); + } + const query = { + sql: 'SELECT $1', + params: { + p1: Spanner.float32(2.2), + }, }; float32Query(done, PG_DATABASE, query, 2.2); }); @@ -5097,19 +5160,28 @@ describe('Spanner', () => { params: { v: values, }, + types: { + v: { + type: 'array', + child: 'float32', + }, + }, }; DATABASE.run(query, (err, rows) => { assert.ifError(err); const expected = values.map(val => { - return is.number(val) ? {value: val} : val; + return is.number(val) ? Spanner.float32(val) : val; }); - assert.strictEqual( - JSON.stringify(rows[0][0].value), - JSON.stringify(expected) - ); + for(let i=0;i { params: { v: Infinity, }, + types: { + v: 'float32', + }, }; float32Query(done, DATABASE, query, 'Infinity'); }); @@ -5177,6 +5252,9 @@ describe('Spanner', () => { params: { p1: Infinity, }, + types: { + p1: 'float32', + }, }; float32Query(done, PG_DATABASE, query, 'Infinity'); }); @@ -5187,6 +5265,9 @@ describe('Spanner', () => { params: { v: -Infinity, }, + types: { + v: 'float32', + }, }; float32Query(done, DATABASE, query, '-Infinity'); }); @@ -5200,6 +5281,9 @@ describe('Spanner', () => { params: { p1: -Infinity, }, + types: { + p1: 'float32', + }, }; float32Query(done, PG_DATABASE, query, '-Infinity'); }); @@ -5210,6 +5294,9 @@ describe('Spanner', () => { params: { v: NaN, }, + types: { + v: 'float32', + }, }; float32Query(done, DATABASE, query, 'NaN'); }); @@ -5223,6 +5310,9 @@ describe('Spanner', () => { params: { p1: NaN, }, + types: { + p1: 'float32', + }, }; float32Query(done, PG_DATABASE, query, 'NaN'); }); @@ -5235,6 +5325,12 @@ describe('Spanner', () => { params: { v: values, }, + types: { + v: { + type: 'array', + child: 'float32', + }, + }, }; DATABASE.run(query, (err, rows) => { From 620c8c48cd6dc377173f5940f66886959c031d8b Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Tue, 26 Mar 2024 18:12:45 +0530 Subject: [PATCH 32/34] fix: lint errors --- system-test/spanner.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/system-test/spanner.ts b/system-test/spanner.ts index 9b8dcce63..f4586ecc2 100644 --- a/system-test/spanner.ts +++ b/system-test/spanner.ts @@ -31,7 +31,6 @@ import { InstanceConfig, Session, protos, - Float32, Float, } from '../src'; import {Key} from '../src/table'; @@ -47,7 +46,6 @@ import {google} from '../protos/protos'; import CreateDatabaseMetadata = google.spanner.admin.database.v1.CreateDatabaseMetadata; import CreateBackupMetadata = google.spanner.admin.database.v1.CreateBackupMetadata; import CreateInstanceConfigMetadata = google.spanner.admin.instance.v1.CreateInstanceConfigMetadata; -import { types } from 'protobufjs'; const SKIP_BACKUPS = process.env.SKIP_BACKUPS; const SKIP_FGAC_TESTS = (process.env.SKIP_FGAC_TESTS || 'false').toLowerCase(); @@ -5065,7 +5063,7 @@ describe('Spanner', () => { }, types: { v: 'float32', - } + }, }; float32Query(done, DATABASE, query, 2.2); }); @@ -5175,11 +5173,13 @@ describe('Spanner', () => { return is.number(val) ? Spanner.float32(val) : val; }); - for(let i=0;i Date: Tue, 26 Mar 2024 18:26:06 +0530 Subject: [PATCH 33/34] fix: presubmit error --- system-test/spanner.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/system-test/spanner.ts b/system-test/spanner.ts index f4586ecc2..2e577185a 100644 --- a/system-test/spanner.ts +++ b/system-test/spanner.ts @@ -395,7 +395,6 @@ describe('Spanner', () => { BytesValue BYTES( MAX), BoolValue BOOL, DateValue DATE, - // Float32Value FLOAT32, // TODO: Uncomment while using float32 feature. FloatValue FLOAT64, IntValue INT64, NumericValue NUMERIC, @@ -404,7 +403,6 @@ describe('Spanner', () => { BytesArray ARRAY, BoolArray ARRAY, DateArray ARRAY< DATE >, - // Float32Array ARRAY, // TODO: Uncomment while using float32 feature. FloatArray ARRAY, IntArray ARRAY, NumericArray ARRAY< NUMERIC >, @@ -424,7 +422,6 @@ describe('Spanner', () => { BytesValue BYTES( MAX), BoolValue BOOL, DateValue DATE, - // Float32Value FLOAT32, // TODO: Uncomment while using float32 feature. FloatValue FLOAT64, JsonValue JSON, IntValue INT64, @@ -434,7 +431,6 @@ describe('Spanner', () => { BytesArray ARRAY, BoolArray ARRAY, DateArray ARRAY< DATE >, - // Float32Array ARRAY, // TODO: Uncomment while using float32 feature. FloatArray ARRAY, JsonArray ARRAY, IntArray ARRAY, @@ -453,7 +449,6 @@ describe('Spanner', () => { "Key" VARCHAR NOT NULL PRIMARY KEY, "BytesValue" BYTEA, "BoolValue" BOOL, - // "Float32Value" DOUBLE PRECISION, // TODO: Uncomment while using float32 feature. "FloatValue" DOUBLE PRECISION, "IntValue" BIGINT, "NumericValue" NUMERIC, @@ -463,7 +458,6 @@ describe('Spanner', () => { "JsonbValue" JSONB, "BytesArray" BYTEA[], "BoolArray" BOOL[], - // "Float32Array" DOUBLE PRECISION[], // TODO: Uncomment while using float32 feature. "FloatArray" DOUBLE PRECISION[], "IntArray" BIGINT[], "NumericArray" NUMERIC[], @@ -3900,7 +3894,6 @@ describe('Spanner', () => { ( SingerId STRING(1024) NOT NULL, Name STRING(1024), - // Float32 FLOAT32, // TODO: Uncomment while using float32 feature. Float FLOAT64, Int INT64, Info BYTES( MAX), @@ -3920,7 +3913,6 @@ describe('Spanner', () => { ( "SingerId" VARCHAR(1024) NOT NULL PRIMARY KEY, "Name" VARCHAR(1024), - // "Float32" DOUBLE PRECISION, // TODO: Uncomment while using float32 feature. "Float" DOUBLE PRECISION, "Int" BIGINT, "Info" BYTEA, From 03a7360f77d1068de2478173c6f131e7b3b6e024 Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Tue, 26 Mar 2024 18:30:33 +0530 Subject: [PATCH 34/34] refactor: add comments --- system-test/spanner.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/system-test/spanner.ts b/system-test/spanner.ts index 2e577185a..8849f6e2b 100644 --- a/system-test/spanner.ts +++ b/system-test/spanner.ts @@ -387,6 +387,7 @@ describe('Spanner', () => { before(async () => { if (IS_EMULATOR_ENABLED) { + // TODO: add column Float32Value FLOAT32 and FLOAT32Array Array while using float32 feature. const [googleSqlOperationUpdateDDL] = await DATABASE.updateSchema( ` CREATE TABLE ${TABLE_NAME} @@ -414,6 +415,7 @@ describe('Spanner', () => { ); await googleSqlOperationUpdateDDL.promise(); } else { + // TODO: add column Float32Value FLOAT32 and FLOAT32Array Array while using float32 feature. const [googleSqlOperationUpdateDDL] = await DATABASE.updateSchema( ` CREATE TABLE ${TABLE_NAME} @@ -442,6 +444,7 @@ describe('Spanner', () => { ` ); await googleSqlOperationUpdateDDL.promise(); + // TODO: add column Float32Value DOUBLE PRECISION and FLOAT32Array DOUBLE PRECISION[] while using float32 feature. const [postgreSqlOperationUpdateDDL] = await PG_DATABASE.updateSchema( ` CREATE TABLE ${TABLE_NAME} @@ -3889,6 +3892,7 @@ describe('Spanner', () => { const postgreSqlTable = PG_DATABASE.table(TABLE_NAME); before(async () => { + // TODO: Add column Float32 FLOAT32 while using float32 feature. const googleSqlCreateTable = await googleSqlTable.create( `CREATE TABLE ${TABLE_NAME} ( @@ -3908,6 +3912,7 @@ describe('Spanner', () => { await onPromiseOperationComplete(googleSqlCreateTable); if (!IS_EMULATOR_ENABLED) { + // TODO: Add column "Float32" DOUBLE PRECISION while using float32 feature. const postgreSqlCreateTable = await postgreSqlTable.create( `CREATE TABLE ${TABLE_NAME} (