From 2e12cdc2e188a1e0d19e7513d228eeefb3d02685 Mon Sep 17 00:00:00 2001 From: Vaibhav <117663341+7ttp@users.noreply.github.com> Date: Tue, 21 Jul 2026 21:04:50 +0530 Subject: [PATCH] fix: empty search_path (#48151) ## TL;DR Restores handling for functions with `search_path` set to `''` editing them in the UI was failing with a Postgres `zero-length delimited identifier` error since the SafeSql refactor dropped the empty-string sentinel conversion ## ref - closes #48149 ## Summary by CodeRabbit * **Bug Fixes** * Preserved empty `search_path` configuration values when updating database functions. * Prevented empty configuration values from being altered or lost during function updates. * **Tests** * Added coverage verifying that function definitions can be updated without changing an existing empty `search_path` setting. --- packages/pg-meta/src/pg-meta-functions.ts | 2 +- packages/pg-meta/test/functions.test.ts | 32 +++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/packages/pg-meta/src/pg-meta-functions.ts b/packages/pg-meta/src/pg-meta-functions.ts index 45054a18dc8..473dd066d4f 100644 --- a/packages/pg-meta/src/pg-meta-functions.ts +++ b/packages/pg-meta/src/pg-meta-functions.ts @@ -260,7 +260,7 @@ function _generateCreateFunctionSql( Object.entries(config_params).map(([param, value]) => value === 'FROM CURRENT' ? safeSql`SET ${qualifiedIdent(param)} FROM CURRENT` - : safeSql`SET ${qualifiedIdent(param)} TO ${value}` + : safeSql`SET ${qualifiedIdent(param)} TO ${value === '""' ? literal('') : value}` ), '\n' ) diff --git a/packages/pg-meta/test/functions.test.ts b/packages/pg-meta/test/functions.test.ts index bc7c38d892f..2d5120534e5 100644 --- a/packages/pg-meta/test/functions.test.ts +++ b/packages/pg-meta/test/functions.test.ts @@ -349,6 +349,38 @@ withTestDatabase('create function with various config_params values', async ({ e await executeQuery(removeSql1) }) +withTestDatabase('update function with empty string search_path', async ({ executeQuery }) => { + const { sql: createSql } = pgMeta.functions.create({ + name: 'test_func_empty_search_path', + schema: 'public', + definition: 'select 1', + return_type: safeSql`integer`, + language: 'sql', + config_params: { search_path: safeSql`''` }, + }) + await executeQuery(createSql) + + const { sql: retrieveSql, zod: retrieveZod } = pgMeta.functions.retrieve({ + name: 'test_func_empty_search_path', + schema: 'public', + args: [], + }) + const result = retrieveZod.parse((await executeQuery(retrieveSql))[0]) + expect(result!.config_params).toEqual({ search_path: '""' }) + + const { sql: updateSql } = pgMeta.functions.update(asSavedFunction(result!), { + definition: 'select 2', + }) + await executeQuery(updateSql) + + const resultUpdated = retrieveZod.parse((await executeQuery(retrieveSql))[0]) + expect(resultUpdated!.definition).toBe('select 2') + expect(resultUpdated!.config_params).toEqual({ search_path: '""' }) + + const { sql: removeSql } = pgMeta.functions.remove(asSavedFunction(resultUpdated!)) + await executeQuery(removeSql) +}) + withTestDatabase( 'create function with namespaced custom GUC config_params', async ({ executeQuery }) => {