Skip to content

Commit 452ffdd

Browse files
authored
Fix calling stored procs on Postgres, and enable some tests (#2308)
1 parent 3e6f9b3 commit 452ffdd

File tree

3 files changed

+30
-71
lines changed

3 files changed

+30
-71
lines changed

foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/databaseaccess/DatabasePlatform.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
2-
* Copyright (c) 1998, 2022 Oracle and/or its affiliates. All rights reserved.
3-
* Copyright (c) 2019, 2022 IBM Corporation. All rights reserved.
2+
* Copyright (c) 1998, 2024 Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2019, 2024 IBM Corporation. All rights reserved.
44
*
55
* This program and the accompanying materials are made available under the
66
* terms of the Eclipse Public License v. 2.0 which is available at
@@ -1443,6 +1443,7 @@ public boolean isInformixOuterJoin() {
14431443
*
14441444
* @see PostgreSQLPlatform
14451445
*/
1446+
@Deprecated(forRemoval = true)
14461447
public boolean isJDBCExecuteCompliant() {
14471448
return true;
14481449
}

foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/platform/database/PostgreSQLPlatform.java

+10-62
Original file line numberDiff line numberDiff line change
@@ -305,20 +305,6 @@ public boolean shouldPrintOutputTokenAtStart() {
305305
return true;
306306
}
307307

308-
/**
309-
* Calling a stored procedure query on PostgreSQL with no output parameters
310-
* always returns true from an execute call regardless if a result set is
311-
* returned or not. This flag will help avoid throwing a JPA mandated
312-
* exception on an executeUpdate call (which calls jdbc execute and checks
313-
* the return value to ensure no results sets are returned (true))
314-
*
315-
* @see PostgreSQLPlatform
316-
*/
317-
@Override
318-
public boolean isJDBCExecuteCompliant() {
319-
return false;
320-
}
321-
322308
/**
323309
* INTERNAL: Answers whether platform is Postgres.
324310
*/
@@ -522,63 +508,25 @@ public int getMaxFieldNameSize() {
522508
*/
523509
@Override
524510
public String getProcedureBeginString() {
525-
return "AS $$ BEGIN ";
511+
return "$$ BEGIN ";
526512
}
527513

528514
/**
529515
* INTERNAL: Used for sp calls.
530516
*/
531517
@Override
532518
public String getProcedureEndString() {
533-
return "; END ; $$ LANGUAGE plpgsql;";
534-
}
535-
536-
/**
537-
* INTERNAL: Used for sp calls. PostGreSQL uses a different method for executing StoredProcedures than other platforms.
538-
*/
539-
@Override
540-
public String buildProcedureCallString(StoredProcedureCall call, AbstractSession session, AbstractRecord row) {
541-
StringWriter tailWriter = new StringWriter();
542-
StringWriter writer = new StringWriter();
543-
boolean outParameterFound = false;
544-
545-
tailWriter.write(call.getProcedureName());
546-
tailWriter.write("(");
547-
548-
int indexFirst = call.getFirstParameterIndexForCallString();
549-
int size = call.getParameters().size();
550-
String nextBindString = "?";
551-
552-
for (int index = indexFirst; index < size; index++) {
553-
String name = call.getProcedureArgumentNames().get(index);
554-
Object parameter = call.getParameters().get(index);
555-
ParameterType parameterType = call.getParameterTypes().get(index);
556-
// If the argument is optional and null, ignore it.
557-
if (!call.hasOptionalArguments() || !call.getOptionalArguments().contains(parameter) || (row.get(parameter) != null)) {
558-
if (!DatasourceCall.isOutputParameterType(parameterType)) {
559-
tailWriter.write(nextBindString);
560-
nextBindString = ", ?";
561-
} else {
562-
if (outParameterFound) {
563-
//multiple outs found
564-
throw ValidationException.multipleOutParamsNotSupported(Helper.getShortClassName(this), call.getProcedureName());
565-
}
566-
outParameterFound = true; //PostGreSQL uses a very different header to execute when there are out params
567-
}
568-
}
569-
}
570-
tailWriter.write(")");
571-
572-
if (outParameterFound) {
573-
writer.write("{?= CALL ");
574-
tailWriter.write("}");
575-
} else {
576-
writer.write("SELECT * FROM ");
577-
}
578-
writer.write(tailWriter.toString());
519+
return "END; $$ LANGUAGE plpgsql;";
520+
}
579521

580-
return writer.toString();
522+
/**
523+
* INTERNAL: Used for sp calls.
524+
*/
525+
@Override
526+
public String getProcedureCallHeader() {
527+
return "CALL ";
581528
}
529+
582530
/**
583531
* INTERNAL Used for stored function calls.
584532
*/

jpa/eclipselink.jpa.test.jse/src/it/java/org/eclipse/persistence/jpa/test/storedproc/TestStoredProcedures.java

+17-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2020 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2024 Oracle and/or its affiliates. All rights reserved.
33
* Copyright (c) 2019 IBM Corporation. All rights reserved.
44
*
55
* This program and the accompanying materials are made available under the
@@ -30,6 +30,7 @@
3030
import org.eclipse.persistence.jpa.test.framework.Property;
3131
import org.eclipse.persistence.platform.database.DatabasePlatform;
3232
import org.eclipse.persistence.sessions.DatabaseSession;
33+
import org.eclipse.persistence.tools.schemaframework.FieldDefinition;
3334
import org.eclipse.persistence.tools.schemaframework.SchemaManager;
3435
import org.eclipse.persistence.tools.schemaframework.StoredProcedureDefinition;
3536

@@ -121,6 +122,8 @@ public void testStoredProcedure_SetUnordered_IndexParameters() {
121122
*/
122123
@Test
123124
public void testStoredProcedure_SetOrdered_NamedParameters() {
125+
Assume.assumeFalse("pgjdbc does not support named parameters", getPlatform(storedProcedureEmf).isPostgreSQL());
126+
124127
EntityManager em = storedProcedureEmf.createEntityManager();
125128
try {
126129
StoredProcedureQuery storedProcedure = em.createStoredProcedureQuery("simple_order_procedure");
@@ -152,6 +155,8 @@ public void testStoredProcedure_SetOrdered_NamedParameters() {
152155
*/
153156
@Test
154157
public void testStoredProcedure_SetUnordered_NamedParameters() {
158+
Assume.assumeFalse("pgjdbc does not support named parameters", getPlatform(storedProcedureEmf).isPostgreSQL());
159+
155160
EntityManager em = storedProcedureEmf.createEntityManager();
156161
try {
157162
StoredProcedureQuery storedProcedure = em.createStoredProcedureQuery("simple_order_procedure");
@@ -186,22 +191,27 @@ private static boolean createSimpleStoredProcedure(EntityManagerFactory emf) {
186191
//Setup a stored procedure
187192
EntityManager em = emf.createEntityManager();
188193
try {
194+
DatabaseSession dbs = ((EntityManagerImpl)em).getDatabaseSession();
195+
SchemaManager manager = new SchemaManager(dbs);
196+
Platform platform = dbs.getDatasourcePlatform();
197+
189198
StoredProcedureDefinition proc = new StoredProcedureDefinition();
190199
proc.setName("simple_order_procedure");
191200

192201
proc.addArgument("in_param_one", String.class, 10);
193202
proc.addArgument("in_param_two", String.class, 10);
194203
proc.addArgument("in_param_three", String.class, 10);
195-
proc.addOutputArgument("out_param_one", String.class, 30);
196-
197-
DatabaseSession dbs = ((EntityManagerImpl)em).getDatabaseSession();
198-
SchemaManager manager = new SchemaManager(dbs);
199-
Platform platform = dbs.getDatasourcePlatform();
204+
if (platform.isPostgreSQL()) {
205+
// PG only supports OUT in 14+
206+
proc.addInOutputArgument(new FieldDefinition("out_param_one", String.class, 30));
207+
} else {
208+
proc.addOutputArgument("out_param_one", String.class, 30);
209+
}
200210

201211
//Add more platform specific diction to support more platforms
202212
if(platform.isMySQL()) {
203213
proc.addStatement("SET out_param_one = CONCAT('One: ',in_param_one,' Two: ',in_param_two,' Three: ',in_param_three)");
204-
} else if(platform.isOracle()) {
214+
} else if(platform.isOracle() || platform.isPostgreSQL()) {
205215
proc.addStatement("out_param_one := 'One: ' || in_param_one || ' Two: ' || in_param_two || ' Three: ' || in_param_three");
206216
} else if (platform.isDB2() || platform.isDB2Z()) {
207217
proc.addStatement("SET out_param_one = 'One: ' || in_param_one || ' Two: ' || in_param_two || ' Three: ' || in_param_three");

0 commit comments

Comments
 (0)