Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Spanner): Proto Columns #8108

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open

feat(Spanner): Proto Columns #8108

wants to merge 6 commits into from

Conversation

bshaffer
Copy link
Contributor

@bshaffer bshaffer commented Feb 24, 2025

Spanner Proto Columns

Create a database with proto columns

use Google\Cloud\Spanner\Admin\Database\V1\Client\DatabaseAdminClient;
use Google\Cloud\Spanner\Admin\Database\V1\CreateDatabaseRequest;

// The result of running `protoc` with `--descriptor_set_out` on your proto file(s)
$fileDescriptorSet = file_get_contents('data/user.pb');

$databaseAdminClient = new DatabaseAdminClient();
$instance = $databaseAdminClient->instanceName($projectId, $instanceId);

$operation = $databaseAdminClient->createDatabase(
    new CreateDatabaseRequest([
        'parent' => $instance,
        'create_statement' => sprintf('CREATE DATABASE `%s`', $databaseId),
        'proto_descriptors' => $fileDescriptorSet,
        'extra_statements' => [
             // Define the proto messages you'll be using in your table definition
            'CREATE PROTO BUNDLE (' .
                'testing.data.User,' .
                'testing.data.User.Address,' .
                'testing.data.Book' .
            ')',
            // Define the Proto column or proto column array
            'CREATE TABLE Users (' .
                'Id INT64,' .
                'User `testing.data.User`,' .
                'Books ARRAY<`testing.data.Book`>,' .
            ') PRIMARY KEY (Id)'
        ],
    ])
);

$operation->pollUntilComplete();

Insert data with proto columns

use Google\Cloud\Spanner\SpannerClient;
use Google\Cloud\Spanner\Proto;
use Testing\Data\User;
use Testing\Data\Book;

$spanner = new SpannerClient();
$database = $spanner->instance($instanceId)->database($databaseId);

$address = (new User\Address())
    ->setCity('San Francisco')
    ->setState('CA');
$user = (new User())
    ->setName('Test User 1')
    ->setAddress($address);

$book1 = new Book(['title' => 'Book 1', 'author' => 'Author 1']);
$book2 = new Book(['title' => 'Book 2', 'author' => 'Author 2']);

$books = [
    // insert using the proto message
    $book1,
    // insert using the Proto wrapper class
    new Proto(
        base64_encode($book2->serializeToString()),
        'testing.data.Book'
    ),
];

$transaction = $database->transaction(['singleUse' => true])
    ->insertBatch('Users', [
        ['Id' => $userId, 'User' => $user, 'Books' => $books],
    ]);
$transaction->commit();

Query data with proto columns

use Google\Cloud\Spanner\SpannerClient;
use Google\Cloud\Spanner\Proto;
use Testing\Data\User;
use Testing\Data\Book;

$spanner = new SpannerClient();
$database = $spanner->instance($instanceId)->database($databaseId);

$userProto = (new User())
    ->setName('Test User ' . $userId);

$results = $database->execute(
    'SELECT * FROM Users, UNNEST(Books) as Book '
    . 'WHERE User.name = @user.name '
    . 'AND Book.title = @bookTitle',
    [
        'parameters' => [
            'user' => $userProto,
            'bookTitle' => 'Book 1',
        ],
    ]
);
foreach ($results as $row) {
    /** @var User $user */
    $user = $row['User']->get();

    /** @var Proto<Book> $book */
    foreach ($row['Books'] ?? [] as $book) {
        // Print the raw row value
        printf('Book: %s (%s)' . PHP_EOL, $book->getValue(), $book->getProtoTypeFqn());
    }
}

@bshaffer bshaffer requested a review from a team as a code owner February 24, 2025 19:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api: spanner Issues related to the Spanner API.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants