From 8fa41ee8efd7eec639245649ac72e4022553683e Mon Sep 17 00:00:00 2001 From: Suyog Sonwalkar Date: Sat, 30 Aug 2025 09:50:29 -0700 Subject: [PATCH] More adapter fixes Summary: Test Plan: --- src/spanner/adapter.ts | 25 ++++++++++- tasks/fix-code-error.md | 98 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 tasks/fix-code-error.md diff --git a/src/spanner/adapter.ts b/src/spanner/adapter.ts index acb2c30..c6ffae6 100644 --- a/src/spanner/adapter.ts +++ b/src/spanner/adapter.ts @@ -115,6 +115,29 @@ function mapDdlTypeToSpannerCode(ddlType: string): string { return "STRING"; } +// Helper function to map type string to Spanner TypeCode enum number +function getSpannerTypeCodeEnum(typeString: string): number { + const typeCodeMap: Record = { + 'BOOL': 1, + 'INT64': 2, + 'FLOAT64': 3, + 'TIMESTAMP': 4, + 'DATE': 5, + 'STRING': 6, + 'BYTES': 7, + 'ARRAY': 8, + 'STRUCT': 9, + 'NUMERIC': 10, + 'JSON': 11, + 'PROTO': 13, + 'ENUM': 14, + 'FLOAT32': 15, + 'INTERVAL': 16, + 'UUID': 17, + }; + return typeCodeMap[typeString] || 6; // Default to STRING (6) if unknown +} + // Helper function to transform DDL hints to Spanner paramTypes object function transformDdlHintsToParamTypes( ddlHints?: Record @@ -129,7 +152,7 @@ function transformDdlHintsToParamTypes( // Construct an object conforming to our local SpannerParamType interface, // which is structurally compatible with google.spanner.v1.IType. paramTypes[key] = { - code: typeCodeString, // mapDdlTypeToSpannerCode returns a string like "STRING" + code: getSpannerTypeCodeEnum(typeCodeString), // Use numeric TypeCode enum value arrayElementType: null, // Assuming scalar types for now structType: null, // Assuming scalar types for now }; diff --git a/tasks/fix-code-error.md b/tasks/fix-code-error.md new file mode 100644 index 0000000..25f4957 --- /dev/null +++ b/tasks/fix-code-error.md @@ -0,0 +1,98 @@ +# Fix Spanner Migration Error: "The code field is required for types" ✅ FIXED + +## Error Description +When running migrations with Spanner adapter, the following error occurs: +``` +Ensuring migration tracking table 'spanner_orm_migrations_log' exists... +error: 3 INVALID_ARGUMENT: The code field is required for types. +``` + +## Root Cause +The error occurs when querying the INFORMATION_SCHEMA.TABLES to check if the migration table exists. The Spanner adapter's `transformDdlHintsToParamTypes` function was incorrectly setting the `code` field in the paramTypes object to a string value (e.g., "STRING") instead of the numeric TypeCode enum value that Spanner's API expects (e.g., 6 for STRING). + +## Actual Issue Location +The issue was in `/src/spanner/adapter.ts` in the `transformDdlHintsToParamTypes` function at line 152-153. + +## Problem Analysis +The error "The code field is required for types" was happening because: + +1. When the migration runner queries INFORMATION_SCHEMA.TABLES with a parameter `@tableName` +2. The Spanner adapter automatically infers the type as "STRING" +3. The `transformDdlHintsToParamTypes` function was incorrectly setting `code: "STRING"` (a string) +4. Spanner's API expects `code: 6` (the numeric TypeCode enum value for STRING) + +## Solution Implemented + +Added a new helper function `getSpannerTypeCodeEnum` in `/src/spanner/adapter.ts` that maps type strings to their numeric TypeCode enum values: + +```typescript +// Helper function to map type string to Spanner TypeCode enum number +function getSpannerTypeCodeEnum(typeString: string): number { + const typeCodeMap: Record = { + 'BOOL': 1, + 'INT64': 2, + 'FLOAT64': 3, + 'TIMESTAMP': 4, + 'DATE': 5, + 'STRING': 6, + 'BYTES': 7, + 'ARRAY': 8, + 'STRUCT': 9, + 'NUMERIC': 10, + 'JSON': 11, + 'PROTO': 13, + 'ENUM': 14, + 'FLOAT32': 15, + 'INTERVAL': 16, + 'UUID': 17, + }; + return typeCodeMap[typeString] || 6; // Default to STRING (6) if unknown +} +``` + +Then updated the `transformDdlHintsToParamTypes` function to use numeric values: + +```typescript +paramTypes[key] = { + code: getSpannerTypeCodeEnum(typeCodeString), // Use numeric TypeCode enum value + arrayElementType: null, + structType: null, +}; +``` + +### TypeCode Enum Values Reference +Based on the official Google Spanner proto definition: +- TYPE_CODE_UNSPECIFIED = 0 +- BOOL = 1 +- INT64 = 2 +- FLOAT64 = 3 +- TIMESTAMP = 4 +- DATE = 5 +- STRING = 6 +- BYTES = 7 +- ARRAY = 8 +- STRUCT = 9 +- NUMERIC = 10 +- JSON = 11 +- PROTO = 13 +- ENUM = 14 +- FLOAT32 = 15 +- INTERVAL = 16 +- UUID = 17 + +## Testing Fix +1. Delete the existing migrations log table if it exists +2. Run migrations again with the fixed code +3. Verify the table is created successfully +4. Check that migration records are inserted properly + +## Related Files to Check +- Migration runner implementation +- Spanner adapter DDL generation +- Type mapping utilities +- Migration log table schema definition + +## Notes +- This issue only affects Spanner, not PostgreSQL/PGLite +- The error occurs during table creation, not data insertion +- Spanner is strict about type definitions and doesn't accept undefined/missing type information \ No newline at end of file