Skip to content

Commit 0d60086

Browse files
committed
fix(postgres): normalize cast shorthand in default expressions
1 parent e00696c commit 0d60086

2 files changed

Lines changed: 44 additions & 3 deletions

File tree

models/Grammars/PostgresGrammar.cfc

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -339,14 +339,32 @@ component extends="qb.models.Grammars.BaseGrammar" singleton {
339339
}
340340

341341
function wrapDefaultType( column ) {
342+
var defaultValue = column.getDefaultValue();
343+
// Normalize PostgreSQL cast shorthand (value::TYPE) so runtimes that
344+
// parse ":" for named params don't break schema DDL execution.
345+
var castPosition = 0;
346+
for ( var i = len( defaultValue ) - 1; i >= 1; i-- ) {
347+
if ( mid( defaultValue, i, 2 ) == "::" ) {
348+
castPosition = i;
349+
break;
350+
}
351+
}
352+
if ( castPosition > 0 ) {
353+
var valuePart = trim( left( defaultValue, castPosition - 1 ) );
354+
var typePart = trim( mid( defaultValue, castPosition + 2, len( defaultValue ) ) );
355+
if ( typePart != "" ) {
356+
defaultValue = "CAST(#valuePart# AS #typePart#)";
357+
}
358+
}
359+
342360
switch ( column.getType() ) {
343361
case "boolean":
344-
return uCase( column.getDefaultValue() );
362+
return uCase( defaultValue );
345363
case "char":
346364
case "string":
347-
return "'#column.getDefaultValue()#'";
365+
return "'#defaultValue#'";
348366
default:
349-
return column.getDefaultValue();
367+
return defaultValue;
350368
}
351369
}
352370

tests/specs/Schema/PostgresSchemaBuilderSpec.cfc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
11
component extends="tests.resources.AbstractSchemaBuilderSpec" {
22

3+
function run() {
4+
super.run();
5+
6+
describe( "postgres specific behavior", function() {
7+
it( "normalizes cast shorthand in default expressions", function() {
8+
testCase( function( schema ) {
9+
return schema.create(
10+
"expenses",
11+
function( table ) {
12+
table.jsonb( "extracted_data" ).default( "'{}'::JSONB" );
13+
},
14+
{},
15+
false
16+
);
17+
}, defaultForJsonbCastShorthand() );
18+
} );
19+
} );
20+
}
21+
322
function emptyTable() {
423
return [ "CREATE TABLE ""users"" ()" ];
524
}
@@ -636,6 +655,10 @@ component extends="tests.resources.AbstractSchemaBuilderSpec" {
636655
return [ "CREATE TABLE ""active_users"" AS (SELECT * FROM ""users"" WHERE ""active"" = ?)" ];
637656
}
638657

658+
function defaultForJsonbCastShorthand() {
659+
return [ "CREATE TABLE ""expenses"" (""extracted_data"" JSONB NOT NULL DEFAULT CAST('{}' AS JSONB))" ];
660+
}
661+
639662
private function getBuilder( mockGrammar ) {
640663
var utils = getMockBox().createMock( "qb.models.Query.QueryUtils" );
641664
arguments.mockGrammar = isNull( arguments.mockGrammar ) ? getMockBox()

0 commit comments

Comments
 (0)