diff --git a/src/spanner/adapter.ts b/src/spanner/adapter.ts index 16910d6..acb2c30 100644 --- a/src/spanner/adapter.ts +++ b/src/spanner/adapter.ts @@ -190,6 +190,8 @@ function cleanParamsForSpanner( if (!params) return undefined; const cleaned: Record = {}; + let hasKeys = false; + for (const key in params) { if (Object.prototype.hasOwnProperty.call(params, key)) { const hint = typeHints?.[key]; @@ -199,9 +201,12 @@ function cleanParamsForSpanner( } else { cleaned[key] = params[key]; } + hasKeys = true; } } - return cleaned; + + // Return undefined if params is empty to avoid sending empty object to Spanner + return hasKeys ? cleaned : undefined; } // Helper function to automatically infer Spanner types from JavaScript values @@ -488,9 +493,13 @@ export class SpannerAdapter implements DatabaseAdapter { try { const updateOptions: any = { sql, - params: cleanedParams, }; + // Only add params if they exist + if (cleanedParams !== undefined) { + updateOptions.params = cleanedParams; + } + // Add types if provided if (types) { updateOptions.types = types; @@ -587,10 +596,14 @@ export class SpannerAdapter implements DatabaseAdapter { const queryOptions: any = { sql, - params: cleanedParams, json: true, }; + // Only add params if they exist + if (cleanedParams !== undefined) { + queryOptions.params = cleanedParams; + } + // Add types if provided if (types) { queryOptions.types = types; @@ -674,10 +687,14 @@ export class SpannerAdapter implements DatabaseAdapter { try { const queryOptions: any = { sql, - params: cleanedParams, json: true, }; + // Only add params if they exist + if (cleanedParams !== undefined) { + queryOptions.params = cleanedParams; + } + // Add types if provided if (types) { queryOptions.types = types; @@ -753,9 +770,13 @@ export class SpannerAdapter implements DatabaseAdapter { const updateOptions: any = { sql: sqlCmd, - params: cleanedParams, }; + // Only add params if they exist + if (cleanedParams !== undefined) { + updateOptions.params = cleanedParams; + } + // Add types if provided if (types) { updateOptions.types = types; @@ -789,10 +810,14 @@ export class SpannerAdapter implements DatabaseAdapter { const queryOptions: any = { sql: sqlQuery, - params: cleanedParams, json: true, }; + // Only add params if they exist + if (cleanedParams !== undefined) { + queryOptions.params = cleanedParams; + } + // Add types if provided if (types) { queryOptions.types = types; @@ -852,9 +877,13 @@ export class SpannerAdapter implements DatabaseAdapter { const updateOptions: any = { sql: cmdSql, - params: cleanedParams, }; + // Only add params if they exist + if (cleanedParams !== undefined) { + updateOptions.params = cleanedParams; + } + // Add types if provided if (types) { updateOptions.types = types; @@ -885,10 +914,14 @@ export class SpannerAdapter implements DatabaseAdapter { const queryOptions: any = { sql: querySql, - params: cleanedParams, json: true, }; + // Only add params if they exist + if (cleanedParams !== undefined) { + queryOptions.params = cleanedParams; + } + // Add types if provided if (types) { queryOptions.types = types; diff --git a/test/spanner/adapter-type-hints.test.ts b/test/spanner/adapter-type-hints.test.ts index 4827786..1a4e004 100644 --- a/test/spanner/adapter-type-hints.test.ts +++ b/test/spanner/adapter-type-hints.test.ts @@ -112,6 +112,8 @@ class TestableSpannerAdapter { if (!params) return undefined; const cleaned: Record = {}; + let hasKeys = false; + for (const key in params) { if (Object.prototype.hasOwnProperty.call(params, key)) { const hint = typeHints?.[key]; @@ -121,9 +123,12 @@ class TestableSpannerAdapter { } else { cleaned[key] = params[key]; } + hasKeys = true; } } - return cleaned; + + // Return undefined if params is empty to avoid sending empty object to Spanner + return hasKeys ? cleaned : undefined; } // Helper function to automatically infer Spanner types from JavaScript values @@ -213,10 +218,14 @@ class TestableSpannerAdapter { const queryOptions: any = { sql, - params: cleanedParams, json: true, }; + // Only add params if they exist + if (cleanedParams !== undefined) { + queryOptions.params = cleanedParams; + } + // Add types if provided or inferred if (mergedHints) { queryOptions.types = mergedHints; @@ -244,9 +253,13 @@ class TestableSpannerAdapter { async (transaction: any) => { const updateOptions: any = { sql, - params: cleanedParams, }; + // Only add params if they exist + if (cleanedParams !== undefined) { + updateOptions.params = cleanedParams; + } + // Add types if provided or inferred if (mergedHints) { updateOptions.types = mergedHints; @@ -278,10 +291,14 @@ class TestableSpannerAdapter { async (transaction: any) => { const queryOptions: any = { sql, - params: cleanedParams, json: true, }; + // Only add params if they exist + if (cleanedParams !== undefined) { + queryOptions.params = cleanedParams; + } + // Add types if provided or inferred if (mergedHints) { queryOptions.types = mergedHints; @@ -311,9 +328,13 @@ class TestableSpannerAdapter { const cleanedParams = this.cleanParamsForSpanner(paramsCmd, mergedHints); const updateOptions: any = { sql: sqlCmd, - params: cleanedParams, }; + // Only add params if they exist + if (cleanedParams !== undefined) { + updateOptions.params = cleanedParams; + } + if (mergedHints) { updateOptions.types = mergedHints; updateOptions.paramTypes = mergedHints; @@ -331,10 +352,14 @@ class TestableSpannerAdapter { const cleanedParams = this.cleanParamsForSpanner(paramsQuery, mergedHints); const queryOptions: any = { sql: sqlQuery, - params: cleanedParams, json: true, }; + // Only add params if they exist + if (cleanedParams !== undefined) { + queryOptions.params = cleanedParams; + } + if (mergedHints) { queryOptions.types = mergedHints; queryOptions.paramTypes = mergedHints; @@ -368,9 +393,13 @@ class TestableSpannerAdapter { const cleanedParams = this.cleanParamsForSpanner(cmdParams, mergedHints); const updateOptions: any = { sql: cmdSql, - params: cleanedParams, }; + // Only add params if they exist + if (cleanedParams !== undefined) { + updateOptions.params = cleanedParams; + } + if (mergedHints) { updateOptions.types = mergedHints; updateOptions.paramTypes = mergedHints; @@ -388,10 +417,14 @@ class TestableSpannerAdapter { const cleanedParams = this.cleanParamsForSpanner(queryParams, mergedHints); const queryOptions: any = { sql: querySql, - params: cleanedParams, json: true, }; + // Only add params if they exist + if (cleanedParams !== undefined) { + queryOptions.params = cleanedParams; + } + if (mergedHints) { queryOptions.types = mergedHints; queryOptions.paramTypes = mergedHints;