Skip to content

PostgreSQL UDF Support - #4240

Open
c2nes wants to merge 16 commits into
GoogleCloudPlatform:mainfrom
c2nes:pg-udf
Open

c2nes wants to merge 16 commits into
GoogleCloudPlatform:mainfrom
c2nes:pg-udf

Conversation

@c2nes

@c2nes c2nes commented Sep 9, 2026

Copy link
Copy Markdown

Adding support for UDFs in the PostgreSQL dialect.

Note, this PR is based on the previously reviewed #3325.

This PR has been rebased, review comments addressed, and a few test failures addressed.

MnkyGns and others added 14 commits September 9, 2026 14:09
…lity

This change updates the UdfParameter.parse method to use the database dialect for determining the correct quote character (backticks for GoogleSQL, double quotes for PostgreSQL). It also refactors the string processing logic to avoid manual index manipulation, leveraging regex-based splitting for the DEFAULT expression.

Additionally, it includes a fix for a compilation error in DirectRunnerClient.java by replacing a deprecated/missing stop() call with interrupt().

New unit tests have been added to verify correct parsing of quoted identifiers and default expressions across dialects.
This change adds integration tests to ExportPipelineIT and ImportPipelineIT
to verify that User-Defined Functions (UDFs) are correctly exported and
imported across different Spanner dialects (GoogleSQL and PostgreSQL).

- Added UDF definitions to test DDL files.
- Updated ExportPipelineIT to verify UDF artifacts in GCS.
- Added testPostgresImportPipeline_UDF to ImportPipelineIT to verify
  UDF restoration from Avro artifacts.
- Included necessary Avro and manifest resources for the import test.
- Replaced manual index manipulation with regex in UdfParameter.parse for better readability and robust dialect support.
- Added support for PostgreSQL types with spaces (e.g., 'double precision') in UdfParameter.parse.
- Preserved GoogleSQL single-word type restriction to minimize behavioral changes.
- Added unit tests for PostgreSQL types with spaces.
- Fixed unused import in InformationSchemaScannerTest.java.
- Delete pr_comments.json per PR review feedback.
- Fix Ddl.Builder.createUdf to pass dialect to Udf.builder(dialect) so scanned PostgreSQL UDFs retain Dialect.POSTGRESQL.
- Fix PostgreSQL UDF parameter quoting and determinism assertions in ExportPipelineIT.
- Add missing pg_multiply.avro resource and fix manifest filenames and Base64 MD5 checksums for ImportPipelineIT.
- Reintroduce PostgreSQL UDF coverage in CopyDbIT-AllSchemaAndData-pg.sql and AvroSchemaToDdlConverterTest.

TAG=agy
CONV=f1c413a3-3f8a-43cd-8eac-9b7a2df210e0
@c2nes
c2nes requested a review from a team as a code owner September 9, 2026 16:40
@google-cla

google-cla Bot commented Sep 9, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces support for User-Defined Functions (UDFs) within the PostgreSQL dialect for Spanner Dataflow templates. It enables the export and import of PostgreSQL UDFs by mapping determinism levels to volatility keywords and enhancing parameter parsing to handle quoted identifiers and default values. These changes ensure consistency and compatibility when migrating or exporting Spanner databases using the PostgreSQL dialect.

Highlights

  • PostgreSQL UDF Support: Added full support for User-Defined Functions (UDFs) in the PostgreSQL dialect for Spanner Dataflow templates.
  • Determinism Mapping: Implemented mapping for spannerDeterminism to PostgreSQL volatility keywords (IMMUTABLE, STABLE, VOLATILE).
  • Parameter Parsing: Enhanced UDF parameter parsing to correctly handle quoted identifiers and default values in PostgreSQL.
  • Information Schema Integration: Updated the InformationSchemaScanner to extract PostgreSQL UDF metadata, including determinism and parameter details.
  • Testing: Added comprehensive unit and integration tests to verify end-to-end export and import workflows for PostgreSQL UDFs.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for User-Defined Functions (UDFs) in the PostgreSQL dialect for Cloud Spanner, including metadata extraction, Avro schema conversion, and SQL generation. The review feedback highlights critical improvements to the parsing logic in UdfParameter.parse, such as fixing a regex bug where Pattern.quote is incorrectly used inside a character class, and addressing a split-logic issue that could bypass empty default expression checks. Additionally, suggestions are made to increase robustness by trimming input parameters and handling case-insensitivity for determinism values. All comments are highly actionable and should be addressed.

