Skip to content

Commit

Permalink
Merge branch 'postgresql-dialect' into php-pdo-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
olavloite committed Jun 19, 2024
2 parents 3b9bbbf + ce7387e commit 96b7393
Show file tree
Hide file tree
Showing 19 changed files with 1,212 additions and 109 deletions.
10 changes: 10 additions & 0 deletions .github/workflows/units.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ jobs:
with:
python-version: '3.9'
- run: python --version
- uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
tools: composer
- run: php --version
- uses: actions/setup-node@v4
with:
node-version: 16
Expand Down Expand Up @@ -76,6 +81,11 @@ jobs:
with:
python-version: '3.9'
- run: python --version
- uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
tools: composer
- run: php --version
- uses: actions/setup-dotnet@v4
with:
dotnet-version: '6.0.x'
Expand Down
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
com.google.cloud.spanner.pgadapter.golang.GolangTest,
com.google.cloud.spanner.pgadapter.csharp.DotnetTest,
com.google.cloud.spanner.pgadapter.python.PythonTest,
com.google.cloud.spanner.pgadapter.python.PhpTest,
com.google.cloud.spanner.pgadapter.nodejs.NodeJSTest,
com.google.cloud.spanner.pgadapter.ruby.RubyTest,
</excludedTests>
Expand Down
2 changes: 1 addition & 1 deletion samples/python/sqlalchemy2-sample/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
psycopg[binary]==3.1.18
pytz==2024.1
sqlalchemy==2.0.27
sqlalchemy==2.0.31
google~=3.0.0
google.auth~=2.30.0
testcontainers~=4.5.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -617,13 +617,19 @@ static ParsedCopyStatement parse(String sql) {
}
builder.direction = Direction.valueOf(parser.readKeyword().toUpperCase());
if (builder.direction == Direction.FROM) {
if (!parser.eatKeyword("stdin")) {
// Silently ignore typo 'copy from stdout'.
// See
// https://github.com/postgres/postgres/blob/03ec203164119f11f0eab4c83c97a8527e2b108d/src/backend/parser/gram.y#L3463
if (!parser.eatKeyword("stdin") && !parser.eatKeyword("stdout")) {
throw PGExceptionFactory.newPGException(
"missing 'STDIN' keyword. PGAdapter only supports COPY ... FROM STDIN: " + sql,
SQLState.SyntaxError);
}
} else {
if (!parser.eatKeyword("stdout")) {
// Silently ignore typo 'copy to stdin'.
// See
// https://github.com/postgres/postgres/blob/03ec203164119f11f0eab4c83c97a8527e2b108d/src/backend/parser/gram.y#L3463
if (!parser.eatKeyword("stdout") && !parser.eatKeyword("stdin")) {
throw PGExceptionFactory.newPGException(
"missing 'STDOUT' keyword. PGAdapter only supports COPY ... TO STDOUT: " + sql,
SQLState.SyntaxError);
Expand Down
17 changes: 17 additions & 0 deletions src/test/java/com/google/cloud/spanner/pgadapter/php/PhpTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.cloud.spanner.pgadapter.php;

public interface PhpTest {}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.google.cloud.spanner.Statement;
import com.google.cloud.spanner.pgadapter.AbstractMockServerTest;
import com.google.cloud.spanner.pgadapter.CopyInMockServerTest;
import com.google.cloud.spanner.pgadapter.php.PhpTest;
import com.google.common.collect.ImmutableList;
import com.google.protobuf.ByteString;
import com.google.protobuf.ListValue;
Expand All @@ -49,14 +50,22 @@
import java.util.Base64;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

@RunWith(JUnit4.class)
@Category(PhpTest.class)
public class PdoMockServerTest extends AbstractMockServerTest {
static final String DIRECTORY_NAME = "./src/test/php/pdo";

@BeforeClass
public static void installDependencies() throws Exception {
run(new String[] {"composer", "install"}, DIRECTORY_NAME);
}

static String execute(String method) throws Exception {
return run(
new String[] {"php", "pdo_test.php", method, String.valueOf(pgServer.getLocalPort())},
Expand Down Expand Up @@ -632,12 +641,7 @@ public void testTextCopyIn() throws Exception {
public void testTextCopyOut() throws Exception {
mockSpanner.putStatementResult(
StatementResult.query(
Statement.of(
"select col_bigint, col_bool, col_bytea, col_float4, col_float8, col_int, "
+ "col_numeric, col_timestamptz, col_date, col_varchar, col_jsonb, "
+ "col_array_bigint, col_array_bool, col_array_bytea, col_array_float4, "
+ "col_array_float8, col_array_int, col_array_numeric, col_array_timestamptz, "
+ "col_array_date, col_array_varchar, col_array_jsonb from all_types"),
Statement.of("select * from all_types"),
ALL_TYPES_RESULTSET
.toBuilder()
.addAllRows(ALL_TYPES_NULLS_RESULTSET.getRowsList())
Expand All @@ -648,50 +652,13 @@ public void testTextCopyOut() throws Exception {

String result = execute("text_copy_out");
assertEquals(
"col_bigint: 1\n"
+ "col_bool: True\n"
+ "col_bytea: b'test'\n"
+ "col_float4: 3.14\n"
+ "col_float8: 3.14\n"
+ "col_int: 100\n"
+ "col_numeric: 6.626\n"
+ "col_timestamptz: 2022-02-16 13:18:02.123456+00:00\n"
+ "col_date: 2022-03-29\n"
+ "col_string: test\n"
+ "col_jsonb: {'key': 'value'}\n"
+ "col_array_bigint: [1, None, 2]\n"
+ "col_array_bool: [True, None, False]\n"
+ "col_array_bytea: [b'bytes1', None, b'bytes2']\n"
+ "col_array_float4: [3.14, None, -99.99]\n"
+ "col_array_float8: [3.14, None, -99.99]\n"
+ "col_array_int: [-100, None, -200]\n"
+ "col_array_numeric: [Decimal('6.626'), None, Decimal('-3.14')]\n"
+ "col_array_timestamptz: [datetime.datetime(2022, 2, 16, 16, 18, 2, 123456, tzinfo=<UTC>), None, datetime.datetime(2000, 1, 1, 0, 0, tzinfo=<UTC>)]\n"
+ "col_array_date: [datetime.date(2023, 2, 20), None, datetime.date(2000, 1, 1)]\n"
+ "col_array_string: ['string1', None, 'string2']\n"
+ "col_array_jsonb: [{'key': 'value1'}, None, {'key': 'value2'}]\n"
+ "col_bigint: None\n"
+ "col_bool: None\n"
+ "col_bytea: None\n"
+ "col_float4: None\n"
+ "col_float8: None\n"
+ "col_int: None\n"
+ "col_numeric: None\n"
+ "col_timestamptz: None\n"
+ "col_date: None\n"
+ "col_string: None\n"
+ "col_jsonb: None\n"
+ "col_array_bigint: None\n"
+ "col_array_bool: None\n"
+ "col_array_bytea: None\n"
+ "col_array_float4: None\n"
+ "col_array_float8: None\n"
+ "col_array_int: None\n"
+ "col_array_numeric: None\n"
+ "col_array_timestamptz: None\n"
+ "col_array_date: None\n"
+ "col_array_string: None\n"
+ "col_array_jsonb: None\n",
"Array\n"
+ "(\n"
+ " [0] => 1\tt\t\\\\x74657374\t3.14\t3.14\t100\t6.626\t2022-02-16 14:18:02.123456+01\t2022-03-29\ttest\t{\"key\": \"value\"}\t{1,NULL,2}\t{t,NULL,f}\t{\"\\\\\\\\x627974657331\",NULL,\"\\\\\\\\x627974657332\"}\t{3.14,NULL,-99.99}\t{3.14,NULL,-99.99}\t{-100,NULL,-200}\t{6.626,NULL,-3.14}\t{\"2022-02-16 17:18:02.123456+01\",NULL,\"2000-01-01 01:00:00+01\"}\t{\"2023-02-20\",NULL,\"2000-01-01\"}\t{\"string1\",NULL,\"string2\"}\t{\"{\\\\\"key\\\\\": \\\\\"value1\\\\\"}\",NULL,\"{\\\\\"key\\\\\": \\\\\"value2\\\\\"}\"}\n"
+ "\n"
+ " [1] => \\N\t\\N\t\\N\t\\N\t\\N\t\\N\t\\N\t\\N\t\\N\t\\N\t\\N\t\\N\t\\N\t\\N\t\\N\t\\N\t\\N\t\\N\t\\N\t\\N\t\\N\t\\N\n"
+ "\n"
+ ")\n",
result);
}

Expand Down Expand Up @@ -730,17 +697,19 @@ public void testReadWriteTransaction() throws Exception {
}

String result = execute("read_write_transaction");
assertEquals("Array\n"
+ "(\n"
+ " [0] => Array\n"
+ " (\n"
+ " [C] => 1\n"
+ " [0] => 1\n"
+ " )\n"
+ "\n"
+ ")\n"
+ "Insert count: 1\n"
+ "Insert count: 1\n", result);
assertEquals(
"Array\n"
+ "(\n"
+ " [0] => Array\n"
+ " (\n"
+ " [C] => 1\n"
+ " [0] => 1\n"
+ " )\n"
+ "\n"
+ ")\n"
+ "Insert count: 1\n"
+ "Insert count: 1\n",
result);

List<ExecuteSqlRequest> select1Requests =
mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream()
Expand Down Expand Up @@ -770,24 +739,26 @@ public void testReadWriteTransaction() throws Exception {
@Test
public void testReadOnlyTransaction() throws Exception {
String result = execute("read_only_transaction");
assertEquals("Array\n"
+ "(\n"
+ " [0] => Array\n"
+ " (\n"
+ " [C] => 1\n"
+ " [0] => 1\n"
+ " )\n"
+ "\n"
+ ")\n"
+ "Array\n"
+ "(\n"
+ " [0] => Array\n"
+ " (\n"
+ " [C] => 2\n"
+ " [0] => 2\n"
+ " )\n"
+ "\n"
+ ")\n", result);
assertEquals(
"Array\n"
+ "(\n"
+ " [0] => Array\n"
+ " (\n"
+ " [C] => 1\n"
+ " [0] => 1\n"
+ " )\n"
+ "\n"
+ ")\n"
+ "Array\n"
+ "(\n"
+ " [0] => Array\n"
+ " (\n"
+ " [C] => 2\n"
+ " [0] => 2\n"
+ " )\n"
+ "\n"
+ ")\n",
result);

assertEquals(1, mockSpanner.countRequestsOfType(BeginTransactionRequest.class));
BeginTransactionRequest beginTransactionRequest =
Expand Down Expand Up @@ -819,33 +790,6 @@ private static String getInsertAllTypesSql() {
+ " values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)";
}

private static Statement createBatchInsertStatement(int index) {
return Statement.newBuilder(getInsertAllTypesSql())
.bind("p1")
.to(100L + index)
.bind("p2")
.to(index % 2 == 0)
.bind("p3")
.to(ByteArray.copyFrom(index + "test_bytes"))
.bind("p4")
.to(3.14d + index)
.bind("p5")
.to(3.14d + index)
.bind("p6")
.to(index)
.bind("p7")
.to(com.google.cloud.spanner.Value.pgNumeric(index + ".123"))
.bind("p8")
.to(Timestamp.parseTimestamp(String.format("2022-03-24T%02d:39:10.123456000Z", index)))
.bind("p9")
.to(Date.parseDate(String.format("2022-04-%02d", index + 1)))
.bind("p10")
.to("test_string" + index)
.bind("p11")
.to(com.google.cloud.spanner.Value.pgJsonb(String.format("{\"key\": \"value%d\"}", index)))
.build();
}

private void addDescribeInsertAllTypesResult() {
mockSpanner.putStatementResult(
StatementResult.query(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ public void testParseNonCopy() {
public void testParseDirection() {
assertEquals(Direction.FROM, parse("copy my_table from stdin").direction);
assertEquals(Direction.TO, parse("copy my_table to stdout").direction);

// PostgreSQL accepts this kind of typo.
// See
// https://github.com/postgres/postgres/blob/03ec203164119f11f0eab4c83c97a8527e2b108d/src/backend/parser/gram.y#L3463
assertEquals(Direction.FROM, parse("copy my_table from stdout").direction);
assertEquals(Direction.TO, parse("copy my_table to stdin").direction);

// COPY BOTH is not supported.
assertThrows(PGException.class, () -> parse("copy my_table both stdin"));
}

Expand Down
21 changes: 21 additions & 0 deletions src/test/php/pdo/composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 25 additions & 0 deletions src/test/php/pdo/vendor/autoload.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

// autoload.php @generated by Composer

if (PHP_VERSION_ID < 50600) {
if (!headers_sent()) {
header('HTTP/1.1 500 Internal Server Error');
}
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
if (!ini_get('display_errors')) {
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
fwrite(STDERR, $err);
} elseif (!headers_sent()) {
echo $err;
}
}
trigger_error(
$err,
E_USER_ERROR
);
}

require_once __DIR__ . '/composer/autoload_real.php';

return ComposerAutoloaderInitc75ef659c589a20a2fcbcffb69d4ef7d::getLoader();
Loading

0 comments on commit 96b7393

Please sign in to comment.