diff --git a/Spanner/src/Database.php b/Spanner/src/Database.php index 9f544d06a66..57c035cfc9e 100644 --- a/Spanner/src/Database.php +++ b/Spanner/src/Database.php @@ -110,6 +110,7 @@ class Database const TYPE_BOOL = TypeCode::BOOL; const TYPE_INT64 = TypeCode::INT64; + const TYPE_FLOAT32 = TypeCode::FLOAT32; const TYPE_FLOAT64 = TypeCode::FLOAT64; const TYPE_TIMESTAMP = TypeCode::TIMESTAMP; const TYPE_DATE = TypeCode::DATE; diff --git a/Spanner/src/ValueMapper.php b/Spanner/src/ValueMapper.php index aa92c2eade6..c54605170b7 100644 --- a/Spanner/src/ValueMapper.php +++ b/Spanner/src/ValueMapper.php @@ -33,6 +33,7 @@ class ValueMapper const TYPE_BOOL = TypeCode::BOOL; const TYPE_INT64 = TypeCode::INT64; + const TYPE_FLOAT32 = TypeCode::FLOAT32; const TYPE_FLOAT64 = TypeCode::FLOAT64; const TYPE_TIMESTAMP = TypeCode::TIMESTAMP; const TYPE_DATE = TypeCode::DATE; @@ -47,6 +48,7 @@ class ValueMapper /** * @var array + * @internal */ public static $allowedTypes = [ self::TYPE_BOOL, @@ -62,6 +64,7 @@ class ValueMapper self::TYPE_JSON, self::TYPE_PG_NUMERIC, self::TYPE_PG_JSONB, + self::TYPE_FLOAT32, ]; /* @@ -324,6 +327,7 @@ private function decodeValue($value, array $type) } break; + case self::TYPE_FLOAT32: case self::TYPE_FLOAT64: // NaN, Infinite and -Infinite are possible FLOAT64 values, // but when the gRPC response is decoded, they are represented @@ -346,8 +350,9 @@ private function decodeValue($value, array $type) default: throw new \RuntimeException(sprintf( - 'Unexpected string value %s encountered in FLOAT64 field.', - $value + 'Unexpected string value %s encountered in %s field.', + $value, + TypeCode::name($type['code']) )); } } diff --git a/Spanner/tests/System/PgQueryTest.php b/Spanner/tests/System/PgQueryTest.php index 2a8b9caaba0..ccea014c7ef 100644 --- a/Spanner/tests/System/PgQueryTest.php +++ b/Spanner/tests/System/PgQueryTest.php @@ -55,6 +55,7 @@ public static function setUpBeforeClass(): void created_at timestamptz, dt date, data jsonb, + weight float4, PRIMARY KEY (id) )' )->pollUntilComplete(); @@ -71,7 +72,8 @@ public static function setUpBeforeClass(): void 'bytes_col' => new Bytes('hello'), 'created_at' => self::$timestampVal, 'data' => '{"a": "hello", "b": "world"}', - 'dt' => '2020-01-01' + 'dt' => '2020-01-01', + 'weight' => 1.432 ], [ 'id' => 2, @@ -81,7 +83,8 @@ public static function setUpBeforeClass(): void 'age' => 26, 'created_at' => self::$timestampVal, 'data' => '{}', - 'dt' => '2021-01-01' + 'dt' => '2021-01-01', + 'weight' => 1.234 ] ]); } @@ -200,32 +203,56 @@ public function testBindFloat64Parameter() $this->assertCount(2, iterator_to_array($res)); } - public function testBindFloat64ParameterNull() + public function testBindFloat32Parameter() { + $db = self::$database; + + $res = $db->execute('SELECT * FROM ' . self::TABLE_NAME . ' WHERE weight = $1', [ + 'parameters' => [ + 'p1' => 1.234 + ], + 'types' => [ + 'p1' => Database::TYPE_FLOAT32 + ] + ]); + + $this->assertCount(1, iterator_to_array($res)); + } + + public function testBindFloatParameterNull() + { + $res = self::$database->execute('SELECT * FROM ' . self::TABLE_NAME . ' WHERE rating IS NULL'); + $currentFloat64NullCount = count(iterator_to_array($res)); + $res = self::$database->execute('SELECT * FROM ' . self::TABLE_NAME . ' WHERE weight IS NULL'); + $currentFloat32NullCount = count(iterator_to_array($res)); // insert a value with a float param binded to null self::$database->runTransaction(function (Transaction $t) { $t->executeUpdate( - 'INSERT INTO ' . self::TABLE_NAME . '(id, name, registered, rating, age) ' - . 'VALUES($1, $2, $3, $4, $5)', + 'INSERT INTO ' . self::TABLE_NAME . '(id, name, registered, rating, age, weight) ' + . 'VALUES($1, $2, $3, $4, $5, $6)', [ 'parameters' => [ 'p1' => 5, 'p2' => 'Vince', 'p3' => true, 'p4' => null, - 'p5' => 26 + 'p5' => 26, + 'p6' => null ], 'types' => [ - 'p4' => Database::TYPE_FLOAT64 + 'p4' => Database::TYPE_FLOAT64, + 'p6' => Database::TYPE_FLOAT32 ] ] ); $t->commit(); }); - $res = self::$database->execute('SELECT * FROM ' . self::TABLE_NAME . ' WHERE rating IS NULL'); + $resFloat64NullCount = self::$database->execute('SELECT * FROM ' . self::TABLE_NAME . ' WHERE rating IS NULL'); + $resFloat32NullCount = self::$database->execute('SELECT * FROM ' . self::TABLE_NAME . ' WHERE weight IS NULL'); - $this->assertCount(1, iterator_to_array($res)); + $this->assertCount(1 + $currentFloat64NullCount, iterator_to_array($resFloat64NullCount)); + $this->assertCount(1 + $currentFloat32NullCount, iterator_to_array($resFloat32NullCount)); } public function testBindStringParameter() @@ -650,6 +677,7 @@ public function arrayTypesEmptyProvider() return [ [Database::TYPE_BOOL], [Database::TYPE_INT64], + [Database::TYPE_FLOAT32], [Database::TYPE_FLOAT64], [Database::TYPE_STRING], [Database::TYPE_BYTES], @@ -686,6 +714,7 @@ public function arrayTypesNullProvider() return [ [Database::TYPE_BOOL], [Database::TYPE_INT64], + [Database::TYPE_FLOAT32], [Database::TYPE_FLOAT64], [Database::TYPE_STRING], [Database::TYPE_BYTES], diff --git a/Spanner/tests/System/PgWriteTest.php b/Spanner/tests/System/PgWriteTest.php index 3a2dd409f30..c4aed6da28f 100644 --- a/Spanner/tests/System/PgWriteTest.php +++ b/Spanner/tests/System/PgWriteTest.php @@ -53,6 +53,7 @@ public static function setUpBeforeClass(): void bytesfield bytea, datefield date, floatfield float, + float4field float4, intfield bigint, stringfield varchar(1024), timestampfield timestamptz, @@ -61,6 +62,7 @@ public static function setUpBeforeClass(): void arrayfield bigint[], arrayboolfield boolean[], arrayfloatfield float[], + arrayfloat4field float4[], arraystringfield varchar(1024)[], arraybytesfield bytea[], arraytimestampfield timestamptz[], @@ -85,6 +87,9 @@ public function fieldValueProvider() [$this->randId(), 'floatfield', 3.1415], [$this->randId(), 'floatfield', INF], [$this->randId(), 'floatfield', -INF], + [$this->randId(), 'float4field', 3.1415], + [$this->randId(), 'float4field', INF], + [$this->randId(), 'float4field', -INF], [$this->randId(), 'datefield', new Date(new \DateTime('1981-01-20'))], [$this->randId(), 'intfield', 787878787], [$this->randId(), 'stringfield', 'foo bar'], @@ -115,7 +120,7 @@ public function testWriteAndReadBackValue($id, $field, $value) if ($value instanceof Timestamp) { $this->assertEquals($value->formatAsString(), $row[$field]->formatAsString()); } else { - $this->assertEquals($value, $row[$field]); + $this->assertValues($value, $row[$field]); } // test result from executeSql @@ -129,7 +134,7 @@ public function testWriteAndReadBackValue($id, $field, $value) if ($value instanceof Timestamp) { $this->assertEquals($value->formatAsString(), $row[$field]->formatAsString()); } else { - $this->assertEquals($value, $row[$field]); + $this->assertValues($value, $row[$field]); } } @@ -242,6 +247,10 @@ public function arrayFieldValueProvider() [$this->randId(), 'arrayfloatfield', []], [$this->randId(), 'arrayfloatfield', [1.1, null, 1.3]], [$this->randId(), 'arrayfloatfield', null], + [$this->randId(), 'arrayfloat4field', [1.1, 1.2, 1.3]], + [$this->randId(), 'arrayfloat4field', []], + [$this->randId(), 'arrayfloat4field', [1.1, null, 1.3]], + [$this->randId(), 'arrayfloat4field', null], [$this->randId(), 'arraystringfield', ['foo','bar','baz']], [$this->randId(), 'arraystringfield', []], [$this->randId(), 'arraystringfield', ['foo',null,'baz']], @@ -276,7 +285,7 @@ public function testWriteAndReadBackArrayValue($id, $field, $value) $read = $db->read(self::TABLE_NAME, $keyset, [$field]); $row = $read->rows()->current(); - $this->assertEquals($value, $row[$field]); + $this->assertValues($value, $row[$field]); // test result from executeSql $exec = $db->execute(sprintf('SELECT %s FROM %s WHERE id = $1', $field, self::TABLE_NAME), [ @@ -290,7 +299,7 @@ public function testWriteAndReadBackArrayValue($id, $field, $value) if ($value instanceof Bytes) { $this->assertEquals($value->formatAsString(), $row[$field]->formatAsString()); } else { - $this->assertEquals($value, $row[$field]); + $this->assertValues($value, $row[$field]); } } @@ -1107,4 +1116,18 @@ public function testExecuteUpdateBatchMultipleErrors() $this->assertEquals(Code::INVALID_ARGUMENT, $res->error()['status']['code']); $this->assertEquals($statements[2], $res->error()['statement']); } + + private function assertValues($expected, $actual, $delta = 0.000001) + { + if (is_float($expected)) { + $this->assertEqualsWithDelta($expected, $actual, $delta); + } elseif (is_array($expected)) { + $this->assertCount(count($expected), $actual); + foreach ($expected as $key => $value) { + $this->assertValues($value, $actual[$key]); + } + } else { + $this->assertEquals($expected, $actual); + } + } } diff --git a/Spanner/tests/System/QueryTest.php b/Spanner/tests/System/QueryTest.php index 057f4a5a9bb..3e6f5a68c97 100644 --- a/Spanner/tests/System/QueryTest.php +++ b/Spanner/tests/System/QueryTest.php @@ -115,26 +115,6 @@ public function testBindBoolParameter() $this->assertTrue($row['foo']); } - /** - * covers 24 - */ - public function testBindBoolParameterNull() - { - $db = self::$database; - - $res = $db->execute('SELECT @param as foo', [ - 'parameters' => [ - 'param' => null - ], - 'types' => [ - 'param' => Database::TYPE_BOOL - ] - ]); - - $row = $res->rows()->current(); - $this->assertNull($row['foo']); - } - /** * covers 25 */ @@ -170,48 +150,57 @@ public function testBindInt64ParameterWithInt64Class() } /** - * covers 26 + * covers 27 */ - public function testBindNullIntParameter() + public function testBindFloat64Parameter() { $db = self::$database; + $pi = 3.1415; $res = $db->execute('SELECT @param as foo', [ 'parameters' => [ - 'param' => null - ], - 'types' => [ - 'param' => Database::TYPE_INT64 + 'param' => $pi ] ]); $row = $res->rows()->current(); - $this->assertNull($row['foo']); + $this->assertEquals($pi, $row['foo']); } /** * covers 27 */ - public function testBindFloat64Parameter() + public function testBindFloat32Parameter() { + $this->skipEmulatorTests(); $db = self::$database; $pi = 3.1415; - $res = $db->execute('SELECT @param as foo', [ + $res = $db->execute('SELECT cast(@param as FLOAT32) as foo', [ 'parameters' => [ 'param' => $pi ] ]); $row = $res->rows()->current(); - $this->assertEquals($pi, $row['foo']); + $this->assertEqualsWithDelta($pi, $row['foo'], 0.0001); } /** + * covers 24 + * covers 26 * covers 28 + * covers 30 + * covers 32 + * covers 34 + * covers 36 + * @dataProvider arrayTypesBindNull */ - public function testBindFloat64ParameterNull() + public function testBindTypeParameterNull($type) { + if ($type == Database::TYPE_FLOAT32) { + $this->skipEmulatorTests(); + } $db = self::$database; $res = $db->execute('SELECT @param as foo', [ @@ -219,7 +208,7 @@ public function testBindFloat64ParameterNull() 'param' => null ], 'types' => [ - 'param' => Database::TYPE_FLOAT64 + 'param' => $type ] ]); @@ -245,26 +234,6 @@ public function testBindStringParameter() $this->assertEquals($str, $row['foo']); } - /** - * covers 30 - */ - public function testBindStringParameterNull() - { - $db = self::$database; - - $res = $db->execute('SELECT @param as foo', [ - 'parameters' => [ - 'param' => null - ], - 'types' => [ - 'param' => Database::TYPE_STRING - ] - ]); - - $row = $res->rows()->current(); - $this->assertNull($row['foo']); - } - public function testBindNumericParameter() { $this->skipEmulatorTests(); @@ -323,26 +292,6 @@ public function testBindBytesParameter() $this->assertEquals($str, (string)$bytes->get()); } - /** - * covers 32 - */ - public function testBindBytesParameterNull() - { - $db = self::$database; - - $res = $db->execute('SELECT @param as foo', [ - 'parameters' => [ - 'param' => null - ], - 'types' => [ - 'param' => Database::TYPE_BYTES - ] - ]); - - $row = $res->rows()->current(); - $this->assertNull($row['foo']); - } - /** * covers 33 */ @@ -363,26 +312,6 @@ public function testBindTimestampParameter() $this->assertEquals($ts->get()->format('r'), $row['foo']->get()->format('r')); } - /** - * covers 34 - */ - public function testBindTimestampParameterNull() - { - $db = self::$database; - - $res = $db->execute('SELECT @param as foo', [ - 'parameters' => [ - 'param' => null - ], - 'types' => [ - 'param' => Database::TYPE_TIMESTAMP - ] - ]); - - $row = $res->rows()->current(); - $this->assertNull($row['foo']); - } - /** * covers 35 */ @@ -403,26 +332,6 @@ public function testBindDateParameter() $this->assertEquals($ts->get()->format('Y-m-d'), $row['foo']->get()->format('Y-m-d')); } - /** - * covers 36 - */ - public function testBindDateParameterNull() - { - $db = self::$database; - - $res = $db->execute('SELECT @param as foo', [ - 'parameters' => [ - 'param' => null - ], - 'types' => [ - 'param' => Database::TYPE_DATE - ] - ]); - - $row = $res->rows()->current(); - $this->assertNull($row['foo']); - } - public function testBindJsonParameter() { $this->skipEmulatorTests(); @@ -511,7 +420,7 @@ public function testBindArrayOfType($value, $result = null, $resultType = null, */ public function testBindEmptyArrayOfTypeLegacy($type) { - if ($type == Database::TYPE_NUMERIC) { + if (in_array($type, [Database::TYPE_NUMERIC, Database::TYPE_FLOAT32])) { $this->skipEmulatorTests(); } @@ -542,7 +451,7 @@ public function testBindEmptyArrayOfTypeLegacy($type) */ public function testBindEmptyArrayOfType($type) { - if ($type == Database::TYPE_NUMERIC) { + if (in_array($type, [Database::TYPE_NUMERIC, Database::TYPE_FLOAT32])) { $this->skipEmulatorTests(); } $db = self::$database; @@ -573,7 +482,7 @@ public function testBindEmptyArrayOfType($type) */ public function testBindNullArrayOfTypeLegacy($type) { - if ($type == Database::TYPE_NUMERIC) { + if (in_array($type, [Database::TYPE_NUMERIC, Database::TYPE_FLOAT32])) { $this->skipEmulatorTests(); } @@ -605,7 +514,7 @@ public function testBindNullArrayOfTypeLegacy($type) */ public function testBindNullArrayOfType($type) { - if ($type == Database::TYPE_NUMERIC) { + if (in_array($type, [Database::TYPE_NUMERIC, Database::TYPE_FLOAT32])) { $this->skipEmulatorTests(); } @@ -781,11 +690,26 @@ function (array $res) { ]; } + public function arrayTypesBindNull() + { + return [ + [Database::TYPE_BOOL], + [Database::TYPE_INT64], + [Database::TYPE_FLOAT32], + [Database::TYPE_FLOAT64], + [Database::TYPE_STRING], + [Database::TYPE_BYTES], + [Database::TYPE_TIMESTAMP], + [Database::TYPE_DATE], + ]; + } + public function arrayTypesEmpty() { return [ [Database::TYPE_BOOL], [Database::TYPE_INT64], + [Database::TYPE_FLOAT32], [Database::TYPE_FLOAT64], [Database::TYPE_STRING], [Database::TYPE_BYTES], @@ -800,6 +724,7 @@ public function arrayTypesNull() return [ [Database::TYPE_BOOL], [Database::TYPE_INT64], + [Database::TYPE_FLOAT32], [Database::TYPE_FLOAT64], [Database::TYPE_STRING], [Database::TYPE_BYTES], @@ -994,6 +919,7 @@ public function testBindStructParameterEqualityCheck() ]); $row = $res->rows()->current(); + $this->assertTrue($row[0]); } /** diff --git a/Spanner/tests/System/SpannerPgTestCase.php b/Spanner/tests/System/SpannerPgTestCase.php index e12ce360c56..0de06236396 100644 --- a/Spanner/tests/System/SpannerPgTestCase.php +++ b/Spanner/tests/System/SpannerPgTestCase.php @@ -120,8 +120,6 @@ public static function getDatabaseWithSessionPool($dbName, $options = []) public static function getDatabaseInstance($dbName) { - $keyFilePath = getenv('GOOGLE_CLOUD_PHP_TESTS_KEY_PATH'); - return self::$client->connect(self::INSTANCE_NAME, $dbName); } diff --git a/Spanner/tests/System/WriteTest.php b/Spanner/tests/System/WriteTest.php index 6b330b8acf9..07b17dad44c 100644 --- a/Spanner/tests/System/WriteTest.php +++ b/Spanner/tests/System/WriteTest.php @@ -51,6 +51,7 @@ public static function setUpBeforeClass(): void arrayField ARRAY, arrayBoolField ARRAY, arrayFloatField ARRAY, + arrayFloat32Field ARRAY, arrayStringField ARRAY, arrayBytesField ARRAY, arrayTimestampField ARRAY, @@ -60,6 +61,7 @@ public static function setUpBeforeClass(): void bytesField BYTES(MAX), dateField DATE, floatField FLOAT64, + float32Field FLOAT32, intField INT64, stringField STRING(MAX), timestampField TIMESTAMP, @@ -83,6 +85,9 @@ public function fieldValueProvider() [$this->randId(), 'floatField', 3.1415], [$this->randId(), 'floatField', INF], [$this->randId(), 'floatField', -INF], + [$this->randId(), 'float32Field', 3.1415], + [$this->randId(), 'float32Field', INF], + [$this->randId(), 'float32Field', -INF], [$this->randId(), 'intField', 787878787], [$this->randId(), 'stringField', 'foo bar'], [$this->randId(), 'timestampField', new Timestamp(new \DateTime)], @@ -117,7 +122,7 @@ public function testWriteAndReadBackValue($id, $field, $value) if ($value instanceof Timestamp) { $this->assertEquals($value->formatAsString(), $row[$field]->formatAsString()); } else { - $this->assertEquals($value, $row[$field]); + $this->assertValues($value, $row[$field]); } // test result from executeSql @@ -131,7 +136,7 @@ public function testWriteAndReadBackValue($id, $field, $value) if ($value instanceof Timestamp) { $this->assertEquals($value->formatAsString(), $row[$field]->formatAsString()); } else { - $this->assertEquals($value, $row[$field]); + $this->assertValues($value, $row[$field]); } } @@ -257,6 +262,10 @@ public function arrayFieldValueProvider() [$this->randId(), 'arrayFloatField', []], [$this->randId(), 'arrayFloatField', [1.1, null, 1.3]], [$this->randId(), 'arrayFloatField', null], + [$this->randId(), 'arrayFloat32Field', [1.1, 1.2, 1.3]], + [$this->randId(), 'arrayFloat32Field', []], + [$this->randId(), 'arrayFloat32Field', [1.1, null, 1.3]], + [$this->randId(), 'arrayFloat32Field', null], [$this->randId(), 'arrayStringField', ['foo','bar','baz']], [$this->randId(), 'arrayStringField', []], [$this->randId(), 'arrayStringField', ['foo',null,'baz']], @@ -310,7 +319,7 @@ public function testWriteAndReadBackFancyArrayValue($id, $field, $value) $read = $db->read(self::TABLE_NAME, $keyset, [$field]); $row = $read->rows()->current(); - $this->assertEquals($value, $row[$field]); + $this->assertValues($value, $row[$field]); // test result from executeSql $exec = $db->execute(sprintf('SELECT %s FROM %s WHERE id = @id', $field, self::TABLE_NAME), [ @@ -324,7 +333,7 @@ public function testWriteAndReadBackFancyArrayValue($id, $field, $value) if ($value instanceof Bytes) { $this->assertEquals($value->formatAsString(), $row[$field]->formatAsString()); } else { - $this->assertEquals($value, $row[$field]); + $this->assertValues($value, $row[$field]); } } @@ -1145,4 +1154,18 @@ public function testExecuteUpdateBatchMultipleErrors() $this->assertEquals(Code::INVALID_ARGUMENT, $res->error()['status']['code']); $this->assertEquals($statements[2], $res->error()['statement']); } + + private function assertValues($expected, $actual, $delta = 0.000001) + { + if (is_float($expected)) { + $this->assertEqualsWithDelta($expected, $actual, $delta); + } elseif (is_array($expected)) { + $this->assertCount(count($expected), $actual); + foreach ($expected as $key => $value) { + $this->assertValues($value, $actual[$key]); + } + } else { + $this->assertEquals($expected, $actual); + } + } } diff --git a/Spanner/tests/Unit/ValueMapperTest.php b/Spanner/tests/Unit/ValueMapperTest.php index 40d19142d68..c33e7402904 100644 --- a/Spanner/tests/Unit/ValueMapperTest.php +++ b/Spanner/tests/Unit/ValueMapperTest.php @@ -822,30 +822,39 @@ public function testDecodeValuesInt64Object() $this->assertEquals('555', $res['rowName']->get()); } - public function testDecodeValuesFloat() + /** + * @dataProvider provideFloatTypes + */ + public function testDecodeValuesFloat($type) { $res = $this->mapper->decodeValues( - $this->createField(Database::TYPE_FLOAT64), + $this->createField($type), $this->createRow(3.1415), Result::RETURN_ASSOCIATIVE ); $this->assertEquals(3.1415, $res['rowName']); } - public function testDecodeValuesFloatNaN() + /** + * @dataProvider provideFloatTypes + */ + public function testDecodeValuesFloatNaN($type) { $res = $this->mapper->decodeValues( - $this->createField(Database::TYPE_FLOAT64), + $this->createField($type), $this->createRow('NaN'), Result::RETURN_ASSOCIATIVE ); $this->assertTrue(is_nan($res['rowName'])); } - public function testDecodeValuesFloatInfinity() + /** + * @dataProvider provideFloatTypes + */ + public function testDecodeValuesFloatInfinity($type) { $res = $this->mapper->decodeValues( - $this->createField(Database::TYPE_FLOAT64), + $this->createField($type), $this->createRow('Infinity'), Result::RETURN_ASSOCIATIVE ); @@ -854,10 +863,13 @@ public function testDecodeValuesFloatInfinity() $this->assertGreaterThan(0, $res['rowName']); } - public function testDecodeValuesFloatNegativeInfinity() + /** + * @dataProvider provideFloatTypes + */ + public function testDecodeValuesFloatNegativeInfinity($type) { $res = $this->mapper->decodeValues( - $this->createField(Database::TYPE_FLOAT64), + $this->createField($type), $this->createRow('-Infinity'), Result::RETURN_ASSOCIATIVE ); @@ -866,12 +878,15 @@ public function testDecodeValuesFloatNegativeInfinity() $this->assertLessThan(0, $res['rowName']); } - public function testDecodeValuesFloatError() + /** + * @dataProvider provideFloatTypes + */ + public function testDecodeValuesFloatError($type) { $this->expectException('RuntimeException'); $res = $this->mapper->decodeValues( - $this->createField(Database::TYPE_FLOAT64), + $this->createField($type), $this->createRow('foo'), Result::RETURN_ASSOCIATIVE ); @@ -1059,4 +1074,12 @@ private function createRow($val) { return [$val]; } + + public function provideFloatTypes() + { + return [ + [Database::TYPE_FLOAT64], + [Database::TYPE_FLOAT32] + ]; + } }