Comment thread v1/src/main/java/com/google/cloud/teleport/spanner/ddl/UdfParameter.java Outdated
Comment thread v1/src/main/java/com/google/cloud/teleport/spanner/ddl/Udf.java Outdated
@codecov

codecov Bot commented Sep 9, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.88889% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 56.33%. Comparing base (d3d4c76) to head (41c7fbb).
⚠️ Report is 35 commits behind head on main.

Files with missing lines Patch % Lines
...ava/com/google/cloud/teleport/spanner/ddl/Udf.java 71.42% 2 Missing and 2 partials ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main    #4240      +/-   ##
============================================
+ Coverage     55.85%   56.33%   +0.48%     
+ Complexity     7488     7412      -76     
============================================
  Files          1135     1155      +20     
  Lines         70313    73245    +2932     
  Branches       8040     8589     +549     
============================================
+ Hits          39271    41263    +1992     
- Misses        28490    29192     +702     
- Partials       2552     2790     +238     
Components Coverage Δ
spanner-templates 84.45% <ø> (+0.25%) ⬆️
spanner-import-export 69.00% <88.88%> (+0.10%) ⬆️
spanner-live-forward-migration 88.89% <ø> (+0.24%) ⬆️
spanner-live-reverse-replication 80.81% <ø> (+0.44%) ⬆️
spanner-bulk-migration 88.95% <ø> (-0.12%) ⬇️
gcs-spanner-dv 88.00% <ø> (+0.02%) ⬆️
Files with missing lines Coverage Δ
...oud/teleport/spanner/AvroSchemaToDdlConverter.java 88.44% <100.00%> (+1.16%) ⬆️
...va/com/google/cloud/teleport/spanner/AvroUtil.java 93.75% <ø> (ø)
...oud/teleport/spanner/DdlToAvroSchemaConverter.java 97.56% <100.00%> (+0.01%) ⬆️
...ava/com/google/cloud/teleport/spanner/ddl/Ddl.java 77.50% <100.00%> (ø)
...oogle/cloud/teleport/spanner/ddl/UdfParameter.java 84.78% <100.00%> (+5.23%) ⬆️
...ava/com/google/cloud/teleport/spanner/ddl/Udf.java 83.33% <71.42%> (-0.83%) ⬇️

... and 48 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…ameter

- Trim parameter string at the start of UdfParameter.parse.
- Pass quote character directly in UdfParameter.parse regex.
- Use word boundary (?i)\s+DEFAULT\b when splitting DEFAULT expression in UdfParameter.parse.
- Match spannerDeterminism() case-insensitively in Udf.prettyPrint.
- Add unit tests in UdfParameterTest and UdfTest.

TAG=agy
CONV=f1c413a3-3f8a-43cd-8eac-9b7a2df210e0
…rameter scan

- Filter out EXTERNAL routines (such as PostgreSQL change stream read_json_*
  functions) in InformationSchemaScanner.listFunctionParametersSQL() to match
  listUdfs() and listUdfOptions().
- Move UDFs in ExportPipelineIT, ImportPipelineIT, and CopyDbIT into named
  schemas, as Cloud Spanner disallows UDFs in the default schema.
- Replace unsupported 'AS ...' SQL function bodies in PostgreSQL DDL test
  resources with 'RETURN (SELECT ...)'.
- Update PostgreSQL UDF type/definition/default expectations in ExportPipelineIT,
  ImportPipelineIT, and InformationSchemaScannerIT to match Spanner PostgreSQL
  information_schema output.

TAG=agy
CONV=f1c413a3-3f8a-43cd-8eac-9b7a2df210e0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants